- 投稿日:2020-03-24T21:04:20+09:00
AndroidのPR作成前のチェックリスト
PR作成の際に
PRを作成する際に最近自分が自分がやりがちなミスを列挙します。
深い設計や効率の良いコードは難しくとも単純ミスを減らすためにのチェックリストです。PR作成前の動作確認と、せめてこのチェックリストは見返すようにしています。
チェックリスト
- レイアウトファイルやManifestファイルはなるべく閉じタグをなくす
中に他のタグを挟む必要が無い場合は、として、コンパクトにタグを記述する。
- Log.dなどデバッグ用のコードの削除
- 日本語文字列やURLはリソースファイルを使って表記
- アップロードキーなど、コミットに含めるべきで無いファイルをGit管理に含めていないか?
- 変数名、メソッド名はUpperSnakeCaseで命名する
- レイアウトファイルのインデント幅は統一されているか?
- 変数やメソッドでprivate宣言に変更すべきところが残っていないか?
- プロジェクトでktlintフォーマッターを導入している場合は、フォーマットコマンド実行
- Androidに限らず、マージやリベース時のコンフリクト解消時のミス
- 各ファイルの右上のチェックマークがOKになっているか
このチェックマークがいつもエラーを検知してくれたり、知らなかったメソッドをサジェスションしてくれていることに気付けて助かっています。特にライブラリをアップデートした場合など、コードを変更する必要が出てくることが多いです。
PR作成後
PR作成後もすぐにレビュー依頼をするのではなく、PRのfile changedでPR中で変更したファイルを全て確認する。
PRに含める全ての変更が見れるので、最後の最後に誤りに気付けるかもしれません。自分の場合はここでレイアウトファイルのインデント崩れに気付けたりします。
- 投稿日:2020-03-24T20:09:26+09:00
Android9アプリ検証中に、プッシュ通知で何でポップアップされない?ってなったときに
アプリの動作検証担当になってここ数ヶ月、個人的には信じられない(単に直感的でない)ことにはまって数時間困った件を残します。
同じことで悩んでいる人の助けになれば幸いです。
事象
Android 9端末(Galaxy A20 SCV46とALLDOCUBE iPlay10 Pro U1006H)にて、
Javaで開発されたアプリの通知機能を検証するために、
インストール直後、通知は受け取れる(ステータスバーにはアイコンは出ている)が、場合によってポップアップされたりされなかったりする???
という悩ましい現象が発生。原因
Androidのアプリ設定にて、検証中のアプリの設定画面を開いていた。
という至極シンプルなことだった。対処方法
通知動作を確認するときは、アプリの設定画面を開いているプロセスを立ち上げっぱなしになっていないことを確認すること。
立ち上げているなら、落とすこと。最後に
Androidのアプリ設定周りの内部仕様をわかっていないので、挙動だけで判断するに、
本来なら初回通知受診時に送信元が設定したパラメータを元に通知設定が作成されるはずが、
アプリの設定画面を開いた状態で通知を受け取ってしまうと、パラメータ値を無視してOS側のデフォルト値を使ってアプリ通知設定が出来上がってしまう。
すなわち、「音声のみ」の通知になるため、ポップアップされなかった。動作検証で通知機能をちゃんと確認しようとした場合、確実にOSのアプリ設定画面は開くことになるはずなので、
悩まないで済むように、もしくは、その現象に気付けるようにこの記事を残す。追伸
こういう大事なことは、Androidの開発者向けの説明資料には掲載されているのかもしれないが、今の所見つけられていない。。。
- 投稿日:2020-03-24T13:51:12+09:00
【Android】 Broadcast Recieverでintentを受け取る
Broadcast Recieverとは?
- BroadcastReceiver(ブロードキャストレシーバー)とは、ブロードキャストしたインテントを受け取る仕組みのこと
- OSのAndroidシステム側でブロードキャストされるイベント(スクリーンのON/OFFなど)以外でも、自分で作成したアプリでも独自のインテントを生成してブロードキャストできる
intentとは?
- intentとは、アプリケーションの中の1つ1つの機能のこと。たとえばアプリケーション同士や、アプリケーションとウィジェット、アプリケーションとシステムを橋渡しする仕組みのこと
- BroadcastRecieverを使わずとも、intentだけでも利用が可能で、例えば電話をかけたりカメラを起動することもできる
- BroadcastRecieverでは、例えばアプリをインストールした際などに発生するintentを検知することができます。例えば...
- スクリーンのON/OFFを検知する
- 電池の状態を検知する
- アプリのインストールを検知する
- 振動を検知する 等
使ってみよう
アクティビティからサービスを起動 → サービスでレシーバーを登録 という流れでやってみました
MyReceiver.javapublic class MyReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction() != null) { if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) { Log.d("registerReceiver: ", "ON"); } if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) { Log.d("registerReceiver: ", "OFF"); } } } }MyActivity.javapublic class MyActivity extends Activity { Button startButton; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); startButton = (Button)findViewById(R.id.start_button); startButton.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { getActivity().startForegroundService(new Intent(getActivity(), MentalHealthService.class)); } else { getActivity().startService(new Intent(getActivity(), MentalHealthService.class)); } } } }MyService.javapublic class MyService extends Service { private MyReceiver mReceiver; private IntentFilter mIntentFilter; @Override public void onCreate() { super.onCreate(); // Receiver登録を実行 registerScreenReceiver(); } @Override public void onDestroy() { super.onDestroy(); // Receiverを解除 unregisterReceiver(mReceiver); } @Override public int onStartCommand(Intent intent, int flags, int startId) { startInForeground(); return START_STICKY; } // receiverを登録 private void registerScreenReceiver() { mReceiver = new MyReceiver(); mIntentFilter = new IntentFilter(); mIntentFilter.addAction(Intent.ACTION_SCREEN_ON); mIntentFilter.addAction(Intent.ACTION_SCREEN_OFF); registerReceiver(mReceiver, mIntentFilter); } // サービスをアライブさせるために通知を生成 private void startInForeground() { Intent notificationIntent = new Intent(this, MainActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); NotificationCompat.Builder builder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID) .setSmallIcon(R.mipmap.ic_launcher) .setContentTitle(getResources().getString(R.string.app_name)) .setContentText("test notification") .setTicker(getResources().getString(R.string.app_name)) .setContentIntent(pendingIntent); Notification notification = builder.build(); if (Build.VERSION.SDK_INT >= 26) { NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID , NOTIFICATION_CHANNEL_NAME , NotificationManager.IMPORTANCE_DEFAULT); channel.setDescription(NOTIFICATION_CHANNEL_DESC); NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); if (notificationManager != null) { notificationManager.createNotificationChannel(channel); } } startForeground(NOTIFICATION_ID, notification); } }解説
- MyReceiverのonReceiveにて、intent.getAction()が登録したintentFilterのアクションと合致したらログを出す様に処理
- MyActivityにボタンを設置。ボタンを押すとサービスを起動するという単純な構造
- MyService内でReceiverの登録を行なっている。startInForegroundはForegroundService用でとりあえず実装(あまり気にしなくていいです)
- サービスが起動している間に、スクリーンをOn/Offにしたらその度にログが出る
備考
- 最ライフログやヘルスケアのアプリをよく見るので、どんな風にデータを集計しているのか気になったところ、intentを使っているパターンが多い様に感じたので調査してみた
- 今回紹介した以外にも、intentはものすごく沢山あるので、アプリによっては有用なものもある...かもしれない