Android アプリ開発 「MATRIX」

Androidアプリの開発に役立つサンプル集



「通知」をタップした時に任意の処理を実行する方法

通知をタップして処理を実行

今回は「通知」をタップした時に画面(Activity)を表示するのではなく、「任意の処理を実行する」というサンプルを作ってみたいと思います。基本的には以下のようなフローになっています。

<流れ>

① テキストボタンを持った「通知」を作成して表示する
        ↓
② 通知のテキストをタップした時に Intent を発信する
        ↓
③ 待機していたサービスが Intent を受け取りブロードキャストレシーバーに送信
        ↓
④ ブロードキャストレシーバーがフィルターを判別して任意の処理を実行 

 

サンプルコード①(Main.activity)

ここには通知を発行する「onCreate」だけでなく、通知から Intent を受け取りブロードキャストレシーバーに処理を依頼する「サービス」と、サービスからの依頼を受け取り処理を実行する「ブロードキャストレシーバー」など、必要なものがすべて含まれています。※詳細はコード内のコメントを参考にしてください。 

public class MainActivity extends AppCompatActivity {

private NotificationCompat.Builder builder;
private NotificationManager manager;
private static TextView textView;

///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////メイン///////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

//レイアウトXMLをセット
setContentView(R.layout.activity_main);

//表示用のテキストビューを操作するための準備
textView = (TextView)findViewById(R.id.text);

//通知の準備
builder = new NotificationCompat.Builder(getBaseContext(), "c1"); //通知ビルダーのインスタンスを生成
builder.setSmallIcon(R.drawable.bar_icon); //バーに表示するアイコンの指定
builder.setContentTitle("Sample Title"); //通知タイトル
builder.setContentText("Sample Text"); //通知する内容
builder.setWhen(System.currentTimeMillis()); //通知時間
builder.setAutoCancel(true); //オートキャンセル(これだけでは動作しない)

//通知にタップで反応するテキストを追加
Intent test_intent = new Intent(); //空のインテントを準備
test_intent.setAction("test_action"); //ブロードキャストが受信した時に識別する「タグ」のようなもの
test_intent.putExtra("sample_name", "sample value"); //ブロードキャストするデータをセット
PendingIntent test_pendingIntent = PendingIntent.getBroadcast(getBaseContext(), 0, test_intent, PendingIntent.FLAG_UPDATE_CURRENT); //インテントペンディングインテントに組み込む
builder.addAction(R.drawable.bar_icon, "ここを押すとブロードキャストする", test_pendingIntent); //上で作ったペンディングインテントActionとして追加する

manager = (NotificationManager)getBaseContext().getSystemService(Service.NOTIFICATION_SERVICE); //通知マネージャーを準備
manager.notify(1, builder.build()); //通知開始

Intent intent = new Intent(getBaseContext(), MyService.class); //サービス開始用のインテントを生成
startService(intent); //サービスを開始して待機
}

///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////サンプル処理/////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////

public static void sample() {
textView.setText("完了しました!"); //テキストを変更する
}

///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////サービス////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////

public static class MyService extends Service {

//自動作成される
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}

//最初に実行される
@Override
public int onStartCommand(Intent intent, int flags, int startId) {

IntentFilter filter = new IntentFilter(); //空のインテントフィルターを準備
filter.addAction("test_action"); //受信するActionを指定("test_action"というアクションを受信してブロードキャストレシーバーに送る)
registerReceiver(MyReceiver, filter); //レシーバーとフィルターを登録してサービス開始

return super.onStartCommand(intent, flags, startId); //自動生成のまま
}
}

///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////ブロードキャストレシーバー////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////

public static BroadcastReceiver MyReceiver = new BroadcastReceiver() {

//サービスから処理のオーダーを受け取る
@Override
public void onReceive(Context context, Intent intent) {

if(intent.getAction().equals("test_action")) { //"test_action"というインテントフィルターが付いた依頼を処理

//ここは別スレッドなのでHandlerを利用してUIスレッドにアクセスしなければならない
Handler handler = new Handler();
handler.post(new Runnable() {
@Override
public void run() {
sample(); //任意の処理(この場合はサンプルメソッドを実行
}
});
}
}
};
}

 

サンプルコード②(AndroidManifest.xml) 

マニフェストファイルには「サービス」と「ブロードキャストレシーバー」の情報を <application></application> タグ内に追加する必要があります。これを書かないと正しく動かないので注意してください。※赤文字の2行。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="htt p://schemas.android.com/apk/res/android"
package="sample.test.co.jp">

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<!-- 追記した部分 -->
<service android:name=".MainActivity$MyService" />
<receiver android:name=".MyReceiver" />

</application>

</manifest>

 

サンプルコード③(activity_main.xml)※抜粋

レイアウトファイルにはテキストを表示する「TextView」があるだけです。通知のテキストをタップした時に、この TextView のテキストを「Hello World!」から「完了しました!」に変更します。 

<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
android:textColor="#000000"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />

 

サンプルの実行結果

① 起動すると画面の中央に「Hello World!」が表示され、すでに通知が届いている状態です。

f:id:vw-dsg:20180124111937j:plain

 

② 通知を下に引き出して確認すると、下側にタップ可能のテキスト(「ここを押すとブロードキャストする」)が表示されます。 

f:id:vw-dsg:20180124112152j:plain

 

③ 通知を収納すると画面中央のテキストが「完了しました!」に変更されています。

f:id:vw-dsg:20180124112207j:plain 

まとめ

ネット上には、通知をタップした時に「画面(Activity)を起動して表示する」という処理をもったサンプルは数多く存在しますが、「任意の処理を実行する」といったものは意外に少ないので、もし似たような処理を実現しようといろいろ模索している場合は、ぜひ今回のサンプルを参考にしてください。

END