Unity 時間指定ローカルプッシュ通知処理を書いてみた Android編

raharu(仮名)(プログラマー)
これがダイバージェンス1%の先の世界か。。。

前回に引き続きUnityのNative連携のAndro編です。

流れとしてはAlarmManagerで登録
レシーバーで受信したらローカル通知を投げるという事をしたいだけなのにクソはまった。。

※まだAndroidPluginの作成環境が出来てない人はこちらの記事で環境を構築してください。 http://nirasan.hatenablog.com/entry/2014/06/23/090440

パッケージ名は自由ですが、
今回はnet.raharu.localnotifypluginです
これあとでAndroidManifestに使うので重要

java側

localNotification.java

package net.raharu.localnotifyplugin;
import java.util.Calendar;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import com.unity3d.player.UnityPlayer;
public class localNotification {
/**
* 時間指定でローカル通知を投げる
* @param message
* @param unixtime
* @param primary_key
*/
public void sendNotification(String message, long unixtime, int primary_key)
{
Log.i("Unity", "SendNotificationStart");
// インテント作成
Activity activity = UnityPlayer.currentActivity;
Context context = activity.getApplicationContext();
Intent intent = new Intent(context, NotificationReceiver.class);
//渡す値
intent.putExtra("MESSAGE", message);
intent.putExtra("PRIMARY_KEY", primary_key);
//10秒後にアラーム(デバック用)
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND, 10);
PendingIntent sender = PendingIntent.getBroadcast(context, primary_key, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarm = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
alarm.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis() , sender);
}
}

NotificationReceiver.java

package net.raharu.localnotifyplugin;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.support.v4.app.NotificationCompat;
/**
* レシーバー
*
* @author raharu
*/
public class NotificationReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
//値の取得
String message = intent.getStringExtra("MESSAGE");
Integer primary_key = intent.getIntExtra("PRIMARY_KEY", 0);
// intentからPendingIntentを作成
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
// LargeIcon の Bitmap を生成
final PackageManager pm = context.getPackageManager();
ApplicationInfo applicationInfo = null;
try {
applicationInfo = pm.getApplicationInfo(context.getPackageName(),PackageManager.GET_META_DATA);
} catch (NameNotFoundException e) {
e.printStackTrace();
return;
}
final int appIconResId = applicationInfo.icon;
Bitmap largeIcon = BitmapFactory.decodeResource(context.getResources(), appIconResId);
// NotificationBuilderを作成
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
builder.setContentIntent(pendingIntent);
builder.setTicker("通知がとどきました"); //ステータスバーに届くテキスト
builder.setSmallIcon(appIconResId); //アイコン
builder.setContentTitle("タイトルだよ!!"); // タイトル
builder.setContentText(message); // 本文(サブタイトル)
builder.setLargeIcon(largeIcon); //開いた時のアイコン
builder.setWhen(System.currentTimeMillis()); //通知に表示される時間(※通知時間ではない!)
// 通知時の音・バイブ・ライト
builder.setDefaults(Notification.DEFAULT_ALL);
builder.setAutoCancel(true);
// NotificationManagerを取得
NotificationManager manager = (NotificationManager) context.getSystemService(Service.NOTIFICATION_SERVICE);
// Notificationを作成して通知
manager.notify(primary_key, builder.build());
}
}

このパッケージをjarとしてエクスポートしてAssets/Plugin/Androidの直下に起きます。

Unity側

AndroidMnifest.xmlにレシーバーと権限を追加

<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="XXXXXXXXXXXX"
android:installLocation="preferExternal"
android:theme="@android:style/Theme.NoTitleBar"
android:versionCode="1"
android:versionName="1.0">
<supports-screens
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:xlargeScreens="true"
android:anyDensity="true"/>
<application
android:icon="@drawable/app_icon"
android:label="@string/app_name"
android:debuggable="true">
<activity android:name="com.unity3d.player.UnityPlayerNativeActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
<meta-data android:name="unityplayer.ForwardNativeEventsToDalvik" android:value="true" />
</activity>
<meta-data
android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />
#ここに通知されるレシーバーを登録する(パッケージ名+クラス名)
<receiver android:name="net.raharu.localnotifyplugin.NotificationReceiver" android:process=":remote" />
</application>
<uses-sdk android:minSdkVersion="9" android:targetSdkVersion="20" />
<uses-feature android:glEsVersion="0x00020000" />
<uses-permission android:name="android.permission.INTERNET" />
#バイブレートの権限追加
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
</manifest>

こんな感じで呼び出せる

#if UNITY_ANDROID
AndroidJavaObject m_plugin = new AndroidJavaObject( "net.raharu.localnotifyplugin.localNotification");
if (m_plugin != null){
m_plugin.Call("sendNotification", "本文だよ!!!!", [unixtime], [unique_id]);
}
#endif

unixtimeは通知したい時間(今回は強制で10秒後にしてるけども。。)
第三引数はユニークな値を入れるとよし

これで時間指定したローカル通知が届くようになりました。

参考にさせて頂きました

http://yusuke-hata.hatenablog.com/entry/2014/11/15/202403 http://qiita.com/nein37/items/52523e39932323ebc654

– 8/26追記 今北工業さんが私のtypoを指摘してくださいました!!ありがとうございます! こちらの記事も参考にしてください

http://blog.livedoor.jp/nyangostar/archives/41149800.html