「Android Tips」の版間の差分
(同じ利用者による、間の5版が非表示) | |||
1行目: | 1行目: | ||
− | ==Android Tips== | + | ==[[Android Tips]]== |
− | [[Android][Java][Eclipse]] | + | [[Android]] | [[Java]] | [[Eclipse]] | |
==概要== | ==概要== | ||
11行目: | 11行目: | ||
===基本=== | ===基本=== | ||
− | *Android アプリケーション基本 | + | *[[Android アプリケーション基本]] |
===[https://docs.google.com/present/view?id=dfrdwzrx_179f7w9q4ct Android 一連の手順概要]=== | ===[https://docs.google.com/present/view?id=dfrdwzrx_179f7w9q4ct Android 一連の手順概要]=== | ||
17行目: | 17行目: | ||
*[http://typea.info/blg/glob/2012/11/20-android.html 開発環境構築簡易版] | *[http://typea.info/blg/glob/2012/11/20-android.html 開発環境構築簡易版] | ||
===インストール=== | ===インストール=== | ||
− | ====[Android SDKのインストール] | + | ====[[Android SDKのインストール|SDKのインストール]]==== |
− | *[Android SDKのインストール] | + | *[[Android SDKのインストール|SDKのインストール]] |
====SDK Manager に APIの一覧が表示されない場合==== | ====SDK Manager に APIの一覧が表示されない場合==== | ||
− | *Tools - Options からForce | + | *Tools - Options からForce にチェックを入れ、[[HTTP]]接続を可能にする |
[[File:0161_android_sdk_manager.jpg]] | [[File:0161_android_sdk_manager.jpg]] | ||
− | ====[Android ADT Eclipse プラグイン | + | ====[[Android ADT Eclipse プラグイン|ADT Eclipse プラグイン]]==== |
− | *[Android ADT Eclipse プラグイン | + | *[[Android ADT Eclipse プラグイン|ADT Eclipse プラグイン]] |
===環境構築手順=== | ===環境構築手順=== | ||
48行目: | 48行目: | ||
====[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で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でADTプラグインインストールエラー] | ||
− | ====Ubuntu ADBドライバに実機を認識させる==== | + | ====[[Ubuntu]] ADBドライバに実機を認識させる==== |
*[http://typea.info/blg/glob/2011/05/ubuntu-android.html ???? と認識されてしまう解決法] | *[http://typea.info/blg/glob/2011/05/ubuntu-android.html ???? と認識されてしまう解決法] | ||
*[http://typea.info/blg/glob/2014/01/ubuntu-1310-64bit-adtadb-android.html 64bit でADBドライバが利用できない解決法] | *[http://typea.info/blg/glob/2014/01/ubuntu-1310-64bit-adtadb-android.html 64bit でADBドライバが利用できない解決法] | ||
==開発環境== | ==開発環境== | ||
===GAE=== | ===GAE=== | ||
− | + | [http://typea.info/blg/glob/2010/08/android_gae_windows7.html Android (実機) と GAE を連携させるためのデバッグ環境を Windows7 に構築する] | |
===SDK ソースコード=== | ===SDK ソースコード=== | ||
− | =====[CentOS 初期設定 | + | =====[[CentOS 初期設定|Gitのインストール(Linux)]]===== |
# git clone git://android.git.kernel.org/platform/frameworks/base.git | # git clone git://android.git.kernel.org/platform/frameworks/base.git | ||
62行目: | 62行目: | ||
**[http://android.git.kernel.org/?p=platform/frameworks/base.git;a=tree;f=core/java/android;h=67060e03dddf2bb4fc9b98fd9aaf24a5722f7369;hb=HEAD 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 projects / platform/frameworks/base.git / tree] | ||
− | =====Eclipse===== | + | =====[[Eclipse]]===== |
*[http://typea.info/blg/glob/2011/01/android-eclipsesdk.html Eclipse から使用可能にする手順] | *[http://typea.info/blg/glob/2011/01/android-eclipsesdk.html Eclipse から使用可能にする手順] | ||
− | ===Eclipse 3.6.1 のコード補完で固まる対処=== | + | ===[[Eclipse]] 3.6.1 のコード補完で固まる対処=== |
*[http://d.hatena.ne.jp/goriponsoft/20110210/1297305320 Eclipse 3.6のコード補完のフリーズを解消する] | *[http://d.hatena.ne.jp/goriponsoft/20110210/1297305320 Eclipse 3.6のコード補完のフリーズを解消する] | ||
− | ===== | + | =====以下のパッチを[[Eclipse]]にあてる(解凍して上書き)===== |
*[http://adt-addons.googlecode.com/svn/patches/org.eclipse.jdt.core_3.6.1.v_A68_R36x.zip 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 org.eclipse.jdt.core_3.6.1.v_A68_R36x.zip] | ||
==エミュレータ== | ==エミュレータ== | ||
81行目: | 81行目: | ||
http://www.hakkaku.net/articles/20090831-579 | http://www.hakkaku.net/articles/20090831-579 | ||
− | *XML の manifest/application/activity の属性、android:screenOrientation を、"portrait" に設定すると、縦画面のまま回転しなくなります。 | + | *[[XML]] の manifest/application/activity の属性、android:screenOrientation を、"portrait" に設定すると、縦画面のまま回転しなくなります。 |
=====設定値===== | =====設定値===== | ||
93行目: | 93行目: | ||
if (条件) { | if (条件) { | ||
// 画面の回転を抑制(現在の向きに固定) | // 画面の回転を抑制(現在の向きに固定) | ||
− | Configuration config = | + | Configuration config = get[[R]]esources().getConfiguration(); |
− | if (config.orientation == Configuration. | + | if (config.orientation == Configuration.OR[[IE]]NTATION_PORTRAIT) { |
− | setRequestedOrientation( | + | setRequestedOrientation(Acti[[vi]]tyInfo.SCREEN_ORIENTATION_PORTRAIT); |
− | } else if(config.orientation == Configuration. | + | } else if(config.orientation == Configuration.OR[[IE]]NTATION_LANDSCAPE) { |
− | setRequestedOrientation( | + | setRequestedOrientation(Acti[[vi]]tyInfo.SCREEN_ORIENTATION_LANDSCAPE); |
} | } | ||
} else { | } else { | ||
// 回転を可能に | // 回転を可能に | ||
− | setRequestedOrientation( | + | setRequestedOrientation(Acti[[vi]]tyInfo.SCREEN_ORIENTATION_UNSPECIFIED); |
} | } | ||
*逆向きにも対応版 | *逆向きにも対応版 | ||
* // @see http://stackoverflow.com/questions/2366706/how-to-lock-orientation-during-runtime | * // @see http://stackoverflow.com/questions/2366706/how-to-lock-orientation-during-runtime | ||
− | int orientation = | + | int orientation = getActi[[vi]]ty().getRequestedOrientation(); |
− | int rotation = ((WindowManager) | + | int rotation = ((WindowManager) getActi[[vi]]ty().getSystemSer[[vi]]ce( |
− | Context. | + | Context.WINDOW_SE[[R]]VICE)).getDefaultDisplay().get[[R]]otation(); |
switch (rotation) { | switch (rotation) { | ||
− | case Surface. | + | case Surface.[[R]]OTATION_0: |
− | orientation = | + | orientation = Acti[[vi]]tyInfo.SCREEN_ORIENTATION_PORTRAIT; |
break; | break; | ||
− | case Surface. | + | case Surface.[[R]]OTATION_90: |
− | orientation = | + | orientation = Acti[[vi]]tyInfo.SCREEN_ORIENTATION_LANDSCAPE; |
break; | break; | ||
− | case Surface. | + | case Surface.[[R]]OTATION_180: |
− | orientation = | + | orientation = Acti[[vi]]tyInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT; |
break; | break; | ||
default: | default: | ||
− | orientation = | + | orientation = Acti[[vi]]tyInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE; |
break; | break; | ||
} | } | ||
− | + | getActi[[vi]]ty().setRequestedOrientation(orientation); | |
*固定解除 | *固定解除 | ||
− | setRequestedOrientation( | + | setRequestedOrientation(Acti[[vi]]tyInfo.SCREEN_ORIENTATION_UNSPECIFIED); |
===画面サイズを取得する=== | ===画面サイズを取得する=== | ||
=====1===== | =====1===== | ||
135行目: | 135行目: | ||
=====outSizeに格納される===== | =====outSizeに格納される===== | ||
Point outSize = new Point(); | Point outSize = new Point(); | ||
− | (WindowManager) | + | (WindowManager)getSystemSer[[vi]]ce(Context.WINDOW_SERVICE)).getDefaultDisplay().getSize(outSize); |
===画面の向きを取得する=== | ===画面の向きを取得する=== | ||
− | <blockquote>API Level 8 以降は | + | <blockquote>API Level 8 以降は get[[R]]otation () を使うこと 0:portrait, 1:landscape</blockquote> |
Display display = getWindowManager().getDefaultDisplay(); | Display display = getWindowManager().getDefaultDisplay(); | ||
switch(display.getOrientation()) { | switch(display.getOrientation()) { | ||
− | case Surface. | + | case Surface.[[R]]OTATION_90: |
− | case Surface. | + | case Surface.[[R]]OTATION_270: |
// TODO | // TODO | ||
break; | break; | ||
153行目: | 153行目: | ||
===タイトルバーを非表示に=== | ===タイトルバーを非表示に=== | ||
=====コード===== | =====コード===== | ||
− | *requestWindowFeature(Window. | + | *requestWindowFeature(Window.FEATU[[R]]E_NO_TITLE)を実行 |
− | public class | + | public class ColorChoiceActi[[vi]]ty extends Acti[[vi]]ty { |
@Override | @Override | ||
public void onCreate(Bundle savedInstanceState) { | public void onCreate(Bundle savedInstanceState) { | ||
super.onCreate(savedInstanceState); | super.onCreate(savedInstanceState); | ||
− | requestWindowFeature(Window. | + | requestWindowFeature(Window.FEATU[[R]]E_NO_TITLE); |
− | setContentView(R.layout.main); | + | setContentView([[R]].layout.main); |
} | } | ||
} | } | ||
− | =====XML===== | + | =====[[XML]]===== |
− | * | + | *[[Android]]Manifest.xml に指定 |
*タイトルバーを非表示、フルスクリーン | *タイトルバーを非表示、フルスクリーン | ||
− | < | + | <acti[[vi]]ty : |
android:theme="@android:style/Theme.NoTitleBar.Fullscreen" > | android:theme="@android:style/Theme.NoTitleBar.Fullscreen" > | ||
===最大化表示(ステータスバーを隠す)=== | ===最大化表示(ステータスバーを隠す)=== | ||
=====コード===== | =====コード===== | ||
− | getWindow().addFlags(WindowManager.LayoutParams. | + | getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSC[[R]]EEN); |
− | getWindow().clearFlags(WindowManager.LayoutParams. | + | getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FO[[R]]CE_NOT_FULLSC[[R]]EEN); |
<blockquote>逆の場合、add と clear を変える</blockquote> | <blockquote>逆の場合、add と clear を変える</blockquote> | ||
− | =====XML===== | + | =====[[XML]]===== |
− | * | + | *[[Android]]Manifest.xml に指定 |
*タイトルバーを非表示、フルスクリーン | *タイトルバーを非表示、フルスクリーン | ||
− | < | + | <acti[[vi]]ty : |
android:theme="@android:style/Theme.NoTitleBar.Fullscreen" > | android:theme="@android:style/Theme.NoTitleBar.Fullscreen" > | ||
190行目: | 190行目: | ||
===スタイル=== | ===スタイル=== | ||
− | *[Android スタイル] | + | *[[Android スタイル|スタイル]] |
===色定義を行い使用する === | ===色定義を行い使用する === | ||
=====values/colos.xml を定義===== | =====values/colos.xml を定義===== | ||
199行目: | 199行目: | ||
</resources> | </resources> | ||
− | =====使い方( | + | =====使い方(Acti[[vi]]ty内)===== |
− | txtHoge.setTextColor( | + | txtHoge.setTextColor(get[[R]]esources().getColor([[R]].color.lightgrey)); |
− | <blockquote>txtHoge.setTextColor(R.color.lightgrey) とするのは、色の値として、リソースIDが渡されるためNG</blockquote> | + | <blockquote>txtHoge.setTextColor([[R]].color.lightgrey) とするのは、色の値として、リソースIDが渡されるためNG</blockquote> |
===EditText に最初にフォーカスがあたり、IMEが自動起動してしまうのを抑制=== | ===EditText に最初にフォーカスがあたり、IMEが自動起動してしまうのを抑制=== | ||
212行目: | 212行目: | ||
getWindow().setSoftInputMode(La outParams.SOFT_INPUT_STATE_ALWA S_HIDDEN); | getWindow().setSoftInputMode(La outParams.SOFT_INPUT_STATE_ALWA S_HIDDEN); | ||
− | setContentView(R.la out.word_editor); | + | setContentView([[R]].la out.word_editor); |
==App ウィジェット== | ==App ウィジェット== | ||
238行目: | 238行目: | ||
}); | }); | ||
− | === | + | ===Acti[[vi]]ty にて戻るボタン押下を検知=== |
@Override | @Override | ||
public boolean onKeyDown(int keyCode, KeyEvent event) { | public boolean onKeyDown(int keyCode, KeyEvent event) { | ||
253行目: | 253行目: | ||
new AlertDialog.Builder(parent) | new AlertDialog.Builder(parent) | ||
− | .setTitle(R.string.lbl_file_delete_confirm) | + | .setTitle([[R]].string.lbl_file_delete_confirm) |
− | .setMessage(parent. | + | .setMessage(parent.get[[R]]esources().getString([[R]].string.msg_file_delete_confirm, file.getName())) |
− | .setPositiveButton(R.string.lbl_yes, new DialogInterface.OnClickListener() { | + | .setPositiveButton([[R]].string.lbl_yes, new DialogInterface.OnClickListener() { |
@Override | @Override | ||
public void onClick(DialogInterface dialog, int which) { | public void onClick(DialogInterface dialog, int which) { | ||
261行目: | 261行目: | ||
} | } | ||
}) | }) | ||
− | .setNegativeButton(R.string.lbl_no, new DialogInterface.OnClickListener() { | + | .setNegativeButton([[R]].string.lbl_no, new DialogInterface.OnClickListener() { |
@Override | @Override | ||
public void onClick(DialogInterface dialog, int which) { | public void onClick(DialogInterface dialog, int which) { | ||
270行目: | 270行目: | ||
public void showSortDialog() { | public void showSortDialog() { | ||
final int[] keys = { | final int[] keys = { | ||
− | + | MENU_SO[[R]]T_BY_TITLE, | |
− | + | MENU_SO[[R]]T_BY_HU_LEVEL_ASC, | |
− | + | MENU_SO[[R]]T_BY_HU_LEVEL_DSC, | |
− | + | MENU_SO[[R]]T_BY_C[[R]]EATE_DATE | |
}; | }; | ||
final String[] items = { | final String[] items = { | ||
− | this.getString(R.string.lbl_sort_by_title), | + | 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_asc), |
− | this.getString(R.string.lbl_sort_by_hu_level_dsc), | + | this.getString([[R]].string.lbl_sort_by_hu_level_dsc), |
− | this.getString(R.string.lbl_sort_by_create_date) | + | this.getString([[R]].string.lbl_sort_by_create_date) |
}; | }; | ||
new AlertDialog.Builder(this) | new AlertDialog.Builder(this) | ||
− | .setTitle(R.string.lbl_sort) | + | .setTitle([[R]].string.lbl_sort) |
.setSingleChoiceItems(items, 0, new DialogInterface.OnClickListener() { | .setSingleChoiceItems(items, 0, new DialogInterface.OnClickListener() { | ||
@Override | @Override | ||
291行目: | 291行目: | ||
} | } | ||
}) | }) | ||
− | .setNegativeButton(R.string.lbl_cancel, new DialogInterface.OnClickListener() { | + | .setNegativeButton([[R]].string.lbl_cancel, new DialogInterface.OnClickListener() { |
@Override | @Override | ||
public void onClick(DialogInterface dialog, int which) { | public void onClick(DialogInterface dialog, int which) { | ||
309行目: | 309行目: | ||
Dialog dialog = new Dialog(mContext); | Dialog dialog = new Dialog(mContext); | ||
− | dialog.setContentView(R.layout.custom_dialog); | + | dialog.setContentView([[R]].layout.custom_dialog); |
dialog.setTitle("Custom Dialog"); | dialog.setTitle("Custom Dialog"); | ||
− | TextView text = (TextView) dialog.findViewById(R.id.text); | + | TextView text = (TextView) dialog.findViewById([[R]].id.text); |
dialog.show(); | dialog.show(); | ||
− | == | + | ==Acti[[vi]]ty== |
===同じアプリケーションのアクティビティを呼び出す=== | ===同じアプリケーションのアクティビティを呼び出す=== | ||
=====マニフェストファイルの application セクションの中に以下を記述===== | =====マニフェストファイルの application セクションの中に以下を記述===== | ||
− | < | + | <acti[[vi]]ty android:name=".OtherActi[[vi]]ty"/> |
=====インテントを利用して呼び出し===== | =====インテントを利用して呼び出し===== | ||
Intent intent = new Intent(getApplicationContext(), | Intent intent = new Intent(getApplicationContext(), | ||
− | + | OtherActi[[vi]]ty.class); | |
− | + | startActi[[vi]]ty(intent); | |
<blockquote>データの受け渡しには、Intent.putExtra を利用</blockquote> | <blockquote>データの受け渡しには、Intent.putExtra を利用</blockquote> | ||
− | ===== | + | =====Acti[[vi]]ty.onCreate ===== |
− | Spinner spFontSize = (Spinner) findViewById(R.id.spn_font_size); | + | Spinner spFontSize = (Spinner) findViewById([[R]].id.spn_font_size); |
ArrayAdapter<CharSequence> spFontSizeAdapter | ArrayAdapter<CharSequence> spFontSizeAdapter | ||
− | = ArrayAdapter. | + | = ArrayAdapter.createFrom[[R]]esource(this, |
− | R.array.ary_font_size, | + | [[R]].array.ary_font_size, |
− | android.R.layout.simple_spinner_item); | + | android.[[R]].layout.simple_spinner_item); |
− | spFontSizeAdapter. | + | spFontSizeAdapter.setDropDownView[[R]]esource(android.[[R]].layout.simple_spinner_dropdown_item); |
spFontSize.setAdapter(spFontSizeAdapter); | spFontSize.setAdapter(spFontSizeAdapter); | ||
===[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 Activity の状態を一時的に保存する]=== | ||
− | + | [http://typea.info/blg/glob/2010/09/androidx06ht-desire-activity-activity.html Activity の状態を一時的に保存する] | |
===[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 コンフィグレーション]=== | ===[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はそのコンフィグレーションにマッチするように更新する必要があるため、Acti[[vi]]tiは再スタートされる |
− | * | + | *コンフィグレーションの変更があってもActi[[vi]]tyの再スタートを避けたい場合、マニフェストにandroid:configChanges属性を追加 |
android:configChanges="locale|orientation|" | android:configChanges="locale|orientation|" | ||
===[http://typea.info/blg/glob/2010/09/android-arrayadapter.html ArrayAdapter に ラジオボタンを置く]=== | ===[http://typea.info/blg/glob/2010/09/android-arrayadapter.html ArrayAdapter に ラジオボタンを置く]=== | ||
− | + | [http://typea.info/blg/glob/2010/09/android-arrayadapter.html ArrayAdapter に ラジオボタンを置く] | |
− | === | + | ===TabActi[[vi]]ty(タブによるアクティビティ切り替え) サンプル=== |
− | + | [http://typea.info/blg/glob/2010/11/android-tabactivity.html TabActivity] | |
− | === | + | ===ListActi[[vi]]ty(リスト表示画面)サンプル=== |
− | [[Android スケルトン ListActivity | + | [[Android スケルトン ListActivity|ListActivity]] |
− | === | + | ===PreferenceActi[[vi]]ty(設定画面の作成) サンプル=== |
− | + | [http://typea.info/blg/glob/2010/10/android-android-hacks.html PreferenceActivity] | |
− | === | + | ===透明なActi[[vi]]tyを作成する=== |
− | *http://stackoverflow.com/questions/2176922/how-to-create-transparent- | + | *http://stackoverflow.com/questions/2176922/how-to-create-transparent-acti[[vi]]ty-in-android |
====res/values/styles.xml に以下の内容を記述==== | ====res/values/styles.xml に以下の内容を記述==== | ||
<?xml version="1.0" encoding="utf-8"?> | <?xml version="1.0" encoding="utf-8"?> | ||
362行目: | 362行目: | ||
</style> | </style> | ||
</resources> | </resources> | ||
− | ==== | + | ====[[Android]]Manifest.xml のActivityのtheme属性にに以下の記述==== |
− | < | + | <acti[[vi]]ty android:name=".EditScoreActi[[vi]]ty" android:theme="@style/Theme.Transparent"></acti[[vi]]ty> |
− | === | + | ===Acti[[vi]]ty をダイアログとして表示する=== |
*@android:style/Theme.Dialog を利用 | *@android:style/Theme.Dialog を利用 | ||
− | < | + | <acti[[vi]]ty android:name=".EditScoreActi[[vi]]ty" android:theme="@android:style/Theme.Dialog"></acti[[vi]]ty> |
− | == | + | ==Ser[[vi]]ce== |
− | ===[Android Service] | + | ===[[Android Service|Service]]=== |
==Fragment== | ==Fragment== | ||
− | *[Android Fragment] | + | *[[Android Fragment|Fragment]] |
===サポートライブラリ(android.support.v4)でFragmentを利用する場合の注意点=== | ===サポートライブラリ(android.support.v4)でFragmentを利用する場合の注意点=== | ||
*android.support.v4 のクラスを利用する | *android.support.v4 のクラスを利用する | ||
import android.support.v4.app.Fragment; | import android.support.v4.app.Fragment; | ||
− | import android.support.v4.app. | + | import android.support.v4.app.FragmentActi[[vi]]ty; |
import android.support.v4.app.FragmentManager; | import android.support.v4.app.FragmentManager; | ||
import android.support.v4.app.FragmentStatePagerAdapter; | import android.support.v4.app.FragmentStatePagerAdapter; | ||
− | import android.support.v4. | + | import android.support.v4.[[vi]]ew.PagerAdapter; |
− | import android.support.v4. | + | import android.support.v4.[[vi]]ew.ViewPager; |
− | * | + | *Acti[[vi]]ty ではなく、FragmentActi[[vi]]tyを利用する |
*getFragmentManager() ではなく、getSupportFragmentManager() を利用する | *getFragmentManager() ではなく、getSupportFragmentManager() を利用する | ||
− | * | + | *invalidateOptions[[Menu]]() ではなく、supportInvalidateOptions[[Menu]]() を利用する |
==非同期処理== | ==非同期処理== | ||
*[http://typea.info/blg/glob/2014/02/android-asynctask.html AsyncTaskを使う] | *[http://typea.info/blg/glob/2014/02/android-asynctask.html AsyncTaskを使う] | ||
388行目: | 388行目: | ||
===ListView の分離線を変更する=== | ===ListView の分離線を変更する=== | ||
− | ==== | + | ====[[XML]]から==== |
<ListView android:id="@+id/android:list" | <ListView android:id="@+id/android:list" | ||
android:layout_height="wrap_content" | android:layout_height="wrap_content" | ||
android:layout_width="fill_parent" | android:layout_width="fill_parent" | ||
− | android: | + | android:di[[vi]]der="#D7D7D7" |
− | android: | + | android:di[[vi]]derHeight="1px"> |
</ListView> | </ListView> | ||
====コードから==== | ====コードから==== | ||
ListView lv = getListView(); | ListView lv = getListView(); | ||
− | lv. | + | lv.setDi[[vi]]der(new ColorDrawable(Color.GREEN)); |
− | lv. | + | lv.setDi[[vi]]derHeight(1); |
===ListViewのID=== | ===ListViewのID=== | ||
415行目: | 415行目: | ||
*[http://typea.info/blg/glob/2012/02/android-8.html ListViewのスクロールバーを大きくする] | *[http://typea.info/blg/glob/2012/02/android-8.html ListViewのスクロールバーを大きくする] | ||
===ListViewのコンテキストメニュー選択時にアイテムを取り出す=== | ===ListViewのコンテキストメニュー選択時にアイテムを取り出す=== | ||
− | + | [http://typea.info/blg/glob/2012/02/android-8.html ListViewのコンテキストメニュー選択時にアイテムを取り出す] | |
===カスタムViewを利用する=== | ===カスタムViewを利用する=== | ||
*http://developer.android.com/guide/topics/ui/custom-components.html | *http://developer.android.com/guide/topics/ui/custom-components.html | ||
− | < | + | <[[vi]]ew xmlns:android="http://schemas.android.com/apk/res/android" |
class="info.typea.iromegane.ColorTile" | class="info.typea.iromegane.ColorTile" | ||
− | android:id="@+id/col_tile" ></ | + | android:id="@+id/col_tile" ></[[vi]]ew> |
− | === | + | ===カスタムViewを作成しレイアウトは[[XML]]で行う=== |
public class HogeView extends LinearLayout { | public class HogeView extends LinearLayout { | ||
429行目: | 429行目: | ||
LayoutInflater layoutInflater | LayoutInflater layoutInflater | ||
− | = (LayoutInflater)context. | + | = (LayoutInflater)context.getSystemSer[[vi]]ce(Context.LAYOUT_INFLATER_SERVICE); |
− | View | + | View [[vi]]ew = layoutInflater.inflate(R.layout.hoge_layout, this); |
} | } | ||
} | } | ||
===ページめくり=== | ===ページめくり=== | ||
− | + | [http://typea.info/blg/glob/2010/07/androidx06ht_desire_2.html ページをめくるサンプル] | |
===Spinnerの使い方例=== | ===Spinnerの使い方例=== | ||
446行目: | 446行目: | ||
</string-array> | </string-array> | ||
− | ===== | + | =====Acti[[vi]]ty===== |
// フォントサイズ | // フォントサイズ | ||
− | spFontSize = (Spinner) findViewById(R.id.spn_font_size); | + | spFontSize = (Spinner) findViewById([[R]].id.spn_font_size); |
ArrayAdapter<CharSequence> spFontSizeAdapter | ArrayAdapter<CharSequence> spFontSizeAdapter | ||
− | = ArrayAdapter. | + | = ArrayAdapter.createFrom[[R]]esource(this, |
− | R.array.ary_font_size, | + | [[R]].array.ary_font_size, |
− | android.R.layout.simple_spinner_item); | + | android.[[R]].layout.simple_spinner_item); |
− | spFontSizeAdapter. | + | spFontSizeAdapter.setDropDownView[[R]]esource(android.[[R]].layout.simple_spinner_dropdown_item); |
spFontSize.setAdapter(spFontSizeAdapter); | spFontSize.setAdapter(spFontSizeAdapter); | ||
− | spFontSize.setPrompt( | + | spFontSize.setPrompt(get[[R]]esources().getText([[R]].string.lbl_font_size)); |
for (int i=0; i<spFontSize.getCount(); i++) { | for (int i=0; i<spFontSize.getCount(); i++) { | ||
467行目: | 467行目: | ||
*[http://typea.info/blg/glob/2010/07/android-x06ht-desire-1.html 入力ダイアログ、確認ダイアログを共通化] | *[http://typea.info/blg/glob/2010/07/android-x06ht-desire-1.html 入力ダイアログ、確認ダイアログを共通化] | ||
==検索== | ==検索== | ||
− | ===[Android 検索インターフェースの作成] | + | ===[[Android 検索インターフェースの作成|検索インターフェースの作成]]=== |
− | == | + | ==ContentPro[[vi]]der== |
===連絡先の取得と電話をかける=== | ===連絡先の取得と電話をかける=== | ||
*[http://typea.info/blg/glob/2010/06/androidx06ht-desire-1.html Android(X06HT Desire) 連絡先の取得と電話をかけるサンプル] | *[http://typea.info/blg/glob/2010/06/androidx06ht-desire-1.html Android(X06HT Desire) 連絡先の取得と電話をかけるサンプル] | ||
477行目: | 477行目: | ||
==レイアウト== | ==レイアウト== | ||
− | === | + | ===[[XML]]からレイアウトをインスタンス化する=== |
− | ===== | + | =====SystemSer[[vi]]ce を直接===== |
− | LayoutInflater vi = (LayoutInflater) | + | LayoutInflater [[vi]] = (LayoutInflater)getSystemSer[[vi]]ce(Context.LAYOUT_INFLATER_SERVICE); |
− | prevView = vi.inflate(R.layout. | + | prevView = [[vi]].inflate(R.layout.layout_pre[[vi]]ous,null); |
− | currentView = vi.inflate(R.layout.layout_current,null); | + | currentView = [[vi]].inflate(R.layout.layout_current,null); |
− | nextView = vi.inflate(R.layout.layout_next,null); | + | nextView = [[vi]].inflate(R.layout.layout_next,null); |
− | ===== | + | =====SystemSer[[vi]]ce を View経由===== |
− | EditText editor = (EditText) View.inflate(this, R.layout.editor_lined, null); | + | EditText editor = (EditText) View.inflate(this, [[R]].layout.editor_lined, null); |
===スクロールさせる=== | ===スクロールさせる=== | ||
511行目: | 511行目: | ||
</LinearLayout> | </LinearLayout> | ||
==インテント== | ==インテント== | ||
− | ===暗黙的 Intent で Twitter や Evernote と連携する=== | + | ===暗黙的 Intent で [[Twitter]] や Evernote と連携する=== |
*[http://typea.info/blg/glob/2011/02/android-intent-twitter-evernote.html 暗黙的 Intent で Twitter や Evernote と連携す] | *[http://typea.info/blg/glob/2011/02/android-intent-twitter-evernote.html 暗黙的 Intent で Twitter や Evernote と連携す] | ||
===テキストエディタ等にファイルの処理をさせる=== | ===テキストエディタ等にファイルの処理をさせる=== | ||
− | =====setDataAndType | + | =====setDataAndType を使って、ファイルのU[[R]]IとMIMEタイプを同時に渡す===== |
− | <blockquote>個別に渡すと後に渡した方しか有効にならない(バグ?仕様 | + | <blockquote>個別に渡すと後に渡した方しか有効にならない(バグ?仕様 [[Android]]2.1 X06HT)</blockquote> |
File f = new File(path); | File f = new File(path); | ||
Intent intent = new Intent(); | Intent intent = new Intent(); | ||
− | intent.setAction(Intent. | + | intent.setAction(Intent.ACTION_V[[IE]]W); |
intent.setDataAndType(Uri.fromFile(f),"text/plain"); | intent.setDataAndType(Uri.fromFile(f),"text/plain"); | ||
− | + | startActi[[vi]]ty(intent); | |
===画像ファイルを共有する=== | ===画像ファイルを共有する=== | ||
Intent intent = new Intent(android.content.Intent.ACTION_SEND); | Intent intent = new Intent(android.content.Intent.ACTION_SEND); | ||
intent.setType("image/jpeg"); | intent.setType("image/jpeg"); | ||
− | intent.putExtra(Intent. | + | intent.putExtra(Intent.EXT[[R]]A_ST[[R]]EAM, Uri.fromFile(file)); |
− | + | startActi[[vi]]ty(Intent.createChooser(intent, "title")); | |
− | === | + | ===ブラウザを開くなどU[[R]]Iの処理を行う=== |
Uri uri = Uri.parse("https://market.android.com/details?id=info.typea.eitangoroid.pro"); | Uri uri = Uri.parse("https://market.android.com/details?id=info.typea.eitangoroid.pro"); | ||
− | Intent intent = new Intent(Intent. | + | Intent intent = new Intent(Intent.ACTION_V[[IE]]W, uri); |
− | context. | + | context.startActi[[vi]]ty(intent); |
===ブロードキャストされたインテントを受け取る=== | ===ブロードキャストされたインテントを受け取る=== | ||
542行目: | 542行目: | ||
*http://typea.info/blg/glob/2013/07/-android-001.html | *http://typea.info/blg/glob/2013/07/-android-001.html | ||
==ノーティフィケーション== | ==ノーティフィケーション== | ||
− | === | + | ===起動しているActi[[vi]]tyを全面に表示させる=== |
*http://blog.livedoor.jp/ss_9/archives/1745734.html?ignore_lite | *http://blog.livedoor.jp/ss_9/archives/1745734.html?ignore_lite | ||
− | ===== | + | =====[[Android]]Manifest.xml===== |
− | *android:launchMode="singleTop" | + | *android:launchMode="singleTop" を指定。指定しないと別のActi[[vi]]tyが生成されてしまう。 |
− | < | + | <acti[[vi]]ty android:name=".TimeKeeperActi[[vi]]ty" |
android:launchMode="singleTop"> | android:launchMode="singleTop"> | ||
: | : | ||
=====インテントを設定し、通知を行う===== | =====インテントを設定し、通知を行う===== | ||
− | Notification notification = new Notification(R.drawable.icon, | + | Notification notification = new Notification([[R]].drawable.icon, |
text, System.currentTimeMillis()); | text, System.currentTimeMillis()); | ||
− | PendingIntent contentIntent = PendingIntent. | + | PendingIntent contentIntent = PendingIntent.getActi[[vi]]ty(this, 0, |
− | Intent(this, | + | Intent(this, TimeKeeperActi[[vi]]ty.class), 0); |
− | notification.setLatestEventInfo(this, getString(R.string.msg_section_alarm), | + | notification.setLatestEventInfo(this, getString([[R]].string.msg_section_alarm), |
text, contentIntent); | text, contentIntent); | ||
− | notifManager.notify(R.string.app_name, notification); | + | notifManager.notify([[R]].string.app_name, notification); |
==メニュー== | ==メニュー== | ||
− | ===Android 規定のアイコンを設定=== | + | ===[[Android]] 規定のアイコンを設定=== |
@Override | @Override | ||
− | public boolean | + | public boolean onCreateOptions[[Menu]]([[Menu]] menu) { |
− | super. | + | super.onCreateOptions[[Menu]](menu); |
− | menu.add(0, MENU_ADD_NEW, 0, R.string.menu_add_new_item) | + | menu.add(0, MENU_ADD_NEW, 0, [[R]].string.menu_add_new_item) |
− | .setIcon(android.R.drawable.ic_menu_add); | + | .setIcon(android.[[R]].drawable.ic_menu_add); |
return true; | return true; | ||
} | } | ||
===ListView に コンテキストメニュー(長押し)を設定=== | ===ListView に コンテキストメニュー(長押し)を設定=== | ||
− | public class | + | public class SampleListActi[[vi]]ty extends ListActi[[vi]]ty { |
− | private static final int MENU_EDIT = Menu.FIRST; | + | private static final int MENU_EDIT = [[Menu]].FIRST; |
@Override | @Override | ||
public void onCreate(Bundle savedInstanceState) { | public void onCreate(Bundle savedInstanceState) { | ||
576行目: | 576行目: | ||
: | : | ||
// 忘れがち | // 忘れがち | ||
− | + | registerForContext[[Menu]](getListView()); | |
} | } | ||
@Override | @Override | ||
− | public void | + | public void onCreateContext[[Menu]](Context[[Menu]] menu, View v, |
− | + | Context[[Menu]]Info menuInfo) { | |
− | super. | + | super.onCreateContext[[Menu]](menu, v, menuInfo); |
− | menu.add(0, MENU_EDIT, 0, R.string.menu_edit); | + | menu.add(0, MENU_EDIT, 0, [[R]].string.menu_edit); |
} | } | ||
@Override | @Override | ||
− | public boolean onContextItemSelected( | + | public boolean onContextItemSelected([[Menu]]Item item) { |
switch(item.getItemId()) { | switch(item.getItemId()) { | ||
case MENU_EDIT: | case MENU_EDIT: | ||
599行目: | 599行目: | ||
==パーミッション== | ==パーミッション== | ||
*http://developer.android.com/reference/android/Manifest.permission.html | *http://developer.android.com/reference/android/Manifest.permission.html | ||
− | ===Android パーミッション=== | + | ===[[Android パーミッション]]=== |
==assetリソース== | ==assetリソース== | ||
===assetリソースディレクトリのファイルを読む=== | ===assetリソースディレクトリのファイルを読む=== | ||
617行目: | 617行目: | ||
continue; | continue; | ||
} | } | ||
− | + | Buffered[[R]]eader reader = new Buffered[[R]]eader(new InputStream[[R]]eader(zin)); | |
String line = null; | String line = null; | ||
while ((line = reader.readLine()) != null) { | while ((line = reader.readLine()) != null) { | ||
631行目: | 631行目: | ||
} | } | ||
==文字列リソース== | ==文字列リソース== | ||
− | === | + | ===書式設定で[[XML]]エラーとなる=== |
− | フォーマットを行う場合、複数の%が含まれたりすると、Multiple annotations found at this | + | フォーマットを行う場合、複数の%が含まれたりすると、Multiple annotations found at this エラーで、[[XML]]が解析されない |
*http://stackoverflow.com/questions/4414389/android-xml-percent-symbol | *http://stackoverflow.com/questions/4414389/android-xml-percent-symbol | ||
640行目: | 640行目: | ||
=====コード例===== | =====コード例===== | ||
− | String text = getContext().getString(R.string.msg_location_msg, | + | String text = getContext().getString([[R]].string.msg_location_msg, |
location.getLatitude(), | location.getLatitude(), | ||
location.getLongitude()); | location.getLongitude()); | ||
648行目: | 648行目: | ||
File targetdir = getFilesDir(); | File targetdir = getFilesDir(); | ||
===SDカードがマウントされているか判定=== | ===SDカードがマウントされているか判定=== | ||
− | if ( | + | if (En[[vi]]ronment.MEDIA_MOUNTED.equals(En[[vi]]ronment.getExternalStorageState())) { |
// マウントされている | // マウントされている | ||
} | } | ||
===SDカードへ保存=== | ===SDカードへ保存=== | ||
=====パーミッション===== | =====パーミッション===== | ||
− | android.permission. | + | android.permission.W[[R]]ITE_EXTE[[R]]NAL_STO[[R]]AGE |
=====対象ディレクトリの取得===== | =====対象ディレクトリの取得===== | ||
− | File targetdir = | + | File targetdir = En[[vi]]ronment.getExternalStorageDirectory(); |
==データベース== | ==データベース== | ||
− | === | + | ===コマンドラインから[[SQL]]を発行=== |
− | *http://typea.info/blg/glob/2012/01/android-sqlite-sql.html | + | *http://typea.info/blg/glob/2012/01/android-[[sqlite]]-sql.html |
**エミュレータを使用する | **エミュレータを使用する | ||
− | ** | + | **コマンドプロンプトのフォントおよび[[文字コード]]を変更する |
C:\Users\piroto>adb shell | C:\Users\piroto>adb shell | ||
# cd /data/data/info.typea.eitangoroid.pro/databases | # cd /data/data/info.typea.eitangoroid.pro/databases | ||
667行目: | 667行目: | ||
# ls | # ls | ||
ls | ls | ||
− | + | web[[vi]]ewCache.db | |
FlippadDB | FlippadDB | ||
− | + | web[[vi]]ew.db | |
− | # | + | # [[sqlite]]3 FlippadDB |
− | + | [[sqlite]]3 FlippadDB | |
− | + | [[SQL]]ite version 3.6.22 | |
Enter ".help" for instructions | Enter ".help" for instructions | ||
− | Enter SQL statements terminated with a ";" | + | Enter [[SQL]] statements terminated with a ";" |
==画像== | ==画像== | ||
===ビットマップのサイズ変更=== | ===ビットマップのサイズ変更=== | ||
697行目: | 697行目: | ||
=====画面中央に文字列描画===== | =====画面中央に文字列描画===== | ||
Paint paint = new Paint(); | Paint paint = new Paint(); | ||
− | paint. | + | paint.setA[[R]]GB(60, 80, 80, 80); |
− | paint.setTextAlign(Paint.Align. | + | paint.setTextAlign(Paint.Align.CENTE[[R]]); |
paint.setTextSize(80); | paint.setTextSize(80); | ||
paint.setTypeface(Typeface.DEFAULT_BOLD); | paint.setTypeface(Typeface.DEFAULT_BOLD); | ||
708行目: | 708行目: | ||
====文字列領域の高さにより、フォントサイズを決定する==== | ====文字列領域の高さにより、フォントサイズを決定する==== | ||
Paint txtPaint = new Paint(); | Paint txtPaint = new Paint(); | ||
− | txtPaint.setTextAlign(Paint.Align. | + | txtPaint.setTextAlign(Paint.Align.CENTE[[R]]); |
txtPaint.setStyle(Paint.Style.FILL); | txtPaint.setStyle(Paint.Style.FILL); | ||
txtPaint.setAntiAlias(true); | txtPaint.setAntiAlias(true); | ||
730行目: | 730行目: | ||
===Bitmap=== | ===Bitmap=== | ||
====リソースからBitmapを生成し、カラーフィルターをかけてCanvasに描画==== | ====リソースからBitmapを生成し、カラーフィルターをかけてCanvasに描画==== | ||
− | Bitmap bmpConfig = BitmapFactory. | + | Bitmap bmpConfig = BitmapFactory.decode[[R]]esource(get[[R]]esources(), [[R]].drawable.config); |
Paint paint = new Paint(); | Paint paint = new Paint(); | ||
− | paint.setColorFilter(new PorterDuffColorFilter(Color. | + | paint.setColorFilter(new PorterDuffColorFilter(Color.G[[R]]EEN,Mode.S[[R]]C_IN)); |
float bmpConfigTop = blindTop + iconMargin; | float bmpConfigTop = blindTop + iconMargin; | ||
canvas.drawBitmap(bmpConfig, 0 ,bmpConfigTop, paint); | canvas.drawBitmap(bmpConfig, 0 ,bmpConfigTop, paint); | ||
738行目: | 738行目: | ||
==デバッグ== | ==デバッグ== | ||
===テスト=== | ===テスト=== | ||
− | *[Android Activity の テスト | + | *[[Android Activity の テスト|Activity の テスト]] |
*[http://typea.info/blg/glob/2011/01/android-eclipse.html Activity の テスト2] | *[http://typea.info/blg/glob/2011/01/android-eclipse.html Activity の テスト2] | ||
===実機でデバッグ=== | ===実機でデバッグ=== | ||
745行目: | 745行目: | ||
*[http://typea.info/blg/glob/2010/09/android-x06ht-desire-windows-xp-adb.html Windows XP にてADBドライバを認識しない場合の対応] | *[http://typea.info/blg/glob/2010/09/android-x06ht-desire-windows-xp-adb.html Windows XP にてADBドライバを認識しない場合の対応] | ||
− | * | + | *[[Android]]Manifest.xml Debuggable = true |
− | === | + | ===[[Ubuntu]]でデバイスIDが????と表示され実機デバッグできない=== |
[[File:0158_android-sdk07.png]] | [[File:0158_android-sdk07.png]] | ||
− | *http://developer.android.com/guide/developing/ | + | *http://developer.android.com/guide/developing/de[[vi]]ce.html#setting-up |
− | *http://developer.android.com/guide/developing/ | + | *http://developer.android.com/guide/developing/de[[vi]]ce.html#VendorIds |
=====51-android.rulesを作成===== | =====51-android.rulesを作成===== | ||
$ cd /etc/udev/rules.d/ | $ cd /etc/udev/rules.d/ | ||
$ sudu su | $ sudu su | ||
− | # vi 51-android.rules | + | # [[vi]] 51-android.rules |
=====HTCを登録===== | =====HTCを登録===== | ||
SYSTEM=="usb", SYSFS{idVendor}=="0bb4", MODE="0666" | SYSTEM=="usb", SYSFS{idVendor}=="0bb4", MODE="0666" | ||
763行目: | 763行目: | ||
====確認==== | ====確認==== | ||
*対応前 | *対応前 | ||
− | # ./adb | + | # ./adb de[[vi]]ces |
− | List of | + | List of de[[vi]]ces attached |
???????????? no permissions | ???????????? no permissions | ||
*対応後 | *対応後 | ||
− | # ./adb | + | # ./adb de[[vi]]ces |
− | List of | + | List of de[[vi]]ces attached |
− | HT061PL00290 | + | HT061PL00290 de[[vi]]ce |
[[File:0159_android-sdk08.png]] | [[File:0159_android-sdk08.png]] | ||
782行目: | 782行目: | ||
*TraceView を実行 | *TraceView を実行 | ||
C:\work>cd C:\Programs\android-sdk-windows\tools | C:\work>cd C:\Programs\android-sdk-windows\tools | ||
− | C:\Programs\android-sdk-windows\tools> | + | C:\Programs\android-sdk-windows\tools>trace[[vi]]ew c:\work\test.trace |
− | [[ | + | {{ref_image trace[[vi]]ew01.jpg}} |
===スクリーンキャプチャ=== | ===スクリーンキャプチャ=== | ||
− | *Android Eclipse から スクリーンキャプチャを取る | + | *[[Android Eclipse から スクリーンキャプチャを取る]] |
===カメラアプリで、FileNotFoundException=== | ===カメラアプリで、FileNotFoundException=== | ||
*http://www.bpsinc.jp/blog/archives/date/2010/05/08 | *http://www.bpsinc.jp/blog/archives/date/2010/05/08 | ||
796行目: | 796行目: | ||
public void onClick(View v) { | public void onClick(View v) { | ||
// ボタンを押したら、ソフウェアキーボードを消す | // ボタンを押したら、ソフウェアキーボードを消す | ||
− | InputMethodManager imm = (InputMethodManager) | + | InputMethodManager imm = (InputMethodManager)getSystemSer[[vi]]ce(Context.INPUT_METHOD_SERVICE); |
imm.hideSoftInputFromWindow(v.getWindowToken(), 0); | imm.hideSoftInputFromWindow(v.getWindowToken(), 0); | ||
} | } | ||
806行目: | 806行目: | ||
*[http://typea.info/blg/glob/2010/05/android-1.html エミュレータのセンサーの値を取得してみる] | *[http://typea.info/blg/glob/2010/05/android-1.html エミュレータのセンサーの値を取得してみる] | ||
*[http://typea.info/blg/glob/2010/06/androidx06ht-desire.html Android(X06HT Desire) 搭載センサーの値を取得してみる] | *[http://typea.info/blg/glob/2010/06/androidx06ht-desire.html Android(X06HT Desire) 搭載センサーの値を取得してみる] | ||
+ | ===GPS(緯度・経度)=== | ||
+ | *[https://www.typea.info/blog/index.php/2011/03/30/android_gps_1/ Android GPS(位置情報) を使うための準備(1)] | ||
+ | *https://www.typea.info/materials/android_a_yan_no1.pdf 使用例] | ||
==バイブレーター== | ==バイブレーター== | ||
=====宣言===== | =====宣言===== | ||
− | private Vibrator | + | private Vibrator [[vi]]b; |
=====初期化===== | =====初期化===== | ||
− | + | [[vi]]b = (Vibrator) getContext().getSystemSer[[vi]]ce(Context.VIBRATOR_SERVICE); | |
=====利用===== | =====利用===== | ||
− | + | [[vi]]b.[[vi]]brate(50L); | |
=====パーミッション===== | =====パーミッション===== | ||
− | <uses-permission android:name="android.permission. | + | <uses-permission android:name="android.permission.VIB[[R]]ATE"></uses-permission> |
825行目: | 828行目: | ||
*カメラデバイスは向きを認識していないので、指定する必要がある | *カメラデバイスは向きを認識していないので、指定する必要がある | ||
Camera.Parameters p = camera.getParameters(); | Camera.Parameters p = camera.getParameters(); | ||
− | p. | + | p.set[[R]]otation(90); |
camera.setParameters(p); | camera.setParameters(p); | ||
841行目: | 844行目: | ||
*[http://typea.info/blg/glob/2010/06/androidx06ht_desire_1.html サンプルソース] | *[http://typea.info/blg/glob/2010/06/androidx06ht_desire_1.html サンプルソース] | ||
*ハードウェアから、音量を制御させるには、以下の記述が必要 | *ハードウェアから、音量を制御させるには、以下の記述が必要 | ||
− | setVolumeControlStream(AudioManager. | + | setVolumeControlStream(AudioManager.ST[[R]]EAM_MUSIC); |
===サウンドモードを判定する=== | ===サウンドモードを判定する=== | ||
− | audioManager = (AudioManager) | + | audioManager = (AudioManager)getSystemSer[[vi]]ce(Context.AUDIO_SERVICE); |
− | switch (audioManager. | + | switch (audioManager.get[[R]]ingerMode()) { |
− | case AudioManager. | + | case AudioManager.[[R]]INGE[[R]]_MODE_SILENT: |
break; | break; | ||
− | case AudioManager. | + | case AudioManager.[[R]]INGE[[R]]_MODE_VIB[[R]]ATE: |
break; | break; | ||
− | case AudioManager. | + | case AudioManager.[[R]]INGE[[R]]_MODE_NO[[R]]MAL: |
player.seekTo(0); | player.seekTo(0); | ||
player.start(); | player.start(); | ||
873行目: | 876行目: | ||
super.onCreate(); | super.onCreate(); | ||
− | powerManager = (PowerManager) | + | powerManager = (PowerManager)getSystemSer[[vi]]ce(POWER_SERVICE); |
− | wakeLock = powerManager.newWakeLock(PowerManager. | + | wakeLock = powerManager.newWakeLock(PowerManager.SC[[R]]EEN_DIM_WAKE_LOCK |
− | | PowerManager. | + | | PowerManager.ACQUI[[R]]E_CAUSES_WAKEUP |
− | | PowerManager. | + | | PowerManager.ON_AFTE[[R]]_[[R]]ELEASE, |
− | + | ClockSer[[vi]]ce.class.getName()); | |
− | keyguardManager = (KeyguardManager) | + | keyguardManager = (KeyguardManager) getSystemSer[[vi]]ce(KEYGUARD_SERVICE); |
− | keyguardLock = keyguardManager.newKeyguardLock( | + | keyguardLock = keyguardManager.newKeyguardLock(ClockSer[[vi]]ce.class.getName()); |
} | } | ||
897行目: | 900行目: | ||
=====必要なパーミッション===== | =====必要なパーミッション===== | ||
<uses-permission android:name="android.permission.WAKE_LOCK"/> | <uses-permission android:name="android.permission.WAKE_LOCK"/> | ||
− | <uses-permission android:name="android.permission. | + | <uses-permission android:name="android.permission.DISABLE_KEYGUA[[R]]D"/> |
907行目: | 910行目: | ||
#/res/anim フォルダを作成 | #/res/anim フォルダを作成 | ||
#anim フォルダでコンテキストメニューから import し適用 | #anim フォルダでコンテキストメニューから import し適用 | ||
− | ViewFlipper vf = (ViewFlipper) findViewById(R.id.details); | + | ViewFlipper vf = (ViewFlipper) findViewById([[R]].id.details); |
− | vf.setAnimation(AnimationUtils.loadAnimation(this, R.anim.push_left_in)); | + | vf.setAnimation(AnimationUtils.loadAnimation(this, [[R]].anim.push_left_in)); |
916行目: | 919行目: | ||
==Web== | ==Web== | ||
===Httpクライアントタイムアウトを設定する=== | ===Httpクライアントタイムアウトを設定する=== | ||
− | + | [http://typea.info/blg/glob/2010/09/android-http.html Httpクライアントタイムアウトを設定する] | |
HttpPost HttpGet = new HttpGet(uri); | HttpPost HttpGet = new HttpGet(uri); | ||
HttpParams httpParms = new BasicHttpParams(); | HttpParams httpParms = new BasicHttpParams(); | ||
923行目: | 926行目: | ||
DefaultHttpClient client = new DefaultHttpClient(httpParms); | DefaultHttpClient client = new DefaultHttpClient(httpParms); | ||
− | + | Http[[R]]esponse response = client.execute(httpPost); | |
===MIMEマルチパートでファイルをアップロードする=== | ===MIMEマルチパートでファイルをアップロードする=== | ||
950行目: | 953行目: | ||
parms.add(new BasicNameValuePair("lat", this.lat)); | parms.add(new BasicNameValuePair("lat", this.lat)); | ||
parms.add(new BasicNameValuePair("lng", this.lng)); | parms.add(new BasicNameValuePair("lng", this.lng)); | ||
− | post.setEntity(new UrlEncodedFormEntity(parms, HTTP.UTF_8)); | + | post.setEntity(new UrlEncodedFormEntity(parms, [[HTTP]].UTF_8)); |
: | : | ||
} catch (UnsupportedEncodingException e) { | } catch (UnsupportedEncodingException e) { | ||
964行目: | 967行目: | ||
parms.add(new BasicNameValuePair("lon", String.valueOf(loc.getLongitude()))); | parms.add(new BasicNameValuePair("lon", String.valueOf(loc.getLongitude()))); | ||
parms.add(new BasicNameValuePair("message", msg)); | parms.add(new BasicNameValuePair("message", msg)); | ||
− | post.setEntity(new UrlEncodedFormEntity(parms, HTTP.UTF_8)); | + | post.setEntity(new UrlEncodedFormEntity(parms, [[HTTP]].UTF_8)); |
DefaultHttpClient httpClient = new DefaultHttpClient(); | DefaultHttpClient httpClient = new DefaultHttpClient(); | ||
− | + | Http[[R]]esponse response = httpClient.execute(post); | |
InputStream in = response.getEntity().getContent(); | InputStream in = response.getEntity().getContent(); | ||
− | + | Buffered[[R]]eader reader = new Buffered[[R]]eader(new InputStream[[R]]eader(in)); | |
String l = null; | String l = null; | ||
while((l = reader.readLine()) != null) { | while((l = reader.readLine()) != null) { | ||
987行目: | 990行目: | ||
==NDK== | ==NDK== | ||
*[http://typea.info/blg/glob/2012/02/android-ndk.html ネイティブライブラリを利用するため NDK を設定する] | *[http://typea.info/blg/glob/2012/02/android-ndk.html ネイティブライブラリを利用するため NDK を設定する] | ||
− | ==Google App Engine== | + | ==[[Google App Engine]]== |
===開発環境の構築=== | ===開発環境の構築=== | ||
*[http://typea.info/blg/glob/2010/08/android-gae-windows7.html Android (実機) と GAE を連携させるためのデバッグ環境を Windows7 に構築] | *[http://typea.info/blg/glob/2010/08/android-gae-windows7.html Android (実機) と GAE を連携させるためのデバッグ環境を Windows7 に構築] | ||
− | ===Google アカウントの利用=== | + | ===[[Google]] アカウントの利用=== |
*[http://typea.info/blg/glob/2010/08/android_google_gae.html Android アプリから Google アカウントを利用して GAE アプリケーションを利用する] | *[http://typea.info/blg/glob/2010/08/android_google_gae.html Android アプリから Google アカウントを利用して GAE アプリケーションを利用する] | ||
*[http://typea.info/blg/glob/2010/09/android-gae.html Android アプリから、GAE 開発サーバーのアカウントを利用] | *[http://typea.info/blg/glob/2010/09/android-gae.html Android アプリから、GAE 開発サーバーのアカウントを利用] | ||
1,003行目: | 1,006行目: | ||
===画像=== | ===画像=== | ||
====読み込み・キャッシュ==== | ====読み込み・キャッシュ==== | ||
− | *https://github.com/nostra13/Android-Universal-Image-Loader | + | *https://github.com/nostra13/[[Android]]-Universal-Image-Loader |
==広告== | ==広告== | ||
− | ===[Android AdMob] | + | ===[[Android AdMob|AdMob]]=== |
− | **[Android AdMob] | + | **[[Android AdMob|AdMob]] |
==公開== | ==公開== | ||
− | ===Android マーケット=== | + | ===[[Android]] マーケット=== |
*[http://typea.info/blg/glob/2010/07/android-1.html Android マーケットに開発者登録] | *[http://typea.info/blg/glob/2010/07/android-1.html Android マーケットに開発者登録] | ||
===SDカードにインストールを許可=== | ===SDカードにインストールを許可=== | ||
− | * | + | *[[Android]]Manifest.xml に installLocation を指定 ([[Android]] SDK 2.2から対応) |
android:installLocation="auto" | android:installLocation="auto" | ||
1,044行目: | 1,047行目: | ||
以下の様なエラーがでて実行できない | 以下の様なエラーがでて実行できない | ||
Your project contains error(s), please fix them before running your application. | Your project contains error(s), please fix them before running your application. | ||
− | Description | + | Description [[R]]esource Path Location Type |
Error generating final archive: java.io.FileNotFoundException: C:\Users\piroto\workspace\EitangoroidPro\bin\resources.ap_ does not exist | 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を参考に以下の手順で解決 | http://www.yukun.info/blog/2012/01/android-eclipse-build-error.htmlを参考に以下の手順で解決 | ||
− | *Window - Android SDK Manager から、インストール済みのSDKを最新にUpdate | + | *Window - [[Android]] SDK Manager から、インストール済みのSDKを最新にUpdate |
*eclipse.exe -clean を実行 | *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 === |
− | Android requires compiler compliance level 5.0 or 6.0. Found '1.4' instead. Please use Android Tools > Fix Project Properties. | + | [[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 等 適切なものに | *Compiler compliance level を 1.6 等 適切なものに | ||
− | *Android Tools > Fix Project Properties | + | *[[Android]] Tools > Fix Project Properties |
*リビルド | *リビルド | ||
2021年7月30日 (金) 16:36時点における最新版
目次
- 1 Android Tips
- 2 概要
- 3 開発環境
- 4 エミュレータ
- 5 画面
- 6 App ウィジェット
- 7 イベント
- 8 ダイアログ
- 9 Activity
- 10 Service
- 11 Fragment
- 12 非同期処理
- 13 View
- 14 検索
- 15 ContentProvider
- 16 プロパティ
- 17 レイアウト
- 18 インテント
- 19 トースト
- 20 ノーティフィケーション
- 21 メニュー
- 22 パーミッション
- 23 assetリソース
- 24 文字列リソース
- 25 ファイル
- 26 データベース
- 27 画像
- 28 アイコン
- 29 描画
- 30 デバッグ
- 31 入力
- 32 センサー
- 33 バイブレーター
- 34 カメラ
- 35 サウンド
- 36 電源管理
- 37 アニメーション
- 38 非同期処理
- 39 Web
- 40 9Patch
- 41 Dropbox
- 42 NDK
- 43 Google App Engine
- 44 ライブラリ
- 45 広告
- 46 公開
- 47 トラブルシュート
Android Tips
概要
ブログ
書籍
基本
Android 一連の手順概要
インストール
SDKのインストール
SDK Manager に APIの一覧が表示されない場合
- Tools - Options からForce にチェックを入れ、HTTP接続を可能にする
ADT Eclipse プラグイン
環境構築手順
JDKのインストールから、Eclipse の日本語化まで
SDKのインストールから、エミュレータの作成まで
実機デバッグ(ADBドライバのインストール)
Eclipse Git プラグインの導入
Eclipse プロジェクトの作成とSDKソースコードをEclipseから閲覧可能に
Ubuntuに開発環境を構築
UbuntuでADTプラグインインストールエラー
Ubuntu ADBドライバに実機を認識させる
開発環境
GAE
Android (実機) と GAE を連携させるためのデバッグ環境を Windows7 に構築する
SDK ソースコード
Gitのインストール(Linux)
# git clone git://android.git.kernel.org/platform/frameworks/base.git
ブラウズ
Eclipse
Eclipse 3.6.1 のコード補完で固まる対処
以下のパッチをEclipseにあてる(解凍して上書き)
エミュレータ
起動時の実際のサイズを指定する
- AVD Manager から、Start the selected AVD を選択
- 表示されたダイアログの Scale display to real size をチェック
- screen size にインチサイズを設定
画面
画面モード(縦、横)が変わらないように設定
http://www.hakkaku.net/articles/20090831-579
- XML の manifest/application/activity の属性、android:screenOrientation を、"portrait" に設定すると、縦画面のまま回転しなくなります。
設定値
- "portrait" … 縦画面で固定
- "landscape" … 横画面で固定
- "unspecified" … デバイス任せ
画面モード(縦、横)が変わる、変わらないを動的に変更
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); }
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);
画面の向きを取得する
<blockquote>API Level 8 以降は getRotation () を使うこと 0:portrait, 1:landscape</blockquote>
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);
<blockquote>逆の場合、add と clear を変える</blockquote>
XML
- AndroidManifest.xml に指定
- タイトルバーを非表示、フルスクリーン
<activity : android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
UIについて
設定画面を作成する
スタイル
色定義を行い使用する
values/colos.xml を定義
<?xml version="1.0" encoding="utf-8"?> <resources> <color name="white">#FFFFFF</color> <color name="lightgrey">#C0C0C0</color> </resources>
使い方(Activity内)
txtHoge.setTextColor(getResources().getColor(R.color.lightgrey));
<blockquote>txtHoge.setTextColor(R.color.lightgrey) とするのは、色の値として、リソースIDが渡されるためNG</blockquote>
EditText に最初にフォーカスがあたり、IMEが自動起動してしまうのを抑制
@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 ウィジェットの作り方
イベント
EditTextの変更を検知
public void addTextChangedListener (TextWatcher watcher)
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); }
ダイアログ
確認ダイアログ
ファイル削除確認
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(); }
プログレスダイアログ
カスタムダイアログ
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);
<blockquote>データの受け渡しには、Intent.putExtra を利用</blockquote>
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 の状態を一時的に保存する
コンフィグレーション
- デバイスのコンフィグレーションが変更されたら、UIはそのコンフィグレーションにマッチするように更新する必要があるため、Activitiは再スタートされる
- コンフィグレーションの変更があってもActivityの再スタートを避けたい場合、マニフェストにandroid:configChanges属性を追加
android:configChanges="locale|orientation|"
ArrayAdapter に ラジオボタンを置く
TabActivity(タブによるアクティビティ切り替え) サンプル
ListActivity(リスト表示画面)サンプル
PreferenceActivity(設定画面の作成) サンプル
透明なActivityを作成する
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
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() を利用する
非同期処理
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のコンテキストメニュー選択時にアイテムを取り出す
ListViewのコンテキストメニュー選択時にアイテムを取り出す
カスタムViewを利用する
<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); } }
ページめくり
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; } }
ダイアログボックス
検索
検索インターフェースの作成
ContentProvider
連絡先の取得と電話をかける
プロパティ
単行
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 と連携する
テキストエディタ等にファイルの処理をさせる
setDataAndType を使って、ファイルのURIとMIMEタイプを同時に渡す
<blockquote>個別に渡すと後に渡した方しか有効にならない(バグ?仕様 Android2.1 X06HT)</blockquote>
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);
ブロードキャストされたインテントを受け取る
トースト
トーストをカスタマイズして吹き出しをつくる
ノーティフィケーション
起動しているActivityを全面に表示させる
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); } }
パーミッション
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
アイコン
ランチャーアイコンガイドライン
描画
画面サイズの取得
- 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);
文字列領域の高さにより、フォントサイズを決定する
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);
デバッグ
テスト
実機でデバッグ
- AndroidManifest.xml Debuggable = true
UbuntuでデバイスIDが????と表示され実機デバッグできない
- 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
TraceView
- トレース開始位置に以下を記述
<blockquote>SDカードがマウントされていること</blockquote>
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}}
スクリーンキャプチャ
カメラアプリで、FileNotFoundException
<blockquote>カメラアプリで、FileNotFoundException /sys/android_camera2/htcwc が発生したら、端末の再起動を行う。</blockquote>
SDKソースコードのステップ実行
入力
IME ソフウェアキーボードを消す
public void onClick(View v) { // ボタンを押したら、ソフウェアキーボードを消す InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(v.getWindowToken(), 0); }
マルチタッチ(ピンチ)
センサー
搭載センサーの値を取得
GPS(緯度・経度)
バイブレーター
宣言
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);
<blockquote>Froyo 化してからは、上記方法が使えなくなった(むしろ使えていたのがおかしかった!?)ため、以下の対応</blockquote>
カメラプレビューが横向きに表示されてしまう!の対応
カメラプレビューを縦向きにすると画面描画の座標が訳わからなくなる対応
上記を行うと、Viewに描画するときに座標が混乱してしまう対応。
サウンド
ハードウェアから、音量を制御
- サンプルソース
- ハードウェアから、音量を制御させるには、以下の記述が必要
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; }
ヘッドフォント着脱を検知する
電源管理
スリープ状態からの復帰、キーロック解除
例
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に表示する
Web
Httpクライアントタイムアウトを設定する
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マルチパートでファイルをアップロードする
以下を入手
<blockquote>httpmime は、httpcomponents-client に httpclient とともにアーカイブされている。</blockquote>
サンプル
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の使い方(吹き出しをつくる)
Dropbox
NDK
Google App Engine
開発環境の構築
Google アカウントの利用
- Android アプリから Google アカウントを利用して GAE アプリケーションを利用する
- Android アプリから、GAE 開発サーバーのアカウントを利用
- Android からGoogleアカウント認証でGAEアクセスするとServer Error になってしまう
ライブラリ
チャート
UI
カードUI
画像
読み込み・キャッシュ
- https://github.com/nostra13/Android-Universal-Image-Loader
広告
AdMob
公開
Android マーケット
SDカードにインストールを許可
android:installLocation="auto"
値 | 内容 |
---|---|
internalOnly | 内蔵メモリへのインストールのみ許可 |
auto | 内蔵メモリ優先 |
preferExternal | SDカードを優先 |
アプリ内課金
トラブルシュート
Error generating final archive: Debug certificate expired on エラーでコンパイルできない
- ユーザーディレクトリの、.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
© 2006 矢木浩人