忍者ブログ
  • 2024.10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 2024.12
[PR]
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

【2024/11/24 05:52 】 |
appCCloudでPUSH通知
そろそろちゃんとまとめよう。
appCCloudを使ってPUSH通知を実装する方法。

appCCloudじゃなくても共通で必要な手順もある。


◯証明書を揃える
PUSH通知用の証明書を作る(開発用、本番用両方)

1. Apple Developerに行き、Certificatesを新規作成


2. 証明書の種類を「Apple Push Notification service SSL」を選択。
開発用の場合は Sandbox , 本番用の場合は Productionにする


3. そのままContinueを押す
この画面には、証明書要求(Certificate Signing Request)の作り方が書いてある。それを作るのは次の手順で。


4. 証明書要求を作る。
Macの「キーチェーン」アプリを起動する。
上部メニューから、キーチェーンアクセス→証明書アシスタント→認証局に証明書を要求 を選択


次の画面で「ディスクに保存」を選択し、「続ける」を押す。(メールアドレスや通称は何でも良い)


すると、
CertificateSigningRequest.certSigningRequest
という名前のファイルが生成される。(次の手順で使ったらもう必要ないので、適当なところに置いておけばよい)

5. 証明書要求を送信する
Apple Developerに戻る。
この画面で、 Choose File から先ほど作ったばかりの CertificateSigningRequest を選択する。
選択したらGenerateをクリック。


6. すると、すぐに証明書が作成されるので、ダウンロードしてどこか分かりやすいところに保存しておく。
開発用なら aps_development.cer, 本番用なら aps_production.cer という名前になっている。

7. キーチェーンに登録
今ダウンロードした aps_development, aps_production.cer をダブルクリックする。
すると自動的にキーチェーンに登録される。
開発用なら「Apple Development IOS Push Service: (バンドル名)」
本番用なら「Apple Production IOS Push Service: (バンドル名)」
という名前で登録されているはず。

8. 秘密鍵を書き出す
この証明書から、秘密鍵情報を書き出す。
キーチェーンの証明書の三角をクリックすると、下に秘密鍵情報の行が表示される。
ここを右クリックして、「◯◯◯を書き出す」を選択。
分かりやすいファイル名をつけ、ファイル形式を「p12」にして書き出す。
これがPUSH通知用の秘密鍵になる。
PUSH通知サービスを使う場合、この秘密鍵の登録が必ず必要になる。


9. pemファイルに変換する
秘密鍵は作れたのでいいのだが、appCCloudを使う場合、ファイル形式をpemにする必要があるので変換する。
ターミナルを開き、以下のコマンドを実行する。
$ openssl pkcs12 -in XXX.p12 -out XXX.pem -nodes -clcerts
これで出力されたXXX.pemを使用することになる。


◯appCCloud管理画面

1.アプリ情報の登録
アプリの登録を行う。
画面はしょっちゅう変わるので、スクリーンショットは割愛。見れば分かる。
バンドルIDその他を登録。正確に。当たり前だがバンドルIDが合っていないとPUSH通知は届かない。
最下部にPUSH通知用の設定箇所がある。ここに先ほど作ったpemファイルを登録する。

また、アプリ情報を登録すると、メディアキーが作成される。これが必要になるのでコピーしておく。

2. 最新SDKダウンロード
当然のことだが、SDKを最新にしておくことは重要。
ダウンロードしておく。
ちなみにcocos2d-x用や、Unity用のSDKもあるので、そちらを使うこと。

3. PUSH通知情報登録
PUSH通知設定画面から、PUSH通知の文面、配信日時、開発用か本番用かなどを登録する。
配信は5分間隔で行われる。(即時でないのが惜しい)
ただしまだ実装の方が済んでないので、そちらが終わってからにしよう。


◯実装
1. 先ほどダウンロードしたSDKを解凍

2.プロジェクトに追加
中に入っているREADME.mdファイルを読めば書いてあるのだが、
AppCCloudPlugin.h
AppCCloudPlugin.cpp
AppCCloudPlugin.mm
libappCCloud.a
includeディレクトリ
をプロジェクトに追加する。

3. ライブラリ追加
CoreTelephony.framework
StoreKit.framework
確かこれらが必要だった気がする

4. ARC対応
前の手順で追加した AppCCloudPlugin.mm が
実はARC非対応で書かれているので、もしプロジェクト全体をARCで作っている場合は対応が必要。そうでないなら(コンパイルが通っていれば)この手順は飛ばしてよい。
プロジェクトビューからプロジェクトを選択→TARGETSからiOSのものを選択→ Build Phases を選択→AppCCloudPlugin.mmをダブルクリック→ -fno-objc-arc を追加
これで、AppCCloudPlugin.mmは非ARCとしてコンパイルされるようになる。


5. コーディング
AppController.mに必要なコードを追記する。
以下はサンプルから抜粋したもの。
APPCCLOUD_MEDIA_KEYには、appCCloudの管理画面で手に入れたメディアキーを入れておくこと。


#define APPCCLOUD_MEDIA_KEY @""

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// プッシュ通知経由の起動数を取得する場合は、引数にlaunchOptionsをセットしてください
[appCCloud setupAppCWithMediaKey:APPCCLOUD_MEDIA_KEY
option:APPC_CLOUD_AD | APPC_CLOUD_PUSH
launchOptions:launchOptions];

return YES;
}

- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *) devToken
{
NSLog(@"success token:%@", devToken);
[appCCloud pushNotificationDidRegisterWithDeviceToken:devToken];
}

- (void)application:(UIApplication *)app didFailToRegisterForRemoteNotificationsWithError:(NSError *) err
{
NSLog(@"failure %@", err);
[appCCloud pushNotificationDidFailWithError:err];
}

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
[appCCloud pushNotificationDidReceive:userInfo appStat:application.applicationState];
}




6. 実機で起動する
実機で起動する。シミュレータではできない。
うまく行けば、「(アプリ名)はPUSH通知を使用します。よろしいですか?」というアラートビューが出る。


ここまでできれば、再度appCCloud管理画面に戻り、PUSH通知設定を行う。
5分待って通知がくれば成功!


◯本番については
本番用については、本番用のアプリを起動した端末があればいい。
PUSH通知設定で本番向けに設定すれば、PUSH通知は飛んでくる。AppStoreに置かれるのを待つことは無い。
appCCloudに登録した証明書の間違いが無いかの確認のため、AppStoreに置かれる前に一度確認しておこう。(もし間違っていても、別にappleへ再サブミットするとかではないので、慌てることは無い。「◯証明書を揃える」の手順を見直せばいいだけだ)

PR
【2015/04/15 23:31 】 | iPhone | 有り難いご意見(0)
SNS周りの実装で注意する点
SNS周りの注意点

[twitter]
iOSはSocialFrameworkですぐできる

Androidは、Intentを使えば早いが、それだと投稿の成功・失敗が取れない。
インセンティブを付与したいときには、Twitterにアプリ登録をして、IDその他を取得。twitter4jを使ってOAuth方式で呼び出す
初回は認証を受ける処理に入るので、フローが変わることに注意。
認証用のIntentに飛ばすためだけのActivityを作ったりもする。
認証をキャンセルしたときに落ちたりもするので注意。(intent.getData().getQueryParameter("oauth_verifier”); が null になった場合、処理を続行させると落ちる)


[facebook]
iOSはSocialFrameworkですぐできる

Androidはかなり面倒。Intentで飛ばすだけならいいが、やらないことも多い


[LINE]
LINEは画像と文字列を同時に投稿できない。スクショなど画像投稿系はLINEを外すことも多い
成功・失敗の判断ができない。ボタンを押した時点でインセンティブを付与してもいいが、そもそもアプリが入ってないときとかはさすがに付与しないよう注意



[iOS]
該当のアプリがインストールされていない場合、どうする?

投稿完了時にアラート表示する?

スクショを撮るなどするとき遅いかもしれないので、インジケータを出す


[Android]
該当のアプリがインストールされていない場合、PlayStoreのページに飛ばす。PlayStoreもインストールされてないときは、ブラウザで該当のページに飛ばす

投稿完了時にtoast表示

スクショを撮るなどするとき遅いので、ProgressDialogなど出す


cocos2d-xの場合、シェアコールバックでそのままゲーム側の処理を行うべきでない。リソース周りへのアクセス等すると落ちる
→フラグを立てるだけなどにしておいて、処理はメインループで行うのがよい。




【2015/04/10 17:43 】 | cocos2d-x | 有り難いご意見(0)
[Android]バイブレーション

参考


【2015/04/10 15:35 】 | Android | 有り難いご意見(0)
[Android]システム音を鳴らす
iOSと比べると、あまりシステム音というのはない。

参考

使える音は以下
DEFAULT_ALARM_ALERT_URI
DEFAULT_NOTIFICATION_URI
DEFAULT_RINGTONE_URI



【2015/04/10 15:34 】 | Android | 有り難いご意見(0)
[iOS]システム音を鳴らす
シャッター音とか、着信音とかを鳴らす方法。

AudioToolBoxライブラリを追加。


#import <AudioToolbox/AudioServices.h>

AudioServicesPlaySystemSound(1108); //シャッター音





プログラムの参考
鳴らせる音の一覧

ちなみにバイブも鳴らせる

AudioServicesPlayAlertSound(kSystemSoundID_Vibrate);



【2015/04/10 15:05 】 | iPhone | 有り難いご意見(0)
addActionでエラー
cocos2d-x。

ActionManager::addAction()でEXC_BAD_ACCESS例外で落ちた。



void ActionManager::addAction(Action *action, Node *target, bool paused)
{
CCASSERT(action != nullptr, "");
CCASSERT(target != nullptr, "");

tHashElement *element = nullptr;
// we should convert it to Ref*, because we save it as Ref*
Ref *tmp = target;
HASH_FIND_PTR(_targets, &tmp, element); // <= ココ!!!!!!!!





こんな感じ。

(このスクショは別の件で起きたものだが、原因は同じ。いつもだいたいこういうコールスタックで落ちる)


thisがnullptrになっているとかではない。
なんだろう?と思ったら、呼び出し元の


node->runAction(action);




のnodeをaddChildしていなかった。
ので、メインループが1週したときにメモリが破棄された。
破棄されたがnodeポインタは破棄されたところをさし続けていて…というパターン。

簡単な話だが、nullptrになるわけではないので気付きにくいのはなんとかしたい。
【2015/04/05 22:51 】 | cocos2d-x | 有り難いご意見(0)
画像の切り取り(Android)
Androidで画像を切り取る方法。

参考

iOSと比べて面倒。
BitmapRegionDecoderというクラスを使う。
このクラスは、コンストラクタにFileインスタンスを渡して作成する。
decodeRegion()というメソッドにRectを渡すと、その範囲を切り取ったBitmapインスタンスを返す。


import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.BitmapRegionDecoder;
import android.graphics.Rect;

public Bitmap clip(String originFilePath, Rect rect)
{
FileInputStream inputStream = new FileInputStream(new File(originFilePath));

BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(inputStream, true);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = false;

return decoder.decodeRegion(rect, options);
}





単にファイルからビットマップを作りたいときは

// filePath ... ファイルパス
File file = new File(filePath);
FileInputStream inputStream = new FileInputStream(file);
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);


となる。
デコードに失敗するとnullが返ることになる。


ちなみに、アセット内の画像ファイルからビットマップを読み込む方法は

// fileName ... アセット内のファイル名
AssetManager assetManager = getResources().getAssets(); //getResources()はContextのメンバ関数。ActivityはContextなので、Activity内ならそのまま使える
InputStream inputStream = assetManager.open(fileName);
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);


となる。


逆に、ビットマップをファイルに書き出すときは

// filePath ... 書き出すファイル名
// bitmap ... 書き出したい画像データ
FileOutputStream fileOutputStream = new FileOutputStream(filePath);
bitmap.compress(CompressFormat.PNG, 80, fileOutputStream);


とする。bitmapの中身がfileに書き出される。

【2015/04/05 11:28 】 | Android | 有り難いご意見(0)
画像の切り取り(iOS)
iOSで、画像(UIImage)を切り取る方法。


参考

そのまま持ってきたもの

UIImage* clipImage(UIImage* image, CGRect rect) {

// イメージの解像度に従いrectも換算
float scale = image.scale;
CGRect cliprect = CGRectMake(rect.origin.x * scale, rect.origin.y * scale,
rect.size.width * scale, rect.size.height * scale);

// ソース画像からCGImageRefを取り出す
CGImageRef srcImgRef = [image CGImage];

// 指定された範囲を切り抜いたCGImageRefを生成しUIImageとする
CGImageRef imgRef = CGImageCreateWithImageInRect(srcImgRef, cliprect);
UIImage* resultImage = [UIImage imageWithCGImage:imgRef scale:scale orientation:image.imageOrientation];

// 後片付け
CGImageRelease(imgRef);

return resultImage;
}




実に簡単。
画像の解像度も考慮してくれているので、
元の(scaleしない)イメージサイズを基準にして、切り取りたい範囲のRectを第2引数に渡せば良い。
Rectは左上が原点。

【2015/04/05 10:56 】 | iPhone | 有り難いご意見(0)
ThreadPoolExecutorで落ちたとき
ThreadPoolExecutorで実行時にハングアップしたとき

AsynkTask クラスのインスタンスのexecute()のところに不具合があった。


AsyncTask<String, Void, AccessToken> task = new AsyncTask<String, Void, AccessToken>() {
@Override
protected AccessToken doInBackground(String... params) {
........
}

@Override
protected void onPostExecute(AccessToken accessToken) {
..........
}
};
task.execute(verifier);



このverifierがnullだったのでエラーになった。
【2015/04/03 13:37 】 | Android | 有り難いご意見(0)
ProgressDialog
何かの処理中に出すようなUI。
iOSでいうとインジケータ。Windowsでいうと砂時計。


ProgressDialog
を使う。簡単

表示するとき

pd = new ProgressDialog(instance);
pd.setMessage("処理中...");
pd.setProgressStyle(ProgressDialog.STYLE_SPINNER);
pd.show();



消すとき

pd.dismiss();



これだけ。
【2015/03/31 17:22 】 | Android | 有り難いご意見(0)
<<前ページ | ホーム | 次ページ>>