Blog - 最新エントリー

画像サイズをまとめちゃいます。

カテゴリ : 
Android » Tips
執筆 : 
NickQ 2013-1-24 9:45

画面の解像度毎にランチャアイコンや通知アイコンを用意しますが

少し前のAndroidならそれほど解像度がずば抜けているという事は無かったんですが

最近のタブレットや4.0搭載している物などは今までの余り気に留めなかったサイズがもろに

出てしまいますそこで意外と忘れがち、な各解像度で必要なサイズをまとめました

(若干サイズが違うのは私の主観もあります)

 

   drawable-hdpi  drawable-mdpi drawable-ldpi  drawable-xhdpi 

ランチャー 

 72*72  48*48  32*32  98*98

通知

 38*38  25*25  19*19  50*50

 

drawable-nodpi はそれぞれ解像度判断されない画像を格納する(ただしストレッチさせると画面に合わせて縮小拡大する)

 

  • コメント (0)
  • トラックバック (0)
  • 閲覧 (2727)
 Google Cloud Messaging for Android (GCM)今更ながら調査の為、触ってみた。
ついでにGoogle App Engine(GAE)での開発にも少し手を入れようと考えてサーバ側の環境は
GAEで作ってみる事にした。
 
アプリの概要はこんな感じ
 
簡単に言うとオンラインのクリップボードを考えていて
Androidアプリにて端末からGAEのサーバアプリにGCMのIDを登録する。
PC側からコピー動作を行ったらGAEサーバへPOSTして
GAEサーバで受けたPOSTにて対象Android端末へ通知を行う。
 
URLやMailアドレスなどだった場合、Android側で即表示可能にする。
通常受信したデータはAndroid端末のクリップボードに張り付けて利用可能にする。
 
その際に、PCからショートカット(Ctrl + Alt + C)で一発で飛ばしたい!(Winに限る)
ブラウザからも同じ事がしたい。
 
どこに使うのか?
 
PCで見ていたアドレスをAndroid端末に渡してみたい場合
・自分の場合は、技術文献など隣に置いたタブレットに飛ばしてPCで開発、タブレットで読む
 
Androidにしか設定していないメールアカウントで長文メールを打ちたいけど面倒な場合
・PCで長文打ってAndroid端末のクリップボードでペーストする(誤字脱字軽減)
 
PCで受信してしまったメールにヤマト伝票番号が有ってそれを端末に飛ばしたい場合
・メールでも可能ですが、ショートカットで一発で送りたい

などなど。

そして作りました。

PC側は流石に、VisualStudioで作りこんでいます。

なかなか快適にオンラインクリップボード出来ますが

GAEが重量課金の為、リリース無料でやるのはちょっと厳しい。

月額にして使ってくれるんだろうか、悩むところ。

寄付もまた微妙だし。

こんな追加機能付けたら行けるだろうか

・特定のパスワードをコピーすると、振動や音で居場所を知らせてくれる(無くした時の発見対策)

GPS起動して座標特定するとか。

・特定のコマンドをコピーすると、写真を撮るとか(画像送信未対応ですが)

・画像のやり取りに対応するとか。

アプリは出来てるんだけど、これは身内で使うかな。

  • コメント (0)
  • トラックバック (0)
  • 閲覧 (4509)

以前、自作ArrayAdapterをListViewにセットして

onListItemClickが発生しない場合の方法を投稿していたがそれでも発生しない場合

(ListActivityで無い場合など)

の対策方法として

ArrayAdapter側のgetViewでView自体にOnClickListenerを設定すると

Activity側のsetOnItemClickListenerが呼ばれる様になる方法を紹介します。

Activity側

onCreateなどで

 

   mListView = (ListView) findViewById(R.id.list);
   list = new ArrayList();
   list = dataSet(this); //<-データをセットする
   adapter = new CustomAdapter(this, R.layout.item, list);
   mListView .setAdapter(adapter);
   registerForContextMenu(mListView );
   //アイテムクリック
   mListView .setOnItemClickListener(new AdapterView.OnItemClickListener() {
     @Override
     public void onItemClick(AdapterView arg0, View arg1,int position,      long arg3) {
       Toast.makeText(getBaseContext(), list.get(position).getPointLocation(), Toast.LENGTH_SHORT).show();
       return;
     }
   });

 

ArrayAdapterのgetViewで

 

 public View getView(final int position, View convertView, final ViewGroup parent) {
   view = inflater.inflate(R.layout.list_item, parent, false);
   view.setOnClickListener(new OnClickListener(){
    public void onClick(View v){
     ((ListView) parent).performItemClick(v, position, (long)0);
    }
   });
 }

 

とすると発生する様になります。

 

 

  • コメント (0)
  • トラックバック (0)
  • 閲覧 (4125)

TextView複数行でのEllipsizing

カテゴリ : 
Android » 開発
執筆 : 
NickQ 2012-10-15 14:38

TextViewで便利なのはEllipsizingです。

文字列が長ければ末尾に...を付けたり、中間を...に置き換えたりと

いろいろ自動でやってくれますが、これはSingleLineに限っての事

複数行の最後を...に置き換える事は出来ません、検索してもバグなのか仕様なのか

実現する必要性が有ったので、とりあえずTextViewをExtendsして作ってみた

(外国のサイトを参考に修正)

※動作を保障する物ではありません。

 

public class EllipsizingTextView extends TextView {
  private static final String ELLIPSIS = "…";
  private static final Pattern DEFAULT_END_PUNCTUATION = Pattern.compile("[\\.,…;\\:\\s]*$", Pattern.DOTALL);
  public interface EllipsizeListener {
    void ellipsizeStateChanged(boolean ellipsized);
  }
  private final List<EllipsizeListener> ellipsizeListeners = new ArrayList<EllipsizeListener>();
  private boolean isEllipsized;
  private boolean isStale;
  private boolean programmaticChange;
  private String fullText;
  private int maxLines;
  private float lineSpacingMultiplier = 1.0f;
  private float lineAdditionalVerticalPadding = 0.0f;
  /**
   * The end punctuation which will be removed when appending #ELLIPSIS.
   */
  //private Pattern endPunctuationPattern;
  public EllipsizingTextView(Context context) {
    this(context, null);
  }
  public EllipsizingTextView(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
  }
  public EllipsizingTextView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    super.setEllipsize(null);
    TypedArray a = context.obtainStyledAttributes(attrs, new int[] { android.R.attr.maxLines });
    setMaxLines(a.getInt(0, Integer.MAX_VALUE));
    setEndPunctuationPattern(DEFAULT_END_PUNCTUATION);
  }
  public void setEndPunctuationPattern(Pattern pattern) {
    //this.endPunctuationPattern = pattern;
  }
  public void addEllipsizeListener(EllipsizeListener listener) {
    if (listener == null) {
      throw new NullPointerException();
    }
    ellipsizeListeners.add(listener);
  }
  public void removeEllipsizeListener(EllipsizeListener listener) {
    ellipsizeListeners.remove(listener);
  }
  public boolean isEllipsized() {
    return isEllipsized;
  }
  @Override
  public void setMaxLines(int maxLines) {
    super.setMaxLines(maxLines);
    this.maxLines = maxLines;
    isStale = true;
  }
  public int getMaxLines() {
    return maxLines;
  }
  public boolean ellipsizingLastFullyVisibleLine() {
    return maxLines == Integer.MAX_VALUE;
  }
  @Override
  public void setLineSpacing(float add, float mult) {
    this.lineAdditionalVerticalPadding = add;
    this.lineSpacingMultiplier = mult;
    super.setLineSpacing(add, mult);
  }
  @Override
  protected void onTextChanged(CharSequence text, int start, int before,
      int after) {
    super.onTextChanged(text, start, before, after);
    if (!programmaticChange) {
        fullText = text.toString();
      isStale = true;
    }
  }
  @Override
  protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    if (ellipsizingLastFullyVisibleLine()) {
      isStale = true;
    }
  }
  public void setPadding(int left, int top, int right, int bottom) {
    super.setPadding(left, top, right, bottom);
    if (ellipsizingLastFullyVisibleLine()) {
      isStale = true;
    }
  }
  @Override
  protected void onDraw(Canvas canvas) {
    if (isStale) {
      resetText();
    }
    super.onDraw(canvas);
  }
  private void resetText() {
   //String workingText = fullText;
   StringBuilder workingText = new StringBuilder(fullText);
   boolean ellipsized = false;
   Layout layout = createWorkingLayout(fullText);
   //Layout layout = createWorkingLayout(workingText);
   int linesCount = getLinesCount();
   if (layout.getLineCount() > linesCount) {
    // We have more lines of text than we are allowed to display.
    //workingText = fullText.substring(0, layout.getLineEnd(linesCount - 1)).trim();
    workingText = new StringBuilder(fullText.substring(0, layout.getLineEnd(linesCount - 1)));
    //workingText = fullText.substring(0, layout.getLineEnd(linesCount - 1));
    while (createWorkingLayout(workingText.toString() + ELLIPSIS).getLineCount() > linesCount) {
     //int lastSpace = workingText.lastIndexOf(' ');
     // int lastSpace = workingText.length() - 1;
     //if (lastSpace == -1) {
     if ((workingText.length() - 1) == -1) {
      break;
     }
     //workingText = workingText.substring(0, lastSpace - 1);
     workingText.delete(workingText.length() - 1, workingText.length());
    }
    // We should do this in the loop above, but it's cheaper this way.
    if(workingText.length() > 2){
     //workingText = workingText.substring(0, workingText.length() - 2);
     workingText.delete(workingText.length() - 2,workingText.length());
    }
    //workingText = endPunctuationPattern.matcher(workingText).replaceFirst("");
    //workingText = workingText + ELLIPSIS;
    //workingText = new StringBuilder(endPunctuationPattern.matcher(workingText.toString()).replaceFirst(""));
    workingText.append(ELLIPSIS);
    ellipsized = true;
   }
   if (!workingText.equals(getText())) {
    programmaticChange = true;
    try {
     setText(workingText);
    } finally {
     programmaticChange = false;
    }
   }
   isStale = false;
   if (ellipsized != isEllipsized) {
    isEllipsized = ellipsized;
    for (EllipsizeListener listener : ellipsizeListeners) {
     listener.ellipsizeStateChanged(ellipsized);
    }
   }
  }
  /**
   * Get how many lines of text we are allowed to display.
   */
  private int getLinesCount() {
    if (ellipsizingLastFullyVisibleLine()) {
      int fullyVisibleLinesCount = getFullyVisibleLinesCount();
      if (fullyVisibleLinesCount == -1) {
        return 1;
      } else {
        return fullyVisibleLinesCount;
      }
    } else {
      return maxLines;
    }
  }
  /**
   * Get how many lines of text we can display so their full height is visible.
   */
  private int getFullyVisibleLinesCount() {
    Layout layout = createWorkingLayout("");
    int height = getHeight() - getPaddingTop() - getPaddingBottom();
    int lineHeight = layout.getLineBottom(0);
    return height / lineHeight;
  }
  private Layout createWorkingLayout(String workingText) {
    return new StaticLayout(workingText, getPaint(),
        getWidth() - getPaddingLeft() - getPaddingRight(),
        Alignment.ALIGN_NORMAL, lineSpacingMultiplier,
        lineAdditionalVerticalPadding, false /* includepad */);
  }
  @Override
  public void setEllipsize(TruncateAt where) {
    // Ellipsize settings are not respected
  }
}

 

resetText()では表示時に表示対象の文字列を抜き出して後ろに...を足しています。

ただ、正確には日本語の場合フォントで比率などの計算をしないとずれるので2文字分引いている。

とりあえず動いたが、処理が遅いのでリファクタリングが必要かな。

※ご利用は自己責任で。

  • コメント (0)
  • トラックバック (0)
  • 閲覧 (23365)

文字列のNullまたはlength0の判断

カテゴリ : 
Android
執筆 : 
NickQ 2012-8-28 13:59

コーディングしていると普通に

 

if(str != null){

}

 

if(str.length() > 0){

}

などで文字列を判断していますが、上記だと””が引っかからないなど

if文を二重にしたりしていませんか?(null判断とlengthは同じifにかけられません)

そこで便利なのが

TextUtils.isEmpty(str)

Nullもlength 0も同時に判断してくれます、もちろんnullもしくはlength=0ならtrueが返ります。

もう少し早く気付けば良かった。。。

  • コメント (0)
  • トラックバック (0)
  • 閲覧 (2395)

Androidで開発していると何かとListActivityを使いますが、画像を入れたり

ちょっとカッコよく表示したり、自作のLayoutを使いたくなります。

 

そこで、ArrayAdapterを作ってListActivityにセットしてさあと思いきやいくらクリックしても

onListItemClickが発生しないという事態になる方も多いはず。

 

原因は、ListActivityのItemにArrayAdapterが紐づいている訳ですので

ArrayAdapterで発生しない限り、ListActivityには通知されません。

 

そこで、発生させる方法として・・・

 

ArrayAdapter側に「OnClickListener」をインプリメントして「onClick」メソッドを追加します。

すると、ListActivityの「onListItemClick」が発生するようになります。

 

  • コメント (0)
  • トラックバック (0)
  • 閲覧 (2605)

 

CM4IS01にBluetoothのデバイスを実装しようと思って、CyanogenModを取得しようと考えた。

ソースを取得するのにgitサーバが落ちたままなの気づかなくてかなり苦労してしまった。

 

repo syncを実行すると

android.git.kernel.org[0:149.20.77]:error=Connection refused ...

fatal:unable to connect a socket(Connection refused)

 

が発生して進まない、ポート9418が開いてないのかと思い調べるが問題無し、いろいろ調べるとサーバが落ちたままだそうで。  

ocdeaurowa.orgが非公式ミラーをしているのそちらを利用させてもらう。

 

repoで取得したManifest.xmlを編集して

 

fetch="git://android.git.kernel.org/" の行を

fetch="git://codeaurowa.org" にして更新して無事取得

 

取得には時間がかかりますけどね〜 さて、どうやってビルドしようか。

 

  • コメント (0)
  • トラックバック (0)
  • 閲覧 (5308)

Android OS

カテゴリ : 
Android » 徒然
執筆 : 
NickQ 2011-12-2 16:52

最近の端末は、2.2以降もが搭載されているのかな?

まだ、2.1以前はあるのかな

IS01は別として、Xperiaは2.1だったかないずれにせよどこから作るかちょっと悩むが

タブレットが多い昨今、レイアウト系の話を考えると2.2以降が良いのかなと考える。

  • コメント (0)
  • トラックバック (0)
  • 閲覧 (1689)

ようやく峠越し

カテゴリ : 
Android » 徒然
執筆 : 
NickQ 2011-12-1 12:05

いろいろと開発案件が乱立していて、こちらに時間を割けませんでしたが少し落ち着いたので。

MediaSwitch系列のバージョンアップ

Bluetooth系の新アプリ

のプロジェクトを開始します。

 

  • コメント (0)
  • トラックバック (0)
  • 閲覧 (2532)

Androidアプリに共有機能などを付ける際に、onCreateでUriを貰って処理を行う

なんて動作を考えたりする、という事でやってみた。

画像をUriで受け取ってUriがNullだったらToastを出して終わらせる。

ACTION_SENDが渡って来たら、外部からの共有で来ている物

そう出なければアプリケーション内から呼び出して物

 

public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

	setContentView(R.layout.action_send);

	Uri mUri = null;

        String action = getIntent().getAction();

        if (Intent.ACTION_SEND.equals(action)) {
		//ACTION_SENDで呼び出し
    		Bundle bundle = getIntent().getExtras();
        	if (bundle != null) {
        		mUri = (Uri)bundle.get(Intent.EXTRA_STREAM);
           	}
    		intent_flg = true;
        } else {
		//アプリケーション内から呼び出し
		Bundle bundle =getIntent().getExtras();
		mUri = (Uri)bundle.get("data");
    		intent_flg = false;
        }

	if(mUri == null ){
		if (Intent.ACTION_SEND.equals(action)) {
	        	Toast.makeText(getApplicationContext(),"Error", Toast.LENGTH_LONG).show();
	        	finish();
	        } else {
		//Uriから画像を読み込み、ImageViewにセットする。
			Intent intent = getIntent();
			setResult(-1, intent);
			finish();
	        }
	}
	
	//UriからBitmap抽出やCopyなど

}		
	

 

もし受け取ったUriがNullだったら、Toastを出すかSetResultでエラーを返して finish()します。  

ですが、これを実行するとエラーが発生します。

 

java.lang.RuntimeException: Unable to start activity

 

これは何故かというと 、finish()を実行した際にonDestroyが呼ばれた後にまたonCreateに戻り

finish()以降のコードが実行される為です、 onCreateが完了するとonDestroyが呼ばれて実行されます。

つまり、onDestroyはfinish()時にスケジュールされるだけだという事です。

エラーで回避したと思っていたが思わぬ処でエラーが発生しました。

その様な、ライフサイクルなのでメンバ変数などの初期化や扱いも注意しないと。

 

 

 

  • コメント (0)
  • トラックバック (0)
  • 閲覧 (7872)
メインメニュー

ログイン
ユーザー名:

パスワード:


SSL パスワード紛失


カテゴリ一覧

アーカイブ

Books