Android Oで色々と機能が追加されたので、色々試してみたいですが、先ずは「Android O Features and APIs」の冒頭で紹介されているNotificationsのNotification Channelsを試してみました。
以前の投稿でAndroid Studio 2.4 Preview3のインストールとPixelエミュレータの起動まではできたので、その環境で実装していきます。まぁ、基本的には公式のサンプル通りですが。
Android Studioのメニューから「File > New > New Project」と選択して適当にプロジェクトを作ります。プロジェクト名は分かりやすく(?)「Oreo」にしました。Activityの種類は「Empty Activity」にしました。
途中、Android Studioのアップデートがあるというポップアップが表示されたので、すかさずアップデート!Preview4になりました… と思ったらいきなりエラーメッセージが!「Could not initialize class com.android.ide.common.util.ReadWriteProcessLock」
公式サイトにも「Known Issues」として取り上げられていました。要は「再起動してね」と。
https://androidstudio.googleblog.com/2017/04/android-studio-24-preview-4-is-now.html
めげずに(?)Android Studioを再起動して開発を続けます。NotificationChannelクラスのリファレンスも見つつ。ページ背景にはひたすら「PREVIEW」の文字が…(2017年4月時点)全体の色も緑でなく黄色になっています。いずれ正式に緑になるのでしょう。
Notificationに「チャンネル」という、分類のような要素を紐付ける事が可能になったわけですが、チャンネルには更に「グループ」を割り当てる事ができます。今回は、チャンネルとグループ、両方を生成し、Notificationに適用するアプリにしてみます。チャンネルとグループの設定はアプリの画面から入力できるようにして、色々な設定が試せるようにしてみます。
先ずは画面から…と、何とAndroid Studio2.4からでしょうか、ActivityのデフォルトレイアウトがRelativeLayoutでなくConstraintLayoutになっています。うーん、まだ慣れてないのに…なにはともあれチャンネルとグループの情報を入力できる画面を作成してみます。完成した画面はこんな感じで:
画面下部の「Hello World!」は残骸です、気にしないでください…
UI部品が多いので、xmlがちょっと長くなってしまいました。
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="jp.co.techfirm.oreo.MainActivity"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintHorizontal_bias="0.383" app:layout_constraintVertical_bias="0.819" /> <EditText android:id="@+id/editText1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:ems="10" android:hint="Channel_Group" android:text="" android:layout_marginTop="8dp" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent" android:layout_marginStart="8dp" /> <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:text="create group" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toBottomOf="@+id/editText1" app:layout_constraintStart_toStartOf="parent" android:layout_marginStart="8dp" /> <EditText android:id="@+id/editText2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:ems="10" android:hint="Channel_ID" android:text="" android:layout_marginTop="8dp" app:layout_constraintTop_toBottomOf="@+id/button1" app:layout_constraintStart_toStartOf="parent" android:layout_marginStart="8dp" /> <Button android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="create channel" android:layout_marginTop="8dp" app:layout_constraintTop_toBottomOf="@+id/editText2" app:layout_constraintStart_toStartOf="parent" android:layout_marginStart="8dp" /> <EditText android:id="@+id/editText3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:ems="10" android:hint="title" android:text="" android:layout_marginTop="8dp" app:layout_constraintTop_toBottomOf="@+id/button2" app:layout_constraintStart_toStartOf="parent" android:layout_marginStart="8dp" /> <EditText android:id="@+id/editText4" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:ems="10" android:hint="content" android:text="" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toBottomOf="@+id/editText3" app:layout_constraintStart_toStartOf="parent" android:layout_marginStart="8dp" /> <EditText android:id="@+id/editText5" android:layout_width="wrap_content" android:layout_height="wrap_content" android:ems="10" android:hint="Notification_ID" android:inputType="numberDecimal" android:layout_marginTop="8dp" app:layout_constraintTop_toBottomOf="@+id/editText4" app:layout_constraintStart_toStartOf="parent" android:layout_marginStart="8dp" /> <Button android:id="@+id/button3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:text="post" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/editText5" android:layout_marginTop="9dp" /> </android.support.constraint.ConstraintLayout>
画面ができたら、Activityの処理を実装する前にgradleの設定をしておこうと思います。あちこちに「O」の文字が指定されていますね。
apply plugin: 'com.android.application' android { compileSdkVersion 'android-O' buildToolsVersion '26.0.0-rc1' defaultConfig { applicationId "jp.co.techfirm.oreo" minSdkVersion 'O' targetSdkVersion 'O' versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) compile 'com.android.support:appcompat-v7:26.0.0-alpha1' testCompile 'junit:junit:4.12' compile 'com.android.support.constraint:constraint-layout:1.0.2' }
Notificationに表示するアイコンを作ってみました。
The Gimpで「の」の文字を描いてみました、背景を透過するのがポイントでしょうか。公式ガイドラインに沿ってサイズは48 x 48pxにしました。
そして遂にActivityの実装です。グループを作ってからチャンネルを作り、チャンネルができたらNotificationを表示できるようにしました。グループ名の先頭には「雑談:」という文字を付けて、チャンネル名の先頭には「24ちゃんねる:」という文字を付けるようにしました、同じ値を入れた時に区別したかっただけですが。
public class MainActivity extends AppCompatActivity { private EditText inputChId; private EditText inputChGrp; private EditText inputTitle; private EditText inputContent; private EditText inputNotifId; private Button btnCreCh; private Button btnCreGrp; private Button btnPost; private String channelId = null; private String grpId = null; private NotificationManager notificationManager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // コンポーネント取得。 inputChGrp = (EditText)findViewById(R.id.editText1); inputChId = (EditText)findViewById(R.id.editText2); inputTitle = (EditText)findViewById(R.id.editText3); inputContent = (EditText)findViewById(R.id.editText4); inputNotifId = (EditText)findViewById(R.id.editText5); btnCreGrp = (Button)findViewById(R.id.button1); btnCreCh = (Button)findViewById(R.id.button2); btnPost = (Button)findViewById(R.id.button3); notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE); // ボタン押下でChannel生成。 btnCreCh.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { channelId = inputChId.getText().toString(); // 設定画面などでユーザーに見せるチャンネル名。識別できるようID値を付加してみました。 CharSequence channelName = "24ちゃんねる:" + inputChId.getText(); /* 指定できる値は以下7種類。 NotificationManager.IMPORTANCE_UNSPECIFIED (-1000); NotificationManager.IMPORTANCE_NONE (0); NotificationManager.IMPORTANCE_MIN (1); NotificationManager.IMPORTANCE_LOW (2); NotificationManager.IMPORTANCE_DEFAULT (3); NotificationManager.IMPORTANCE_HIGH (4); NotificationManager.IMPORTANCE_MAX (5); */ int importance = NotificationManager.IMPORTANCE_DEFAULT; NotificationChannel mChannel = new NotificationChannel(channelId, channelName, importance); mChannel.enableLights(true); mChannel.setLightColor(Color.RED); mChannel.enableVibration(true); mChannel.setGroup(grpId); mChannel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400}); notificationManager.createNotificationChannel(mChannel); btnPost.setEnabled(true); // notificationをpostしてok。 } }); btnCreCh.setEnabled(false); // グループを作成するまでは無効に。 // ボタン押下でChannel Group生成。 btnCreGrp.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { grpId = inputChGrp.getText().toString(); // 設定画面などでユーザーに見せるグループ名。識別できるようにID値を付加してみました。 CharSequence grpName = "雑談:" + inputChGrp.getText(); notificationManager.createNotificationChannelGroup(new NotificationChannelGroup(grpId, grpName)); btnCreCh.setEnabled(true); // チャンネルを作ってok。 } }); btnPost.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { int notificationId = 1; notificationId = Integer.parseInt(inputNotifId.getText().toString()); // アイコンサイズはとりあえず48x48にしてみた:https://developer.android.com/guide/practices/ui_guidelines/icon_design_status_bar.html Notification notification = new Notification.Builder(MainActivity.this) .setContentTitle(inputTitle.getText()) .setContentText(inputContent.getText()) .setSmallIcon(R.drawable.icon_no) .setChannel(channelId) .setGroup(grpId) .build(); notificationManager.notify(notificationId, notification); } }); btnPost.setEnabled(false); // チャンネルを作成するまでは無効に。 } }
アプリを起動して、各種値を入力して「POST」ボタンを押せば…
↓画面の左上にNotificationの「の」アイコンが表示されました!
Notification部分をロングタップすると設定が表示されます。
これでNotificationのグループやチャンネルを色々な設定で試せます。
グループは主にマルチユーザに対して有効な設定なようなので、マルチユーザを意識したアプリを作るまでは出番が少ないかもしれませんが…