!!!Android Tips

[Android][Java][Eclipse]

!!!概要
!!ブログ
*[記事一覧|http://typea.info/portal/android/android.html]

!!書籍
*[Android 書籍レビュー|http://typea.info/blg/glob/2010/11/android-3.html]

!!基本
*Android アプリケーション基本
!![Android 一連の手順概要|https://docs.google.com/present/view?id=dfrdwzrx_179f7w9q4ct]

*[Android 一連の手順概要|https://docs.google.com/present/view?id=dfrdwzrx_179f7w9q4ct]
*[開発環境構築簡易版|http://typea.info/blg/glob/2012/11/20-android.html]
!!インストール
![[SDKのインストール|Android SDKのインストール]]
*[[SDKのインストール|Android SDKのインストール]]
!SDK Manager に APIの一覧が表示されない場合
*Tools - Options からForce にチェックを入れ、HTTP接続を可能にする
{{ref_image android_sdk_manager.jpg}}
![[ADT Eclipse プラグイン|Android ADT Eclipse プラグイン]]
*[[ADT Eclipse プラグイン|Android ADT Eclipse プラグイン]]

!!環境構築手順
![JDKのインストールから、Eclipse の日本語化まで|http://typea.info/blg/glob/2010/12/android-1-javasdkeclipse.html]
*[JDKのインストールから、Eclipse の日本語化まで|http://typea.info/blg/glob/2010/12/android-1-javasdkeclipse.html]

![SDKのインストールから、エミュレータの作成まで|http://typea.info/blg/glob/2010/12/android-2-1.html]
*[SDKのインストールから、エミュレータの作成まで|http://typea.info/blg/glob/2010/12/android-2-1.html]


![実機デバッグ(ADBドライバのインストール)|http://typea.info/blg/glob/2010/12/android-3-adb.html]
*[実機デバッグ(ADBドライバのインストール)|http://typea.info/blg/glob/2010/12/android-3-adb.html]
*[実機デバッグ(HTC J)|http://typea.info/blg/glob/2012/07/htc-j-android.html]
*[実機デバッグ(Windows8)|http://typea.info/blg/glob/2014/01/windows-8-android.html]
![Eclipse Git プラグインの導入|http://typea.info/blg/glob/2010/12/eclipse-git.html]
*[Eclipse Git プラグインの導入|http://typea.info/blg/glob/2010/12/eclipse-git.html]

![Eclipse プロジェクトの作成とSDKソースコードをEclipseから閲覧可能に|http://typea.info/blg/glob/2011/01/android-eclipsesdk.html]
*[Eclipse プロジェクトの作成とSDKソースコードをEclipseから閲覧可能に|http://typea.info/blg/glob/2011/01/android-eclipsesdk.html]

![Ubuntuに開発環境を構築|http://typea.info/blg/glob/2011/05/ubuntu-android.html]
*[Ubuntuに開発環境を構築|http://typea.info/blg/glob/2011/05/ubuntu-android.html]

![UbuntuでADTプラグインインストールエラー|http://typea.info/blg/glob/2011/11/ubuntu-android-adt-svn.html]
*[UbuntuでADTプラグインインストールエラー|http://typea.info/blg/glob/2011/11/ubuntu-android-adt-svn.html]
!Ubuntu ADBドライバに実機を認識させる
*[???? と認識されてしまう解決法|http://typea.info/blg/glob/2011/05/ubuntu-android.html]
*[64bit でADBドライバが利用できない解決法|http://typea.info/blg/glob/2014/01/ubuntu-1310-64bit-adtadb-android.html]
!!!開発環境
!!GAE
[Android (実機) と GAE を連携させるためのデバッグ環境を Windows7 に構築する|http://typea.info/blg/glob/2010/08/android_gae_windows7.html]
!!SDK ソースコード
::[[Gitのインストール(Linux)|CentOS 初期設定]]
 # git clone git://android.git.kernel.org/platform/frameworks/base.git

::ブラウズ
*http://android.git.kernel.org/
**[projects / platform/frameworks/base.git / tree|http://android.git.kernel.org/?p=platform/frameworks/base.git;a=tree;f=core/java/android;h=67060e03dddf2bb4fc9b98fd9aaf24a5722f7369;hb=HEAD]

::Eclipse
*[Eclipse から使用可能にする手順|http://typea.info/blg/glob/2011/01/android-eclipsesdk.html]


!!Eclipse 3.6.1 のコード補完で固まる対処
*[Eclipse 3.6のコード補完のフリーズを解消する|http://d.hatena.ne.jp/goriponsoft/20110210/1297305320]
::以下のパッチをEclipseにあてる(解凍して上書き)
*[org.eclipse.jdt.core_3.6.1.v_A68_R36x.zip|http://adt-addons.googlecode.com/svn/patches/org.eclipse.jdt.core_3.6.1.v_A68_R36x.zip]
!!!エミュレータ
!!起動時の実際のサイズを指定する
+AVD Manager から、Start the selected AVD を選択
+表示されたダイアログの Scale display to real size をチェック
+screen size にインチサイズを設定
{{ref_image android_emu.png}}

!!!画面
!!画面モード(縦、横)が変わらないように設定
http://www.hakkaku.net/articles/20090831-579

*XML の manifest/application/activity の属性、android:screenOrientation を、"portrait" に設定すると、縦画面のまま回転しなくなります。

::設定値
*"portrait" … 縦画面で固定
*"landscape" … 横画面で固定
*"unspecified" … デバイス任せ


!!画面モード(縦、横)が変わる、変わらないを動的に変更
*http://319ring.net/blog/archives/1502
 if (条件) {
     // 画面の回転を抑制(現在の向きに固定)
     Configuration config = getResources().getConfiguration();
     if (config.orientation == Configuration.ORIENTATION_PORTRAIT) {
         setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
     } else if(config.orientation == Configuration.ORIENTATION_LANDSCAPE) {
         setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
     }            
 } else {
     // 回転を可能に
     setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
 }

*逆向きにも対応版
* // @see http://stackoverflow.com/questions/2366706/how-to-lock-orientation-during-runtime
 int orientation = getActivity().getRequestedOrientation();
 int rotation = ((WindowManager) getActivity().getSystemService(
         Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();
 switch (rotation) {
 case Surface.ROTATION_0:
     orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
     break;
 case Surface.ROTATION_90:
     orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
     break;
 case Surface.ROTATION_180:
     orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
     break;
 default:
     orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
     break;
 }
 getActivity().setRequestedOrientation(orientation);

*固定解除
 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
!!画面サイズを取得する
::1
 Display display = getWindowManager().getDefaultDisplay(); 
 int width = display.getWidth();
 int height = display.getHeight();

::outSizeに格納される
 Point outSize = new Point();
 (WindowManager)getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getSize(outSize);
!!画面の向きを取得する

""API Level 8 以降は getRotation () を使うこと 0:portrait, 1:landscape
 
 Display display = getWindowManager().getDefaultDisplay(); 
 
 switch(display.getOrientation()) {
 case Surface.ROTATION_90:
 case Surface.ROTATION_270:
    // TODO
 	break;
 default:
    // TODO
 	break;
 }
!!タイトルバーを非表示に
::コード
*requestWindowFeature(Window.FEATURE_NO_TITLE)を実行
 public class ColorChoiceActivity extends Activity {
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         requestWindowFeature(Window.FEATURE_NO_TITLE);
         
         setContentView(R.layout.main);
     }
 }
::XML
*AndroidManifest.xml に指定
*タイトルバーを非表示、フルスクリーン
 <activity    :
          android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >

!!最大化表示(ステータスバーを隠す)
::コード
 getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); 
 getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);

""逆の場合、add と clear を変える
::XML
*AndroidManifest.xml に指定
*タイトルバーを非表示、フルスクリーン
 <activity    :
          android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >

!!UIについて
*[Android UI|http://android.siprop.org/index.php?plugin=attach&pcmd=open&file=AndroidUI_20090912.pdf&refer=%B5%BB%BD%D1%BB%F1%CE%C1]

*[Android風のアイコンを作成する方法|http://www.pixel-arms.com/2009/04/how_to_make_android_icon/]

!!設定画面を作成する
*[設定画面を作成する|http://typea.info/blg/glob/2010/10/android-android-hacks.html]

!!スタイル
*[[スタイル|Android スタイル]]
!!色定義を行い使用する	
::values/colos.xml を定義
 &lt;?xml version="1.0" encoding="utf-8"?&gt;
 &lt;resources&gt;
     &lt;color name="white"&gt;#FFFFFF&lt;/color&gt;
     &lt;color name="lightgrey"&gt;#C0C0C0&lt;/color&gt;
 &lt;/resources&gt;

::使い方(Activity内)
 txtHoge.setTextColor(getResources().getColor(R.color.lightgrey));

""txtHoge.setTextColor(R.color.lightgrey) とするのは、色の値として、リソースIDが渡されるためNG

!!EditText に最初にフォーカスがあたり、IMEが自動起動してしまうのを抑制
*http://goo.gl/LeFOK
 @Override
 protected void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     // EditText に最初にフォーカスがあたり、IMEが自動起動してしまうのを抑制
     getWindow().setSoftInputMode(La    outParams.SOFT_INPUT_STATE_ALWA    S_HIDDEN);
     
     setContentView(R.la    out.word_editor);

!!!App ウィジェット
!!App ウィジェットの作り方
*[App ウィジェットの作り方|http://typea.info/blg/glob/2012/05/android-app.html]
*[ボタンを押した処理を実装|http://typea.info/blg/glob/2012/05/android-app-1.html]
*[アプリに組み込む|http://typea.info/blg/glob/2012/05/android-10.html]
!!!イベント
!!EditTextの変更を検知
::[public void addTextChangedListener (TextWatcher watcher)|http://developer.android.com/reference/android/widget/TextView.html#addTextChangedListener(android.text.TextWatcher)]
 txtTitle.addTextChangedListener(new TextWatcher() {
     
     @Override
     public void onTextChanged(CharSequence s, int start, int before, int count) {
     }
     
     @Override
     public void beforeTextChanged(CharSequence s, int start, int count,int after) {
     }
     
     @Override
     public void afterTextChanged(Editable s) {
          updateHogeObject();
     }
 });

!!Activity にて戻るボタン押下を検知
 @Override
 public boolean onKeyDown(int keyCode, KeyEvent event) {
     if (keyCode == KeyEvent.KEYCODE_BACK) {
 
     }
     return super.onKeyDown(keyCode, event);
 }
!!!ダイアログ
!!確認ダイアログ
*http://developer.android.com/guide/topics/ui/dialogs.html
::ファイル削除確認
 final File file = new File(path);
       
 new AlertDialog.Builder(parent)
     .setTitle(R.string.lbl_file_delete_confirm)
     .setMessage(parent.getResources().getString(R.string.msg_file_delete_confirm, file.getName()))
     .setPositiveButton(R.string.lbl_yes, new DialogInterface.OnClickListener() {
         @Override
         public void onClick(DialogInterface dialog, int which) {
             deletreFile(file);
         }
     })
     .setNegativeButton(R.string.lbl_no, new DialogInterface.OnClickListener() {
         @Override
         public void onClick(DialogInterface dialog, int which) {
         }
     })
     .create().show();
!!オプションリストのダイアログ
     public void showSortDialog() {
         final int[] keys = {
                 MENU_SORT_BY_TITLE,
                 MENU_SORT_BY_HU_LEVEL_ASC,
                 MENU_SORT_BY_HU_LEVEL_DSC,
                 MENU_SORT_BY_CREATE_DATE
         };
         final String[] items = {
                 this.getString(R.string.lbl_sort_by_title),
                 this.getString(R.string.lbl_sort_by_hu_level_asc),
                 this.getString(R.string.lbl_sort_by_hu_level_dsc),
                 this.getString(R.string.lbl_sort_by_create_date)
         };
         
         new AlertDialog.Builder(this)
         .setTitle(R.string.lbl_sort)
         .setSingleChoiceItems(items, 0, new DialogInterface.OnClickListener() {
             @Override
             public void onClick(DialogInterface dialog, int which) {
                 sortWorkingSet(keys[which]);
                 dialog.dismiss();
             }
         })
         .setNegativeButton(R.string.lbl_cancel, new DialogInterface.OnClickListener() {
             @Override
             public void onClick(DialogInterface dialog, int which) {
                 dialog.dismiss();
             }
         })
         .show();
     }


!!プログレスダイアログ
*[非同期処理をAsyncTaskを使って行い進捗をProgressDialogに表示する|http://typea.info/blg/glob/2011/05/android-asynctaskprogressdialog.html]

!!カスタムダイアログ

 Context mContext = getApplicationContext();
 Dialog dialog = new Dialog(mContext);
 
 dialog.setContentView(R.layout.custom_dialog);
 dialog.setTitle("Custom Dialog");
 TextView text = (TextView) dialog.findViewById(R.id.text);

 dialog.show();
!!!Activity
!!同じアプリケーションのアクティビティを呼び出す
::マニフェストファイルの application セクションの中に以下を記述
 <activity android:name=".OtherActivity"/>
::インテントを利用して呼び出し
 Intent intent = new Intent(getApplicationContext(),
              OtherActivity.class);
 startActivity(intent);
""データの受け渡しには、Intent.putExtra を利用

::Activity.onCreate 
 Spinner spFontSize = (Spinner) findViewById(R.id.spn_font_size);
 ArrayAdapter<CharSequence> spFontSizeAdapter 
     = ArrayAdapter.createFromResource(this,
             R.array.ary_font_size,
             android.R.layout.simple_spinner_item);
 spFontSizeAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
 spFontSize.setAdapter(spFontSizeAdapter);
!![Activity の状態を一時的に保存する|http://typea.info/blg/glob/2010/09/androidx06ht-desire-activity-activity.html]
[Activity の状態を一時的に保存する|http://typea.info/blg/glob/2010/09/androidx06ht-desire-activity-activity.html]
!![コンフィグレーション|http://android.siprop.org/index.php?%CA%D9%B6%AF%B2%F1%2FAndroid%20SDK%20WG%20%C2%E81%B2%F3%20%A5%BB%A5%C3%A5%B7%A5%E7%A5%F3%A1%CA2008.10.25%A1%CB]
*デバイスのコンフィグレーションが変更されたら、UIはそのコンフィグレーションにマッチするように更新する必要があるため、Activitiは再スタートされる
*コンフィグレーションの変更があってもActivityの再スタートを避けたい場合、マニフェストにandroid:configChanges属性を追加
 android:configChanges="locale|orientation|"

!![ArrayAdapter に ラジオボタンを置く|http://typea.info/blg/glob/2010/09/android-arrayadapter.html]
[ArrayAdapter に ラジオボタンを置く|http://typea.info/blg/glob/2010/09/android-arrayadapter.html]

!!TabActivity(タブによるアクティビティ切り替え) サンプル
[TabActivity|http://typea.info/blg/glob/2010/11/android-tabactivity.html]
!!ListActivity(リスト表示画面)サンプル
[[ListActivity|Android スケルトン ListActivity]]
!!PreferenceActivity(設定画面の作成) サンプル
[PreferenceActivity|http://typea.info/blg/glob/2010/10/android-android-hacks.html]
!!透明なActivityを作成する
*http://stackoverflow.com/questions/2176922/how-to-create-transparent-activity-in-android
!res/values/styles.xml に以下の内容を記述
 <?xml version="1.0" encoding="utf-8"?>
 <resources>
     <style name="Theme.Transparent" parent="android:Theme">
         <item name="android:windowIsTranslucent">true</item>
         <item name="android:windowBackground">@android:color/transparent</item>
         <item name="android:windowContentOverlay">@null</item>
         <item name="android:windowNoTitle">true</item>
         <item name="android:windowIsFloating">true</item>
         <item name="android:backgroundDimEnabled">false</item>
     </style>
 </resources>
!AndroidManifest.xml のActivityのtheme属性にに以下の記述
 <activity android:name=".EditScoreActivity" android:theme="@style/Theme.Transparent"></activity>

!!Activity をダイアログとして表示する
*@android:style/Theme.Dialog を利用
 <activity android:name=".EditScoreActivity" android:theme="@android:style/Theme.Dialog"></activity>
!!!Service
!![[Service|Android Service]]
!!!Fragment
*[[Fragment|Android Fragment]]
!!サポートライブラリ(android.support.v4)でFragmentを利用する場合の注意点
*android.support.v4 のクラスを利用する
 import android.support.v4.app.Fragment;
 import android.support.v4.app.FragmentActivity;
 import android.support.v4.app.FragmentManager;
 import android.support.v4.app.FragmentStatePagerAdapter;
 import android.support.v4.view.PagerAdapter;
 import android.support.v4.view.ViewPager;
*Activity ではなく、FragmentActivityを利用する
*getFragmentManager() ではなく、getSupportFragmentManager() を利用する
*invalidateOptionsMenu() ではなく、supportInvalidateOptionsMenu() を利用する
!!!非同期処理
*[AsyncTaskを使う|http://typea.info/blg/glob/2014/02/android-asynctask.html]
!!!View

!!ListView の分離線を変更する
!XMLから
 <ListView android:id="@+id/android:list" 
           android:layout_height="wrap_content" 
	   android:layout_width="fill_parent"
	   android:divider="#D7D7D7"
           android:dividerHeight="1px">
 </ListView>

!コードから
 ListView lv = getListView(); 
 lv.setDivider(new ColorDrawable(Color.GREEN));
 lv.setDividerHeight(1);
   
!!ListViewのID
*ListViewのIDは、以下の様にする。
*TextViewは、リストがない場合
 <ListView android:id="@android:id/list" ・・・></ListView>
 <TextView android:id="@android:id/empty" ・・・></TextView>
または、
 <ListView android:id="@+id/android:list" ・・・></ListView>
 <TextView android:id="@+id/android:empty" ・・・></TextView>

!!ListViewの背景色の設定をしても、スクロールすると黒くなってしまう
 android:scrollingCache="false"
!!ListViewのスクロールバーを大きくする
*[ListViewのスクロールバーを大きくする|http://typea.info/blg/glob/2012/02/android-8.html]
!!ListViewのコンテキストメニュー選択時にアイテムを取り出す
[ListViewのコンテキストメニュー選択時にアイテムを取り出す|http://typea.info/blg/glob/2012/02/android-8.html]
!!カスタムViewを利用する
*http://developer.android.com/guide/topics/ui/custom-components.html
 <view xmlns:android="http://schemas.android.com/apk/res/android"
  class="info.typea.iromegane.ColorTile"
  android:id="@+id/col_tile" ></view>

!!カスタムViewを作成しレイアウトはXMLで行う

  public class HogeView extends LinearLayout {
      public HogeView(Context context) {
          super(context);
          
          LayoutInflater layoutInflater 
              = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
          
          View view = layoutInflater.inflate(R.layout.hoge_layout, this);
      }
  }
!!ページめくり
[ページをめくるサンプル|http://typea.info/blg/glob/2010/07/androidx06ht_desire_2.html]

!!Spinnerの使い方例
::string.xml
 <string-array name="ary_font_size">
     <item>70</item>
     <item>80</item>
     <item>90</item>
     <item>100</item>
 </string-array>

::Activity
 // フォントサイズ
 spFontSize = (Spinner) findViewById(R.id.spn_font_size);
 ArrayAdapter<CharSequence> spFontSizeAdapter 
     = ArrayAdapter.createFromResource(this,
             R.array.ary_font_size,
             android.R.layout.simple_spinner_item);
 spFontSizeAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
 spFontSize.setAdapter(spFontSizeAdapter);
 spFontSize.setPrompt(getResources().getText(R.string.lbl_font_size));
 
 for (int i=0; i<spFontSize.getCount(); i++) {
     int fs = Integer.parseInt(spFontSizeAdapter.getItem(i).toString());
     if (hogehoge.getFontSize() == fs) {
         spFontSize.setSelection(i);
         break;
     }
 }
!!ダイアログボックス
*[入力ダイアログ、確認ダイアログを共通化|http://typea.info/blg/glob/2010/07/android-x06ht-desire-1.html]
!!!検索
!![[検索インターフェースの作成|Android 検索インターフェースの作成]]
!!!ContentProvider
!!連絡先の取得と電話をかける
*[Android(X06HT Desire) 連絡先の取得と電話をかけるサンプル|http://typea.info/blg/glob/2010/06/androidx06ht-desire-1.html]

!!!プロパティ
!!単行
 android:maxLines="1"

!!!レイアウト
!!XMLからレイアウトをインスタンス化する
::SystemService を直接
 LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        
 prevView    = vi.inflate(R.layout.layout_previous,null);
 currentView = vi.inflate(R.layout.layout_current,null);
 nextView    = vi.inflate(R.layout.layout_next,null);

::SystemService を View経由
 EditText editor = (EditText) View.inflate(this, R.layout.editor_lined, null);

!!スクロールさせる
*ScrollViewを利用
 <?xml version="1.0" encoding="utf-8"?>
 <LinearLayout android:orientation="vertical"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     xmlns:android="http://schemas.android.com/apk/res/android">
 
     <ScrollView android:id="@+id/scrl_word_editor" 
         android:layout_height="wrap_content" 
         android:layout_width="match_parent">
         
         <LinearLayout android:orientation="vertical"
             android:layout_width="match_parent"
             android:layout_height="match_parent">
         
             <TextView></TextView>
             <EditText></EditText>
                   :
         </LinearLayout>
     </ScrollView>
 </LinearLayout>
!!!インテント
!!暗黙的 Intent で Twitter や Evernote と連携する
*[暗黙的 Intent で Twitter や Evernote と連携す|http://typea.info/blg/glob/2011/02/android-intent-twitter-evernote.html]
!!テキストエディタ等にファイルの処理をさせる
::setDataAndType を使って、ファイルのURIとMIMEタイプを同時に渡す
""個別に渡すと後に渡した方しか有効にならない(バグ?仕様 Android2.1 X06HT)
 File f = new File(path);
 	
 Intent intent = new Intent();
 intent.setAction(Intent.ACTION_VIEW);
 intent.setDataAndType(Uri.fromFile(f),"text/plain");
			
 startActivity(intent);

!!画像ファイルを共有する
 Intent intent = new Intent(android.content.Intent.ACTION_SEND);
 intent.setType("image/jpeg");
 intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file));
 startActivity(Intent.createChooser(intent, "title"));

!!ブラウザを開くなどURIの処理を行う
 Uri uri = Uri.parse("https://market.android.com/details?id=info.typea.eitangoroid.pro");
 
 Intent intent = new Intent(Intent.ACTION_VIEW, uri);
 context.startActivity(intent);

!!ブロードキャストされたインテントを受け取る
*[ブロードキャストされたインテントを受け取る|http://typea.info/blg/glob/2011/12/android-7.html]
!!!トースト
!トーストをカスタマイズして吹き出しをつくる
*http://typea.info/blg/glob/2013/07/-android-001.html
!!!ノーティフィケーション
!!起動しているActivityを全面に表示させる
*http://blog.livedoor.jp/ss_9/archives/1745734.html?ignore_lite
::AndroidManifest.xml
*android:launchMode="singleTop" を指定。指定しないと別のActivityが生成されてしまう。
 <activity android:name=".TimeKeeperActivity"
           android:launchMode="singleTop">
           :
::インテントを設定し、通知を行う
 Notification notification = new Notification(R.drawable.icon, 
     text, System.currentTimeMillis());
 PendingIntent contentIntent = PendingIntent.getActivity(this, 0, 
      Intent(this, TimeKeeperActivity.class), 0);
 notification.setLatestEventInfo(this, getString(R.string.msg_section_alarm),    
      text, contentIntent);
 notifManager.notify(R.string.app_name, notification);
!!!メニュー
!!Android 規定のアイコンを設定

 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
    super.onCreateOptionsMenu(menu);
    menu.add(0, MENU_ADD_NEW, 0, R.string.menu_add_new_item)
      .setIcon(android.R.drawable.ic_menu_add);
    return true;
 }

!!ListView に コンテキストメニュー(長押し)を設定
 public class SampleListActivity extends ListActivity {
     private static final int MENU_EDIT    = Menu.FIRST; 
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
                      :
         // 忘れがち
         registerForContextMenu(getListView());
     }
     @Override
     public void onCreateContextMenu(ContextMenu menu, View v,
             ContextMenuInfo menuInfo) {
         
         super.onCreateContextMenu(menu, v, menuInfo);
         menu.add(0, MENU_EDIT, 0, R.string.menu_edit);
     }
     @Override
     public boolean onContextItemSelected(MenuItem item) {
         switch(item.getItemId()) {
         case MENU_EDIT:
                :
             break;
         default:
             break;
         }
         return super.onContextItemSelected(item);
     }        
 }    
!!!パーミッション
*http://developer.android.com/reference/android/Manifest.permission.html
!!Android パーミッション
!!!assetリソース
!!assetリソースディレクトリのファイルを読む
 AssetManager am = context.getAssets();
 InputStream in = am.open("test.txt");

!!assetリソースディレクトのzipファイルを読む
 public void readZipFromAssets(String filename) {
     try {
         AssetManager am = context.getAssets();
         InputStream in = am.open(filename);
         ZipInputStream zin = new ZipInputStream(in);
         
         ZipEntry ze = null;
         while((ze = zin.getNextEntry()) != null) {
             if (ze.isDirectory()) {
                 continue;
             }
             BufferedReader reader = new BufferedReader(new InputStreamReader(zin));
             String line = null;
             while ((line = reader.readLine()) != null) {
                 Log.i(FlippadApplication.TAG, line);
             }
         }
         zin.close();
 
     } catch (IOException e) {
         // TODO Auto-generated catch block
         e.printStackTrace();
     }
 }
!!!文字列リソース
!!書式設定でXMLエラーとなる
フォーマットを行う場合、複数の%が含まれたりすると、Multiple annotations found at this エラーで、XMLが解析されない

*http://stackoverflow.com/questions/4414389/android-xml-percent-symbol
*formatted="false" を指定する
::string.xml例
 <string name="msg_location_msg" formatted="false">経度 %9.6f、緯度 %9.6f 付近のメッセージ</string>

::コード例
 String text = getContext().getString(R.string.msg_location_msg, 
    location.getLatitude(), 
    location.getLongitude()); 
!!!ファイル
!!アプリケーションのデータディレクトリ
::Context
 File targetdir = getFilesDir();
!!SDカードがマウントされているか判定
 if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
     // マウントされている				
 }
!!SDカードへ保存
::パーミッション
 android.permission.WRITE_EXTERNAL_STORAGE
::対象ディレクトリの取得
 File targetdir = Environment.getExternalStorageDirectory();

!!!データベース
!!コマンドラインからSQLを発行
*http://typea.info/blg/glob/2012/01/android-sqlite-sql.html
**エミュレータを使用する
**コマンドプロンプトのフォントおよび文字コードを変更する
 C:\Users\piroto>adb shell
 # cd /data/data/info.typea.eitangoroid.pro/databases
 cd /data/data/info.typea.eitangoroid.pro/databases
 # ls
 ls
 webviewCache.db
 FlippadDB
 webview.db
 # sqlite3 FlippadDB
 sqlite3 FlippadDB
 SQLite version 3.6.22
 Enter ".help" for instructions
 Enter SQL statements terminated with a ";"
!!!画像
!!ビットマップのサイズ変更
 Matrix matrix = new Matrix();
 float w = (float)newWidth / (float)bmp.getWidth();
 float h = (float)newHeight / (float)bmp.getHeight();
 matrix.postScale(w,h);
 bmp = Bitmap.createBitmap(bmp,0,0,bmp.getWidth(),bmp.getHeight(),matrix,true);

!!OutOfMemory
*[Bitmap.createBitmap で OutOfMemory|http://typea.info/blg/glob/2011/03/android-bitmapcreatebitmap-outofmemory.html]

!!!アイコン
![ランチャーアイコンガイドライン|http://typea.info/blg/glob/2012/03/android-9.html]
*[ランチャーアイコンガイドライン|http://typea.info/blg/glob/2012/03/android-9.html]
!!!描画
!!画面サイズの取得
*View クラスの getWidth()、getHeight()
!!文字列幅の取得
*Paint クラスの measureText() 
!!文字列の描画例
::画面中央に文字列描画
  Paint paint = new Paint();
  paint.setARGB(60, 80, 80, 80);
  paint.setTextAlign(Paint.Align.CENTER);
  paint.setTextSize(80);
  paint.setTypeface(Typeface.DEFAULT_BOLD);
  canvas.drawText(str, getWidth() / 2, getHeight() / 2, paint);

*http://wikiwiki.jp/android/?%A5%C6%A5%AD%A5%B9%A5%C8%A4%CE%C9%C1%B2%E8(FontMetrics)
{{ref_image fontmetrics.gif}}

!文字列領域の高さにより、フォントサイズを決定する
 Paint txtPaint = new Paint();
 txtPaint.setTextAlign(Paint.Align.CENTER);
 txtPaint.setStyle(Paint.Style.FILL);
 txtPaint.setAntiAlias(true);
 FontMetrics fontMetrics = null;
 for (int i=5; i<40 ; i++) {
     txtPaint.setTextSize(i);
     fontMetrics = txtPaint.getFontMetrics();
     
     if ((fontMetrics.bottom - fontMetrics.top) > baseHeight ) {
         i--;
         txtPaint.setTextSize(i);
         fontMetrics = txtPaint.getFontMetrics();
         break;
     }
 }
!!図形描画

!角が丸い図形を描画する(CornerPathEffect)
 paint.setPathEffect(new CornerPathEffect(12.0f));

!!Bitmap
!リソースからBitmapを生成し、カラーフィルターをかけてCanvasに描画
 Bitmap bmpConfig = BitmapFactory.decodeResource(getResources(), R.drawable.config);
 Paint paint = new Paint();
 paint.setColorFilter(new PorterDuffColorFilter(Color.GREEN,Mode.SRC_IN));
 float bmpConfigTop    = blindTop + iconMargin;
 canvas.drawBitmap(bmpConfig, 0 ,bmpConfigTop, paint);
 
!!!デバッグ
!!テスト
*[[Activity の テスト|Android Activity の テスト]]
*[Activity の テスト2|http://typea.info/blg/glob/2011/01/android-eclipse.html]
!!実機でデバッグ
*[実機(X06HT Desire)デバッグ|http://typea.info/blg/glob/2010/06/android_x06ht_desire.html]
*[デバッグ中か否かを判定する|http://typea.info/blg/glob/2010/08/android-2.html]
*[Windows XP にてADBドライバを認識しない場合の対応|http://typea.info/blg/glob/2010/09/android-x06ht-desire-windows-xp-adb.html]

*AndroidManifest.xml Debuggable = true

!!UbuntuでデバイスIDが????と表示され実機デバッグできない
{{ref_image android-sdk07.png}}
*http://developer.android.com/guide/developing/device.html#setting-up
*http://developer.android.com/guide/developing/device.html#VendorIds

::51-android.rulesを作成
 $ cd /etc/udev/rules.d/
 $ sudu su
 # vi 51-android.rules 
::HTCを登録
 SYSTEM=="usb", SYSFS{idVendor}=="0bb4", MODE="0666" 
::権限の設定
 # chmod a+r 51-android.rules 

!確認
*対応前
 # ./adb devices
 List of devices attached 
 ????????????	no permissions
*対応後
 # ./adb devices
 List of devices attached 
 HT061PL00290	device

{{ref_image android-sdk08.png}}
!!TraceView
*トレース開始位置に以下を記述
""SDカードがマウントされていること
 Debug.startMethodTracing("test");
*トレース終了位置に
 Debug.stopMethodTracing();
*トレースが完了したら、トレースファイルを取得
 C:\work>adb pull /sdcard/test.trace
*TraceView を実行
 C:\work>cd C:\Programs\android-sdk-windows\tools
 C:\Programs\android-sdk-windows\tools>traceview c:\work\test.trace
{{ref_image traceview01.jpg}}
!!スクリーンキャプチャ
*Android Eclipse から スクリーンキャプチャを取る
!!カメラアプリで、FileNotFoundException
*http://www.bpsinc.jp/blog/archives/date/2010/05/08
""カメラアプリで、FileNotFoundException /sys/android_camera2/htcwc が発生したら、端末の再起動を行う。

!!SDKソースコードのステップ実行
*[Eclipse からSDKソースコードのステップ実行|http://typea.info/blg/glob/2011/01/android-eclipsesdk.html]
!!!入力
!!IME ソフウェアキーボードを消す
 public void onClick(View v) {
    // ボタンを押したら、ソフウェアキーボードを消す   	
    InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
 }

!!マルチタッチ(ピンチ)
*[ピンチイン・ピンチアウトのサンプル|http://typea.info/blg/glob/2010/08/androidx06ht-desire-3.html]
!!!センサー
!!搭載センサーの値を取得
*[エミュレータのセンサーの値を取得してみる|http://typea.info/blg/glob/2010/05/android-1.html]
*[Android(X06HT Desire) 搭載センサーの値を取得してみる|http://typea.info/blg/glob/2010/06/androidx06ht-desire.html]

!!!バイブレーター
::宣言
 private Vibrator vib;

::初期化
 vib = (Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE);

::利用
 vib.vibrate(50L);

::パーミッション
 <uses-permission android:name="android.permission.VIBRATE"></uses-permission>
		

!!!カメラ
!!画像が90度回転してしまう
*カメラデバイスは向きを認識していないので、指定する必要がある
 Camera.Parameters p = camera.getParameters();
 p.setRotation(90);
 camera.setParameters(p);

""Froyo 化してからは、上記方法が使えなくなった(むしろ使えていたのがおかしかった!?)ため、以下の対応

![カメラプレビューが横向きに表示されてしまう!の対応|http://typea.info/blg/glob/2010/10/android-x06ht-desire-2.html]
*[カメラプレビューが横向きに表示されてしまう!の対応|http://typea.info/blg/glob/2010/10/android-x06ht-desire-2.html]


![カメラプレビューを縦向きにすると画面描画の座標が訳わからなくなる対応|http://typea.info/blg/glob/2011/04/android-5.html]
上記を行うと、Viewに描画するときに座標が混乱してしまう対応。
*[カメラプレビューを縦向きにすると画面描画の座標が訳わからなくなる対応|http://typea.info/blg/glob/2011/04/android-5.html]
!!!サウンド
!!ハードウェアから、音量を制御
*[サンプルソース|http://typea.info/blg/glob/2010/06/androidx06ht_desire_1.html]
*ハードウェアから、音量を制御させるには、以下の記述が必要
 setVolumeControlStream(AudioManager.STREAM_MUSIC); 

!!サウンドモードを判定する
 audioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
 switch (audioManager.getRingerMode()) {
 case AudioManager.RINGER_MODE_SILENT:
     break;
 case AudioManager.RINGER_MODE_VIBRATE:
     break;
 case AudioManager.RINGER_MODE_NORMAL:
     player.seekTo(0);
     player.start();
     break;
 default:
     break;
 }

!!ヘッドフォント着脱を検知する
*[ヘッドフォント着脱を検知する|http://typea.info/blg/glob/2011/12/android-7.html]
!!!電源管理
!!スリープ状態からの復帰、キーロック解除
*http://d.hatena.ne.jp/siso9to/touch/20110212/1297540035
::例
 private PowerManager powerManager;
 private WakeLock wakeLock;
 private KeyguardManager keyguardManager;
 private KeyguardLock keyguardLock;
 
 @Override
 public void onCreate() {
     super.onCreate();
 
     powerManager = (PowerManager)getSystemService(POWER_SERVICE);
     wakeLock = powerManager.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK
                                     | PowerManager.ACQUIRE_CAUSES_WAKEUP
                                     | PowerManager.ON_AFTER_RELEASE, 
                                     ClockService.class.getName());
     keyguardManager = (KeyguardManager) getSystemService(KEYGUARD_SERVICE);
     keyguardLock = keyguardManager.newKeyguardLock(ClockService.class.getName());
 }

 private void hoge() {
  
     // スリープからの復帰とキーロック解除
     wakeLock.acquire();
     keyguardLock.disableKeyguard();
    
     // 何らかの処理
  
     // リリース
     wakeLock.release();
     keyguardLock.disableKeyguard();
 }

::必要なパーミッション
 <uses-permission android:name="android.permission.WAKE_LOCK"/>
 <uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>




!!!アニメーション
!!サンプル設定ファイルの場所
 {android-sdk}\samples\android-7\ApiDemos\res\anim
+/res/anim フォルダを作成
+anim フォルダでコンテキストメニューから import し適用
 ViewFlipper vf = (ViewFlipper) findViewById(R.id.details);
 vf.setAnimation(AnimationUtils.loadAnimation(this, R.anim.push_left_in));


!!!非同期処理
!![非同期処理をAsyncTaskを使って行い進捗をProgressDialogに表示する|http://typea.info/blg/glob/2011/05/android-asynctaskprogressdialog.html]
*[非同期処理をAsyncTaskを使って行い進捗をProgressDialogに表示する|http://typea.info/blg/glob/2011/05/android-asynctaskprogressdialog.html]
!!!Web
!!Httpクライアントタイムアウトを設定する
[Httpクライアントタイムアウトを設定する|http://typea.info/blg/glob/2010/09/android-http.html]
 HttpPost HttpGet = new HttpGet(uri);
 HttpParams httpParms = new BasicHttpParams();
 httpParms.setIntParameter(AllClientPNames.CONNECTION_TIMEOUT, 3000);
 httpParms.setIntParameter(AllClientPNames.SO_TIMEOUT, 5000);
 
 DefaultHttpClient client = new DefaultHttpClient(httpParms);
 HttpResponse response = client.execute(httpPost);

!!MIMEマルチパートでファイルをアップロードする
::以下を入手
*[apache-mime4j|http://james.apache.org/download.cgi#Apache_Mime4J]
*[httpclient|http://hc.apache.org/downloads.cgi]
*[httpcore|http://hc.apache.org/downloads.cgi]
*[httpmime|http://hc.apache.org/downloads.cgi]
""httpmime は、httpcomponents-client に httpclient とともにアーカイブされている。
::サンプル
 DefaultHttpClient client = new DefaultHttpClient();
 HttpPost httpPost = new HttpPost(uri);
 File upfile = new File(info.getPath());
 
 MultipartEntity entity = new MultipartEntity();
 entity.addPart("upload_file_name",     new StringBody(upfile.getName()));
 entity.addPart("upload_file_contents", new FileBody(upfile));
 httpPost.setEntity(entity);
 response = client.execute(httpPost);

!!HttpPost に標準的なパラメータを設定する

 try {
     HttpPost post =  new HttpPost("http://hogehoge.com/hoge");
     List<NameValuePair> parms = new ArrayList<NameValuePair>();
     parms.add(new BasicNameValuePair("lat", this.lat));
     parms.add(new BasicNameValuePair("lng", this.lng));
     post.setEntity(new UrlEncodedFormEntity(parms, HTTP.UTF_8));
                  :
 } catch (UnsupportedEncodingException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
 }

!!Httpリクエストからレスポンスまでの概要
 HttpPost post =  new HttpPost("http://hogehoge.com/hoge");
 
 List<NameValuePair> parms = new ArrayList<NameValuePair>();
 parms.add(new BasicNameValuePair("lat", String.valueOf(loc.getLatitude())));
 parms.add(new BasicNameValuePair("lon", String.valueOf(loc.getLongitude())));
 parms.add(new BasicNameValuePair("message", msg));
 post.setEntity(new UrlEncodedFormEntity(parms, HTTP.UTF_8));
 
 DefaultHttpClient httpClient = new DefaultHttpClient();
 HttpResponse response = httpClient.execute(post);
 
 InputStream in = response.getEntity().getContent();
 BufferedReader reader = new BufferedReader(new InputStreamReader(in));
 String l = null;
 while((l = reader.readLine()) != null) {
     buf.append(l + "\r\n");
 }        
 if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
     Log.e(LocationBasedMessageApplication.TAG, buf.toString());
 }
!!!9Patch
!9Patchの使い方(吹き出しをつくる)
*http://typea.info/blg/glob/2013/07/-android-001.html

!!!Dropbox
*[Dropbox アプリを作成する|http://typea.info/blg/glob/2012/06/android-dropbox.html]
*[Dropbox アプリを公開する|http://typea.info/blg/glob/2012/06/dropbox-android.html]
!!!NDK
*[ネイティブライブラリを利用するため NDK を設定する|http://typea.info/blg/glob/2012/02/android-ndk.html]
!!!Google App Engine
!!開発環境の構築
*[Android (実機) と GAE を連携させるためのデバッグ環境を Windows7 に構築|http://typea.info/blg/glob/2010/08/android-gae-windows7.html]
!!Google アカウントの利用
*[Android アプリから Google アカウントを利用して GAE アプリケーションを利用する|http://typea.info/blg/glob/2010/08/android_google_gae.html]
*[Android アプリから、GAE 開発サーバーのアカウントを利用|http://typea.info/blg/glob/2010/09/android-gae.html]
*[Android からGoogleアカウント認証でGAEアクセスするとServer Error になってしまう|http://typea.info/blg/glob/2011/04/android-googlegaeserver-error.html]
!!!ライブラリ
*http://qiita.com/KeithYokoma/items/fb6872a72a75e9b6f2e6
!!チャート
*https://code.google.com/p/achartengine/
!!UI
!カードUI
*https://github.com/gabrielemariotti/cardslib
!!画像
!読み込み・キャッシュ
*https://github.com/nostra13/Android-Universal-Image-Loader

!!!広告
!![[AdMob|Android AdMob]]
**[[AdMob|Android AdMob]]
!!!公開
!!Android マーケット
*[Android マーケットに開発者登録|http://typea.info/blg/glob/2010/07/android-1.html]

!!SDカードにインストールを許可
*AndroidManifest.xml に installLocation を指定 (Android SDK 2.2から対応)

 android:installLocation="auto" 

,値,内容
,internalOnly,内蔵メモリへのインストールのみ許可
,auto,内蔵メモリ優先
,preferExternal,SDカードを優先

!!アプリ内課金
*[アプリ内課金手順|http://typea.info/blg/glob/2014/03/android-11.html]
!!!トラブルシュート
!!Error generating final archive: Debug certificate expired on エラーでコンパイルできない
*http://android.roof-balcony.com/debug/certificate-expired/

+ユーザーディレクトリの、.android/debug.keystore ファイルを削除
+プロジェクトのクリーン

!!resources.ap_ does not exist エラーで実行できない
以下の様なエラーがでて実行できない
 Your project contains error(s), please fix them before running your application. 
 Description	Resource	Path	Location	Type
 Error generating final archive: java.io.FileNotFoundException: C:\Users\piroto\workspace\EitangoroidPro\bin\resources.ap_ does not exist
http://www.yukun.info/blog/2012/01/android-eclipse-build-error.htmlを参考に以下の手順で解決
*Window - Android SDK Manager から、インストール済みのSDKを最新にUpdate
*eclipse.exe -clean を実行

!!Android requires compiler compliance level 5.0 or 6.0. Found '1.4' instead 
 Android requires compiler compliance level 5.0 or 6.0. Found '1.4' instead. Please use Android Tools > Fix Project Properties.
*プロジェクトのプロパティから、Java Compiler
*Compiler compliance level を 1.6 等 適切なものに
*Android Tools > Fix Project Properties
*リビルド


!!Unable to resolve target
*以下の様なエラーは、SDKのバージョン不一致
 [2013-05-27 22:43:56 - EitangoroidPro] Unable to resolve target 'android-8'
*project.properties を修正
 # Project target.
 target=android-17