Cocos2d-x 3.2でスクリーンショットを撮ってツイート
Cocos2d-x3.2で、スクリーンショットを撮るためのメソッドが実装されたので、
これを使ってスクリーンショットをツイートする機能を作ってみたのでメモ。
基本はこの記事と同じです。
Cocos2d-xで撮ったスクリーンショットをTwitterに添付してツイートできないか試してみた - おかひろの雑記
※2014/8/8 iOS6でツイート後に画面操作ができなくなる問題があったため、NativeCodeLauncher_objc.mmを修正しました。
今回使用したバージョン
- Cocos2d-x 3.2
Cocos2d-xでスクリーンショットを撮る方法はこちらhttp://www.cocos2d-x.org/projects/cocos2d-x/wiki/How_to_save_a_screenshotを参考にしました。
ネイティブ連携
ツイートする内容に加え、画像ファイルのフルパスを一緒に渡すようにしています。
共通
NativeCodeLauncher.h
namespace Cocos2dExt { class NativeCodeLauncher { public: static void openTweetDialog(char const *tweet,char const *filePath); }; }
iOS
NativeCodeLauncher.mm
static void static_openTweetDialog(const char* tweet,const char* filePath) { [NativeCodeLauncher openTweetDialog:[NSString stringWithUTF8String:tweet] filePath:[NSString stringWithUTF8String:filePath]]; } namespace Cocos2dExt { void NativeCodeLauncher::openTweetDialog(const char *tweet,const char *filePath) { static_openTweetDialog(tweet,filePath); } }
NativeCodeLauncher_objc.h
@interface NativeCodeLauncher : NSObject
+(void)openTweetDialog:(NSString *)tweet filePath : (NSString *)filePath;
@end
NativeCodeLauncher_objc.mm
※2014/8/8 CompletionHandler内にdismissViewControllerAnimatedメソッドを追加。それに伴う修正。
@implementation NativeCodeLauncher +(void)openTweetDialog:(NSString *)tweet filePath:(NSString *)filePath { if([SLComposeViewController isAvailableForServiceType:SLServiceTypeTwitter]) { AppController *appController = (AppController *)[UIApplication sharedApplication].delegate; NSString *serviceType = SLServiceTypeTwitter; SLComposeViewController *composeCtl = [SLComposeViewController composeViewControllerForServiceType:serviceType]; [composeCtl setInitialText:tweet]; UIImage *image = [UIImage imageWithContentsOfFile:filePath]; [composeCtl addImage:image]; [composeCtl setCompletionHandler:^(SLComposeViewControllerResult result) { [appController.viewController dismissViewControllerAnimated:YES completion:nil]; if (result == SLComposeViewControllerResultDone) { //投稿成功時の処理 NSLog(@"ツイートしました"); } }]; [appController.viewController presentViewController:composeCtl animated:YES completion:nil]; } else { tweet = [NSString stringWithFormat:@"http://twitter.com/home?status=%@",tweet]; tweet = [tweet stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; NSURL *url = [NSURL URLWithString:tweet]; [[UIApplication sharedApplication] openURL:url]; } } @end
iOSの場合は画像ファイルをUIImageに読み込むだけなので簡単です。
Social.frameworkを使う形に変更しました。
Android
NativeCodeLauncher.cpp
namespace Cocos2dExt { void NativeCodeLauncher::openTweetDialog(char const* tweet,char const *filePath) { openTweetDialogJNI(tweet,filePath); } }
NativeCodeLauncherJni.h
extern "C" { extern void openTweetDialogJNI(char const* tweet,char const *filePath); }
NativeCodeLauncherJni.cpp
... #define CLASS_NAME "org/cocos2dx/cpp/AppActivity" ... extern "C" { ... void openTweetDialogJNI(char const* tweet,char const *filePath) { JniMethodInfo methodInfo; if (!getStaticMethodInfo(methodInfo, "openTweetDialog", "(Ljava/lang/String;Ljava/lang/String;)V")) { return; } jstring tweetArg = methodInfo.env->NewStringUTF(tweet); jstring filePathArg = methodInfo.env->NewStringUTF(filePath); methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID, tweetArg,filePathArg); methodInfo.env->DeleteLocalRef(tweetArg); methodInfo.env->DeleteLocalRef(filePathArg); methodInfo.env->DeleteLocalRef(methodInfo.classID); } }
AppActivity.java
public class AppActivity extends Cocos2dxActivity{ private static Activity me = null; protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); me = this; } static { System.loadLibrary("game"); } // JNIから呼び出すメソッド public static void openTweetDialog(String tweet,String filePath) { final String path = filePath; final String tweetMessage = tweet; me.runOnUiThread(new Runnable(){ @Override public void run() { File f = new File(path); byte[] data; try { data = readFileToByte(path); } catch(Exception e) { Log.e("Debug", e.getMessage()); return; } File savePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES); File saveFile = new File(savePath,"screenshot.jpeg"); if(!savePath.exists()) { savePath.mkdir(); } FileOutputStream fos = null; try { fos = new FileOutputStream(saveFile); fos.write(data); fos.close(); } catch(Exception e) { Log.e("Debug", e.getMessage()); return ; } Uri uri = Uri.fromFile(saveFile); Intent it = new Intent(Intent.ACTION_SEND); it.putExtra(Intent.EXTRA_SUBJECT, ""); it.putExtra(Intent.EXTRA_TEXT, tweetMessage); it.putExtra(Intent.EXTRA_STREAM,uri); it.setType("image/jpeg"); me.startActivity(Intent.createChooser(it,"共有")); } }); } private static byte[] readFileToByte(String filePath) throws Exception { byte[] b = new byte[1]; FileInputStream fis = new FileInputStream(filePath); ByteArrayOutputStream baos = new ByteArrayOutputStream(); while (fis.read(b) > 0) { baos.write(b); } baos.close(); fis.close(); b = baos.toByteArray(); return b; } }
画像ファイルを外部ストレージに一旦コピーしています。
そのため、AndroidManifest.xmlにパーミッションが必要になります。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
呼び出し
utils::captureScreen([&](bool succeed,const std::string &fileName){ // ツイート if(succeed) { // スクリーンショット保存成功 Cocos2dExt::NativeCodeLauncher::openTweetDialog(”ツイートメッセージ”,fileName.c_str()); } else { // スクリーンショット保存失敗 } }, "screenshot.jpg");
スクリーンショットを撮った後にコールバックされるようなので、その中でツイートの準備を行います。