とあるプログラマの備忘録

都内某所に住むプログラマが自分用に備忘録を残すという趣旨のブログです。はてなダイアリーから移動しました!

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

-- 8/26追記 今北工業さんが私の記事のtypoを修正してくださりました〜! こちらも参考にしてくださいm( )m

blog.livedoor.jp

今月末に引っ越しを控え案件のタスクを残したくないraharuです
さて、前回に引き続きUnityのNative連携のAndro編です。

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

※まだAndroidPluginの作成環境が出来てない人はこちらの記事で環境を構築してください。

パッケージ名は自由ですが、
今回は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秒後にしてるけども。。)
第三引数はユニークな値を入れるとよし

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

当たり前の事かも知れないけど一本アプリ作るのに
c# java obj-c phpと4言語扱うのに
mono eclipse xcode vimを言ったり来たりして段々今何言語書いてるのか分からなくなってくる。

ネイティブ連携は面倒くさいね!

参考にさせて頂きました

【Android】指定時間に処理を実行する【AlarmManager】 - アプリ開発者のチラシの裏

Android - スリープ時にもBroadcastを処理する方法 - Qiita