!!!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 に指定 *タイトルバーを非表示、フルスクリーン !!最大化表示(ステータスバーを隠す) ::コード getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); ""逆の場合、add と clear を変える ::XML *AndroidManifest.xml に指定 *タイトルバーを非表示、フルスクリーン !!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 を定義 <?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)); ""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 セクションの中に以下を記述 ::インテントを利用して呼び出し Intent intent = new Intent(getApplicationContext(),              OtherActivity.class); startActivity(intent); ""データの受け渡しには、Intent.putExtra を利用 ::Activity.onCreate Spinner spFontSize = (Spinner) findViewById(R.id.spn_font_size); ArrayAdapter 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 に以下の内容を記述 !AndroidManifest.xml のActivityのtheme属性にに以下の記述 !!Activity をダイアログとして表示する *@android:style/Theme.Dialog を利用 !!!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 lv = getListView(); lv.setDivider(new ColorDrawable(Color.GREEN)); lv.setDividerHeight(1); !!ListViewのID *ListViewのIDは、以下の様にする。 *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を作成しレイアウトは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 70 80 90 100 ::Activity // フォントサイズ spFontSize = (Spinner) findViewById(R.id.spn_font_size); ArrayAdapter 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 : !!!インテント !!暗黙的 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が生成されてしまう。 : ::インテントを設定し、通知を行う 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例 経度 %9.6f、緯度 %9.6f 付近のメッセージ ::コード例 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); ::パーミッション !!!カメラ !!画像が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(); } ::必要なパーミッション !!!アニメーション !!サンプル設定ファイルの場所 {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 parms = new ArrayList(); 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 parms = new ArrayList(); 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