LoginSignup
54
55

More than 5 years have passed since last update.

cocos2dxでローカル通知を出す(iOS/Android)

Last updated at Posted at 2014-01-12

※ (6/11) コメント頂いたgetPendingIntentを修正

cocos2d-xでローカル通知を出したい

cocos2d-xでiOS/Androidのローカル通知(LocalNotification)を出すコードです。

iOSの場合

iOSの場合は、実装ファイルの拡張子を*.mmに変えるだけでObjective-Cを呼び出せるので簡単。

LocalNotification.h
#ifndef ___LocalNotificationSample__LocalNotification__
#define ___LocalNotificationSample__LocalNotification__

#include <string>

class LocalNotification {
public:
  /**
   * Show local notification
   * @param message  Message should be shown in notificatin
   * @param interval Interval in seconds
   * @param tag      Tag to specify notification
   */
  static void show(std::string message, int interval, int tag);

  /**
   * Cancel local notification specified by ID
   * @param tag Tag of local notification
   */
  static void cancel(int tag);
};

#endif /* defined(___LocalNotificationSample__LocalNotification__) */
LocalNotification_iOS.mm
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)

#include "LocalNotification.h"

using namespace std;

void LocalNotification::show(std::string message, int interval, int tag)
{
  // 通知を作成する
  UILocalNotification *notification = [[UILocalNotification alloc] init];

  notification.fireDate = [[NSDate date] dateByAddingTimeInterval:interval];
  notification.timeZone = [NSTimeZone defaultTimeZone];
  notification.alertBody = [NSString stringWithCString:message.c_str()
                                              encoding:[NSString defaultCStringEncoding]];
  notification.alertAction = @"Open";
  notification.soundName = UILocalNotificationDefaultSoundName;

  NSNumber* tag1 = [NSNumber numberWithInteger:tag];
  NSDictionary *infoDict = [NSDictionary dictionaryWithObject:tag1 forKey:@"ID"];
  notification.userInfo = infoDict;

  // 通知を登録する
  [[UIApplication sharedApplication] scheduleLocalNotification:notification];

  [notification release];
}

void LocalNotification::cancel(int tag)
{
  for(UILocalNotification *notification in [[UIApplication sharedApplication] scheduledLocalNotifications]) {
    if([[notification.userInfo objectForKey:@"ID"] integerValue] == tag) {
      [[UIApplication sharedApplication] cancelLocalNotification:notification];
    }
  }
}

#endif // CC_TARGET_PLATFORM == CC_PLATFORM_IOS

Androidの場合

iOSとは違って、ちょっとめんどくさいです。
JavaでLocalNotificationを出すメソッドを定義して、JNI経由でC++から呼び出します。
Androidの通知UIのAPIはバージョンによって差分があるので、Support Library v4に入ってるNotificationCompatクラスを使用しましょう。

Cocos2dxActivity.java
package org.cocos2dx.cpp;

import java.util.Calendar;

import android.app.Activity;
import android.app.AlarmManager;
import android.app.NativeActivity;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;

public class Cocos2dxActivity extends NativeActivity{

    private static final String TAG = Cocos2dxActivity.class.getSimpleName();
    private static Activity sActivity;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);

        //For supports translucency

        //1.change "attribs" in cocos\2d\platform\android\nativeactivity.cpp
        /*const EGLint attribs[] = {
                EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
                EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,  
                //EGL_BLUE_SIZE, 5,   -->delete 
                //EGL_GREEN_SIZE, 6,  -->delete 
                //EGL_RED_SIZE, 5,    -->delete 
                EGL_BUFFER_SIZE, 32,  //-->new field
                EGL_DEPTH_SIZE, 16,
                EGL_STENCIL_SIZE, 8,
                EGL_NONE
        };*/

        //2.Set the format of window
        // getWindow().setFormat(PixelFormat.TRANSLUCENT);

        // LocalNotification
        sActivity = this;
    }

    public static void showLocalNotification(String message, int interval, int tag) {
        Log.v(TAG, "showLocalNotification");
        PendingIntent sender = getPendingIntent(message, tag);

        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(System.currentTimeMillis());
        calendar.add(Calendar.SECOND, interval);

        AlarmManager am = (AlarmManager)sActivity.getSystemService(ALARM_SERVICE);
        am.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), sender);
    }

    public static void cancelLocalNotification(int tag) {
        Log.v(TAG, "cancelLocalNotification");
        PendingIntent sender = getPendingIntent(null, tag);
        AlarmManager am = (AlarmManager)sActivity.getSystemService(ALARM_SERVICE);
        am.cancel(sender);
    }

    private static PendingIntent getPendingIntent(String message, int tag) {
        Intent i = new Intent(sActivity.getApplicationContext(), LocalNotificationReceiver.class);
        i.putExtra("notification_id", tag);
        i.putExtra("message", message);
        PendingIntent sender = PendingIntent.getBroadcast(sActivity,  tag, i, PendingIntent.FLAG_UPDATE_CURRENT);
        return sender;
    }
}
LocalNotificationReceiver.java
package org.cocos2dx.cpp;

import com.MyCompany.AwesomeGame.R;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.support.v4.app.NotificationCompat;

public class LocalNotificationReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        int notificationId = intent.getIntExtra("notification_id", 0);
        String message = intent.getStringExtra("message");

        Intent intent2 = new Intent(context, Cocos2dxActivity.class);
        intent2.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
        PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent2,
                PendingIntent.FLAG_UPDATE_CURRENT);

        Bitmap largeIcon = BitmapFactory.decodeResource(context.getResources(),
                R.drawable.icon);
        NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
        builder.setContentTitle(context.getString(R.string.app_name));
        builder.setContentText(message);
        builder.setSmallIcon(R.drawable.icon);
        builder.setLargeIcon(largeIcon);
        builder.setTicker(message);
        builder.setAutoCancel(true);
        builder.setDefaults(Notification.DEFAULT_ALL);
        builder.setContentIntent(pendingIntent);

        NotificationManager manager = (NotificationManager) context
                .getSystemService(Context.NOTIFICATION_SERVICE);
        manager.notify(notificationId, builder.build());
    }

}

AndroidManifest.xmlに以下の1行を追加します。

AndroidManifest.xml
<!-- ローカル通知のレシーバー -->
<receiver android:name="org.cocos2dx.cpp.LocalNotificationReceiver" android:process=":remote" />

C++側の実装は以下です。iOS版とAPIを合わせています。

LocalNotification_Android.cpp
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)

#include "LocalNotification.h"
#include "platform/android/jni/JniHelper.h"
#include <jni.h>

using namespace std;

// Java class
// NativeActivityのパッケージ名・クラス名に合わせて修正してください
#define  CLASS_NAME "org/cocos2dx/cpp/Cocos2dxActivity"

static bool getJNIStaticMethodInfo(cocos2d::JniMethodInfo &methodinfo,
                                        const char *methodName,
                                        const char *paramCode) {
  return cocos2d::JniHelper::getStaticMethodInfo(methodinfo,
                                                 CLASS_NAME,
                                                 methodName,
                                                 paramCode);
}

void LocalNotification::show(std::string message, int interval, int tag)
{
  cocos2d::JniMethodInfo methodInfo;

  if (! getJNIStaticMethodInfo(methodInfo, "showLocalNotification", "(Ljava/lang/String;II)V")) {
    return;
  }

  jstring stringArg = methodInfo.env->NewStringUTF(message.c_str());
  methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID, stringArg, interval, tag);
  methodInfo.env->DeleteLocalRef(stringArg);
  methodInfo.env->DeleteLocalRef(methodInfo.classID);
}

void LocalNotification::cancel(int tag)
{
  cocos2d::JniMethodInfo methodInfo;

  if (! getJNIStaticMethodInfo(methodInfo, "cancelLocalNotification", "(I)V")) {
    return;
  }

  methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID, tag);
  methodInfo.env->DeleteLocalRef(methodInfo.classID);
}

#endif // CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID

使い方

こんな感じで呼び出します。

// 10sec後に表示
LocalNotification::show("Hello Notification!", 10, 1);

// タグ1の通知をキャンセル
LocalNotification::cancel(1);
54
55
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
54
55