Cocos2d-xで撮ったスクリーンショットをTwitterに添付してツイートできないか試してみた
Cocos2d-x上からTwitterにツイートする - おかひろの雑記ではテキストデータのみのツイートをやってみましたが、
Cocos2d-xの画面のスクリーンショットを添付してツイートできないか試してみました。
ちなみにCocos2d-xでスクリーンショットを撮る方法はこちらhttp://www.cocos2d-x.org/projects/cocos2d-x/wiki/How_to_save_a_screenshotを参考にしました。
処理の流れ
1.Cocos2d-X上でスクリーンショットを撮って、ファイルに保存
↓
2.保存したファイルのパスを取得して、ネイティブに渡す
↓
3.ネイティブはパスから画像を取得し、ツイートする
とりあえずこういう流れでやってみました。
今回使用したバージョン
- Cocos2d-X 2.1.4
スクリーンショット保存
AppDelegateにstaticメソッドとして実装しました。
AppDelegate.h
static void saveScreenShot();
AppDelegate.cpp
void AppDelegate::saveScreenShot() { CCSize size = CCDirector::sharedDirector()->getWinSize(); CCRenderTexture* texture = CCRenderTexture::create((int)size.width, (int)size.height); texture->setPosition(ccp(size.width * 0.5f, size.height * 0.5f)); texture->begin(); CCDirector::sharedDirector()->getRunningScene()->visit(); texture->end(); texture->saveToFile("screenshot.jpg", kCCImageFormatJPEG); }
ネイティブ連携
ツイートする内容に加え、画像ファイルのフルパスを一緒に渡すようにしています。
共通
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.m
@implementation NativeCodeLauncher +(void)openTweetDialog:(NSString *)tweet filePath:(NSString *)filePath { if([TWTweetComposeViewController canSendTweet]) { AppController *appController = (AppController *)[UIApplication sharedApplication].delegate; TWTweetComposeViewController *tweetController = [[TWTweetComposeViewController alloc]init]; [tweetController setInitialText:tweet]; UIImage *image = [UIImage imageWithContentsOfFile:filePath]; [tweetController addImage:image]; [appController.viewController presentModalViewController:tweetController animated:YES]; } 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に読み込むだけなので簡単です。
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/lib/Cocos2dxActivity" #define CLASS_NAME "jp/milt/okahiro/OkahiroCocos2dX" ... 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); } }
OkahiroCocos2dX.java
public class OkahiroCocos2dX 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; } }
Androidの場合は自分の知識不足もあり、いろいろと苦労しました。
画像ファイルをUri化してIntentで渡すだけだとAndroid4.2でうまくいかなかったので、画像ファイルを外部ストレージに一旦コピーしています。
そのため、AndroidManifest.xmlにパーミッションが必要になります。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
呼び出し
// スクリーンショット保存 AppDelegate::saveScreenShot(); // パスを取得 std::string filePathName = CCFileUtils::sharedFileUtils()->getWritablePath().append("screenshot.jpg"); // ネイティブに渡す Cocos2dExt::NativeCodeLauncher::openTweetDialog("テストツイート http://example.com/ #テスト",filePathName.c_str());
スクリーンショット画像ファイルの保存先はCCFileUtilsクラスのgetWritablePathメソッドで取得しますが、
このパスがCocos2d-Xのバージョンによって変わっていることもあるようなので、少なくともiOSとAndroidで
どういうパスが指定されているのか、ログなどで確認をしておいたほうがいいと思います。
結果
スクリーンショット画像はCocos2d-X上で作成しているので、広告などは映りません。
Android twicca
Android tweecha
とりあえず作って動かしてみたレベルのものなので、ネイティブの特にAndroidのソースに関しては、
課題が残っている感じもします。