目次
- Android Tips
- 概要
- 開発環境
- エミュレータ
- 画面
- App ウィジェット
- イベント
- ダイアログ
- Activity
- Service
- Fragment
- 非同期処理
- View
- 検索
- ContentProvider
- プロパティ
- レイアウト
- インテント
- トースト
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 clone git://android.git.kernel.org/platform/frameworks/base.git
- ブラウズ
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);
画面の向きを取得する
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);
}
}
- AndroidManifest.xml に指定
- タイトルバーを非表示、フルスクリーン
<activity :
android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
最大化表示(ステータスバーを隠す)
- コード
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
逆の場合、add と clear を変える
- 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));
txtHoge.setTextColor(R.color.lightgrey) とするのは、色の値として、リソースIDが渡されるためNG
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の変更を検知
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);
データの受け渡しには、Intent.putExtra を利用
- Activity.onCreate
Spinner spFontSize = (Spinner) findViewById(R.id.spn_font_size);
ArrayAdapter<CharSequence> spFontSizeAdapter
= ArrayAdapter.createFromResource(this,
R.array.ary_font_size,
android.R.layout.simple_spinner_item);
spFontSizeAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spFontSize.setAdapter(spFontSizeAdapter);
Activity の状態を一時的に保存する
コンフィグレーション
- デバイスのコンフィグレーションが変更されたら、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タイプを同時に渡す
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
- トレース開始位置に以下を記述
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
スクリーンキャプチャ
カメラアプリで、FileNotFoundException
カメラアプリで、FileNotFoundException /sys/android_camera2/htcwc が発生したら、端末の再起動を行う。
SDKソースコードのステップ実行
入力
IME ソフウェアキーボードを消す
public void onClick(View v) {
// ボタンを押したら、ソフウェアキーボードを消す
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
}
マルチタッチ(ピンチ)
センサー
搭載センサーの値を取得
バイブレーター
- 宣言
private Vibrator vib;
- 初期化
vib = (Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE);
- 利用
vib.vibrate(50L);
- パーミッション
<uses-permission android:name="android.permission.VIBRATE"></uses-permission>
カメラ
画像が90度回転してしまう
- カメラデバイスは向きを認識していないので、指定する必要がある
Camera.Parameters p = camera.getParameters(); p.setRotation(90); camera.setParameters(p);
Froyo 化してからは、上記方法が使えなくなった(むしろ使えていたのがおかしかった!?)ため、以下の対応
カメラプレビューが横向きに表示されてしまう!の対応
カメラプレビューを縦向きにすると画面描画の座標が訳わからなくなる対応
上記を行うと、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マルチパートでファイルをアップロードする
- 以下を入手
httpmime は、httpcomponents-client に httpclient とともにアーカイブされている。
- サンプル
DefaultHttpClient client = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(uri);
File upfile = new File(info.getPath());
MultipartEntity entity = new MultipartEntity();
entity.addPart("upload_file_name", new StringBody(upfile.getName()));
entity.addPart("upload_file_contents", new FileBody(upfile));
httpPost.setEntity(entity);
response = client.execute(httpPost);
HttpPost に標準的なパラメータを設定する
try {
HttpPost post = new HttpPost("http://hogehoge.com/hoge");
List<NameValuePair> parms = new ArrayList<NameValuePair>();
parms.add(new BasicNameValuePair("lat", this.lat));
parms.add(new BasicNameValuePair("lng", this.lng));
post.setEntity(new UrlEncodedFormEntity(parms, HTTP.UTF_8));
:
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Httpリクエストからレスポンスまでの概要
HttpPost post = new HttpPost("http://hogehoge.com/hoge");
List<NameValuePair> parms = new ArrayList<NameValuePair>();
parms.add(new BasicNameValuePair("lat", String.valueOf(loc.getLatitude())));
parms.add(new BasicNameValuePair("lon", String.valueOf(loc.getLongitude())));
parms.add(new BasicNameValuePair("message", msg));
post.setEntity(new UrlEncodedFormEntity(parms, HTTP.UTF_8));
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpResponse response = httpClient.execute(post);
InputStream in = response.getEntity().getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String l = null;
while((l = reader.readLine()) != null) {
buf.append(l + "\r\n");
}
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
Log.e(LocationBasedMessageApplication.TAG, buf.toString());
}
9Patch
9Patchの使い方(吹き出しをつくる)
Dropbox
NDK
Google App Engine
開発環境の構築
Google アカウントの利用
- Android アプリから Google アカウントを利用して GAE アプリケーションを利用する
- Android アプリから、GAE 開発サーバーのアカウントを利用
- Android からGoogleアカウント認証でGAEアクセスするとServer Error になってしまう
ライブラリ
チャート
UI
カードUI
画像
読み込み・キャッシュ
広告
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

YAGI Hiroto (piroto@a-net.email.ne.jp)
twitter http://twitter.com/pppiroto
Copyright© 矢木 浩人 All Rights Reserved.