gracetory’s blog

東池袋にある合同会社グレストリのエンジニアブログです

UnityでAndroidの通知からアプリの起動

f:id:gracetory_yama:20170727102755j:plain

紹介

皆さま初めまして。

グレストリでエンジニアをしております、山口という者です。

果たして会社に見合うだけの技術力を身に付けることができるのか、

筆者の次回作にご期待ください(完)

冗談さておき、先日弊社から「魔王さまの誤算」というタイトルをリリースさせていただきました。

魔王さまの誤算:超爽快ラインディフェンスゲームを App Store で

魔王さまの誤算:無料爽快ディフェンスゲーム - Google Play の Android アプリ

ぜひDLをお願いします。

注意など

筆者はこのプロジェクト以前には、ほぼPHPしか触れたことがない人間でした。

またこの実装をしたのは結構前で、曖昧なところもあります。

同じ悩みを持つ方が、どうしてもというときに一次療法としてお使いください。

本題

本ゲームにはUnity(5.5.4)を使用しました。

Androidのプラグインでローカル通知を実装したところ、

通知が来ても、その通知からアプリの起動ができない状態でどハマり。

簡単に解決方法をここに備忘録として残しておきます。

問題

まず、これらの記事を参考にさせていただき、ローカル通知を実装しました。

klabgames.tech.blog.jp.klab.com

raharu0425.hatenablog.com

マニフェストの書き方とかはご自身で探してください(丸投げ)。

さすが先人の方達の知恵、見事に通知が届きました。

が、ここで問題が発生。

通知をタップしてもアプリが起動しない…?

応急処置

結論から言うと、こちらの記事でやり方が。

qiita.com

あなたが神か。

が、setClassNameの第二引数に渡すクラスがよくわからない…

自分のアプリのクラス名を渡せばいいとのこと。それを知る方法がわからん。

というわけで、自分のクラス名を取得するだけのクラスを作成。

こちらのサイト様を参考にさせていただきました。

指定したアプリを起動 – Android | ごろつきめも

// OpenGame.java

package {パッケージ名};

import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.widget.Toast;

public class OpenGame extends Activity {
    @Override
    public void onCreate(Bundle bundle) {
        super.onCreate(bundle);

        PackageManager pm = getPackageManager();
        Intent intent = null;
        try {
            intent = pm.getLaunchIntentForPackage("{パッケージ名}");
        } catch (Exception e) {
            Toast.makeText(this, "対象のアプリがありません", Toast.LENGTH_SHORT).show();
        }
        startActivity(intent);
    }
}

あとはこのクラスをレシーバーで指定するだけ。

わーい たーのしー

実装

// NotificationReceiver.java

package {パッケージ名};

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
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;

/**
 * レシーバー
 *
 */
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);


        // NotificationBuilderを作成
        NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
        builder.setTicker("通知が届きました");             // 通知到着時に通知バーに表示
        builder.setContentTitle("表示したいゲームタイトル");       // タイトル
        builder.setContentText(message);                 // 本文(サブタイトル)
        builder.setWhen(System.currentTimeMillis());     // 通知に表示される時間


        // intentからPendingIntentを作成
        // プロセスがあればそのまま復帰、なければ起動画面から開始する
        Intent new_intent = new Intent(Intent.ACTION_MAIN);
        new_intent.addCategory(Intent.CATEGORY_LAUNCHER);
        new_intent.setClassName("{パッケージ名}", "{パッケージ名}.OpenGame"); // 今回作ったクラス
        new_intent.setFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED | Intent.FLAG_ACTIVITY_NEW_TASK);
        PendingIntent pendingIntent = PendingIntent.getActivity(context, primary_key, new_intent, PendingIntent.FLAG_CANCEL_CURRENT);
        //Builderに追加
        builder.setContentIntent(pendingIntent);


        // LargeIcon の Bitmap を生成してBuilderに追加
        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);

        int imageResourceId = context.getResources().getIdentifier("notify", "drawable", "{パッケージ名}");


        // builder.setSmallIcon(appIconResId); // アイコン
        builder.setSmallIcon(imageResourceId); // アイコン
        builder.setLargeIcon(largeIcon);    // 開いた時のアイコン


        // 通知の音・バイブ・ライトのデフォルト設定、タップで消えるように
        builder.setDefaults(Notification.DEFAULT_ALL);
        builder.setAutoCancel(true);


        // NotificationManagerを取得
        NotificationManager manager = (NotificationManager) context.getSystemService(Service.NOTIFICATION_SERVICE);
        // Notificationを作成して通知
        manager.notify(primary_key, builder.build());
    }

}

感想

これにて無事に通知からアプリを起動できました!

「とりあえずUnityでゲーム作りたい!」

「Androidの通知からアプリ起動させたい!けどやり方わからない!!」

みたいな人がいたら、この記事が一助になれば幸いです。

が、あとでちゃんとしたやり方を模索しましょうね。

私も見つけたらまた記事にします。

あとはあれです。

Unityの有料アセット買えば、通知周りも簡単らしいです(おい)。