android開発TIPSをまとめました。
androidのswitch文で「定数式が必要です」エラーが発生する対応
android開発で、switchのcase文にR.idを入れたらエラーになる場合があり、メニューの分岐処理等でよく発生する現象です。ライブラリプロジェクトにおいて、リソースフィールドを条件分岐に使用する場合は、switch ではなく if-else を使う必要があります。「ライブラリプロジェクト」とは Project → Properties → Android で Is Library にチェックを入れたプロジェクトのことです。
参考ページ:『Non-constant Fields in Case Labels』
setTargetFragmentを使った時、落ちた時の対応
(現象)
Activity→PreferenceBaseFragment→DialogFragmentで表示している時、1回目 or 2回目の回転で落ちてしまう現象です。最初、落ちる原因が不明だったが、1つずつ処理を出し入れして原因追究すると、回転対応の処理でsetTargetFragmentを使用していると落ちる事が分かりました。setTargetFragment処理部をコメントにすると、とりあえずは落ちなくなりましたが、setTargetFragmentを使用した本来の目的は達成できなくなってしまいます。
(原因)
ActivityのonCreateでPreferenceBaseFragmentのフラグメントを作成している事が問題でした。onCreateでFragmentの生成処理を記述しているため、回転の度にFragmentが生成され競合しているため、問題が発生しているようです。
参考ページ『PreferenceFragmentからDialogFragmentを表示し画面回転で例外発生』『FragmentをActivityに貼付ける』
(対応)
ActivityのonCreateで初回だけFragmentを生成するように変更しました。
1 2 3 4 5 6 7 8 9 |
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (savedInstanceState == null) { //フラグメント生成処理 } } |
AsyncTaskでプログレスダイアログで進捗表示する時について
AsyncTaskでProgressDialogを使用する時、onPreExecuteメソッド内でProgressDialogをインスタン化(new)してshow()メソッドを実行する場合が多いと思います(WEBページ上にあるほとんどのサンプルもこの通りだと思います)。ProgressDialogをインスタン化する時、ProgressDialogのコンストラクタにContextを与えますが、このContextは呼出しの元アクティビティのContextを与える必要があります。ActivityのContextを取得するには、(Activityを継承してるクラスで)thisを呼ぶ事になります。
Toolbar使用の注意点
ToobarはAndroid 5.0 (Lollipop)と同時に追加されたActionBarの代替となるコンポーネントで、アクティビティのテーマに影響します。
Toobarを使用するアクティビティに対して、AndroidManifest.xmlのactivityタグで「android:theme="@style/AppTheme.NoActionBar"」の指定を行う必要があります。
EventBus使用の注意点
Activityでイベントを受信するなら、onResume(もしくはonStart)でEventBus.getDefault().register(this);とすることでイベントの購読を行います。この際、onPause(もしくはonStop)でEventBus.getDefault().unregister(this);で購読解除を忘れないようにします。両者の設定をせず、@Subscribeアノテーションのメソッドのみをイベントハンドラとして登録している場合は、Activityの起動でエラーになるようです。
JAVAの4種類の内部クラスについて
(1)非staticな内部クラス
非staticな内部クラスは外部クラスへの暗黙的な参照を持ちます。その証拠として内部クラスのメソッド内から外部クラスのインスタンス変数にアクセス可能です。暗黙的な参照のためメモリリークの原因になることがあり、なるべく使用しないようにします。
(2)staticな内部クラス
staticな内部クラスは外部クラスへの参照を持ちません。そのため、内部クラスのメソッド内から外部クラスのインスタンス変数をアクセスすることは出来ません。また、staticな内部クラスは外部に定義したクラスとほぼ同様に扱うことが出来ますので、通常、内部クラスを定義する場合は、staticな内部クラスを使用した方が安全です。
(3)ローカルクラス
(4)無名クラス
Androidエミュレータについて
Androidエミュレータとしては、「Genymotion」が良いように感じました。
- Oracle VirtualBoxで実現している(Oracle VirtualBoxをインストールする必要があります)。
- Windows、Mac、Linuxで利用可能できます。
- 高速に動作すると感じます。
- 個人利用なら完全無料のようです。
(参考資料)
GenymotionにGoogle Playストアをインストールする方法
開発者向けオプションの「アクティビティを保持しない」について
このオプションを有効にすることで、常に最前面以外のアクティビティはすぐに破棄されるようになります。アクティビティ保持の厳格モードとして使用します。開発中は「アクティビティを保持しない」をONにする事で、アクティビティの破棄テストを常に行う事が可能になります。ただ、このアクティビティの破棄ですが、回転などによるconfiguration changeのログを表示ような動きでもなく、また、Low MemoryによるプロセスKILLの動きでもないようです。configuration changeのような動きであれば、Loaderも実行中タスクも破棄されませんし、Low MemoryによるプロセスKILLであれば、当然、Loaderも実行中タスクも破棄されます。当該アクティビティのみの破棄なので、Loaderは破棄されますが、実行中タスクは破棄されず、実行タスクの終了でonLoadFinishedが実行されない状況になるようです。
外部ストレージ保存
外部ストレージへの読み書きには2つのパーミッションが必要
(1) AndroidManifest.xml にusers-permissionの記述を入れる
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
(2) WRITE_EXTERNAL_STORAGE は dangerous permission なので、permission checkの実装が必要になります。これを実装するとユーザーに許可・不許可のダイアログを表示させ、ユーザーはいつでもアプリの許可設定を変更できます。テスト段階での確認をするだけならpermission checkをオミットすることができます。該当アプリを「設定」から探し「権限」の項目にあるストレージをenableにします。
(参考資料)
[Android] 外部ストレージにファイルを保存する WRITE_EXTERNAL_STORAGE
[Android] アプリ内にファイルを保存する FileOutputStream, FileInputStream
[Android] Runtime Permission, Dangerous Permission
実行時のパーミッション リクエスト(Runtime Permission) 色々まとめ
あらためてRuntime Permissionと実装方法をおさらいする
android:layout_weightが効かない場合
(1) layout_weightが効かない場合は、layout_width="0dp"を設定してみる。
(2) layout_weight属性はweightSum属性の親ウィジェットの残りのスペースを分け合って使う。
(参考資料)
レイアウト(5)-layout_weight属性とweightSum属性 親ウィジェットの残りのスペースを分け合って使う