Merge pull request #1 from lihex/master

Add twitter social share plugin
This commit is contained in:
Bin Zhang 2013-04-24 01:03:23 -07:00
commit d657524859
47 changed files with 2107 additions and 1 deletions

View File

@ -0,0 +1,58 @@
#ifndef __CCX_SOCIAL_TWITTER_H__
#define __CCX_SOCIAL_TWITTER_H__
#include "ProtocolSocial.h"
#include <map>
#include <string>
namespace cocos2d { namespace plugin {
class SocialTwitter : public ProtocolSocial
{
PLUGIN_REGISTER_DECL(SocialTwitter)
public:
/**
@brief plugin initialization
*/
virtual bool init();
/**
@brief initialize the developer info
@param devInfo This parameter is the info of developer, must contains key:
AlipayPartner The partner id of alipay account
AlipaySeller The seller id of alipay account
AlipayRsaPrivate The RSA private key of alipay account
AlipayPublic The public key of alipay account
AlipayNotifyUrl The notify url of developer (must not be empty)
AlipayPluginName The apk file name of Alipay (must not be empty)
@warning Must invoke this interface before other interfaces.
And invoked only once.
*/
virtual void initDeveloperInfo(TDeveloperInfo devInfo);
/**
@brief pay for product
@param info The info of product, must contains key:
productName The name of product
productPrice The price of product(must can be parse to float)
productDesc The description of product
@warning For different plugin, the parameter should have other keys to pay.
Look at the manual of plugins.
*/
virtual void share(TShareInfo info);
/**
@brief Set whether needs to output logs to console.
@param debug if true debug mode enabled, or debug mode disabled.
*/
virtual void setDebugMode(bool debug);
virtual const char* getPluginVersion() { return "v0.1.01"; };
virtual const char* getSDKVersion();
virtual ~SocialTwitter();
};
}} // namespace cocos2d { namespace plugin {
#endif /* __CCX_SOCIAL_TWITTER_H__ */

View File

@ -0,0 +1,55 @@
#include "SocialTwitter.h"
#include "PluginUtils.h"
namespace cocos2d { namespace plugin {
PLUGIN_REGISTER_IMPL(SocialTwitter)
SocialTwitter::~SocialTwitter()
{
}
/**
@brief plugin initialization
*/
bool SocialTwitter::init()
{
return PluginUtils::initJavaPlugin(this, "org.cocos2dx.plugin.SocialTwitter");
}
/**
@brief initialize the developer info
@param devInfo This parameter is the info of developer, must contains key:
consumerkey The consumerkey of twitter account
consumersecret The consumersecret of twitter account
More: https://dev.twitter.com
@warning Must invoke this interface before other interfaces.
And invoked only once.
*/
void SocialTwitter::initDeveloperInfo(TDeveloperInfo devInfo)
{
ProtocolSocial::initDeveloperInfo(devInfo);
}
/**
@brief pay for product
@param info The info of product, must contains key:
text The text to share
imagePath The full path of image to share
*/
void SocialTwitter::share(TShareInfo info)
{
ProtocolSocial::share(info);
}
const char* SocialTwitter::getSDKVersion()
{
return ProtocolSocial::getSDKVersion();
}
void SocialTwitter::setDebugMode(bool debug)
{
ProtocolSocial::setDebugMode(debug);
}
}} // namespace cocos2d { namespace plugin {

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
<classpathentry exported="true" kind="lib" path="/Users/lihex/cocos2d-x/plugin/plugins/twitter/proj.android/sdk/signpost-commonshttp4-1.2.1.1.jar"/>
<classpathentry exported="true" kind="lib" path="/Users/lihex/cocos2d-x/plugin/plugins/twitter/proj.android/sdk/signpost-core-1.2.1.1.jar"/>
<classpathentry exported="true" kind="lib" path="/Users/lihex/cocos2d-x/plugin/plugins/twitter/proj.android/sdk/signpost-jetty6-1.2.1.1.jar"/>
<classpathentry exported="true" kind="lib" path="/Users/lihex/cocos2d-x/plugin/plugins/twitter/proj.android/sdk/twitter4j-core-android-3.0.1.jar"/>
<classpathentry kind="output" path="bin/classes"/>
</classpath>

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>libPluginTwitter</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
<linkedResources>
<link>
<name>android</name>
<type>2</type>
<locationURI>PARENT-1-PROJECT_LOC/platform/android</locationURI>
</link>
<link>
<name>include</name>
<type>2</type>
<locationURI>PARENT-1-PROJECT_LOC/include</locationURI>
</link>
</linkedResources>
</projectDescription>

View File

@ -0,0 +1,9 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.cocos2dx.libSocialTwitter"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="7" android:targetSdkVersion="15" />
</manifest>

View File

@ -0,0 +1 @@
db46ceaf2554c8d9e48cdaec3a4cdf5519bb8896

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<manifestConfig xmlns:android="http://schemas.android.com/apk/res/android">
<permissionCfg>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
</permissionCfg>
</manifestConfig>

View File

@ -0,0 +1,91 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="libPluginSocialTwitter" default="plugin-publish">
<!-- The local.properties file is created and updated by the 'android' tool.
It contains the path to the SDK. It should *NOT* be checked into
Version Control Systems. -->
<property file="local.properties" />
<!-- The ant.properties file can be created by you. It is only edited by the
'android' tool to add properties to it.
This is the place to change some Ant specific build properties.
Here are some properties you may want to change/update:
source.dir
The name of the source directory. Default is 'src'.
out.dir
The name of the output directory. Default is 'bin'.
For other overridable properties, look at the beginning of the rules
files in the SDK, at tools/ant/build.xml
Properties related to the SDK location or the project target should
be updated using the 'android' tool with the 'update' action.
This file is an integral part of the build system for your
application and should be checked into Version Control Systems.
-->
<property file="ant.properties" />
<!-- if sdk.dir was not set from one of the property file, then
get it from the ANDROID_HOME env var.
This must be done before we load project.properties since
the proguard config can use sdk.dir -->
<property environment="env" />
<condition property="sdk.dir" value="${env.ANDROID_HOME}">
<isset property="env.ANDROID_HOME" />
</condition>
<!-- The project.properties file is created and updated by the 'android'
tool, as well as ADT.
This contains project specific properties such as project target, and library
dependencies. Lower level build properties are stored in ant.properties
(or in .classpath for Eclipse projects).
This file is an integral part of the build system for your
application and should be checked into Version Control Systems. -->
<loadproperties srcFile="project.properties" />
<!-- quick check on sdk.dir -->
<fail
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
unless="sdk.dir"
/>
<!--
Import per project custom build rules if present at the root of the project.
This is the place to put custom intermediary targets such as:
-pre-build
-pre-compile
-post-compile (This is typically used for code obfuscation.
Compiled code location: ${out.classes.absolute.dir}
If this is not done in place, override ${out.dex.input.absolute.dir})
-post-package
-post-build
-pre-clean
-->
<import file="custom_rules.xml" optional="true" />
<!-- Import the actual build file.
To customize existing targets, there are two options:
- Customize only one target:
- copy/paste the target into this file, *before* the
<import> task.
- customize it to your needs.
- Customize the whole content of build.xml
- copy/paste the content of the rules files (minus the top node)
into this file, replacing the <import> task.
- customize to your needs.
***********************
****** IMPORTANT ******
***********************
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
in order to avoid having your file be overridden by tools such as "android update project"
-->
<!-- version-tag: 1 -->
<import file="${plugin.dir}/tools/android/build_common.xml" />
</project>

View File

@ -0,0 +1,20 @@
# set params
PLUGIN_ANDROID_ROOT=$(cd "$(dirname "$0")"; pwd)
if [ ! "${PLUGIN_ROOT}" ]; then
PLUGIN_ROOT="$PLUGIN_ANDROID_ROOT"/../..
fi
# build
"$ANDROID_NDK_ROOT"/ndk-build -C "$PLUGIN_ANDROID_ROOT" \
NDK_MODULE_PATH="$PLUGIN_ROOT"
echo
if [ "0" != "$?" ]; then
echo "Build error occoured!!!"
exit 1
fi
echo
echo "Native build action success."
exit 0

View File

@ -0,0 +1,29 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := PluginTwitterStatic
LOCAL_MODULE_FILENAME := libPluginTwitterStatic
LOCAL_SRC_FILES := \
$(addprefix ../../platform/android/, \
SocialTwitter.cpp \
) \
LOCAL_CFLAGS :=
LOCAL_EXPORT_CFLAGS :=
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../include
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/../../include
LOCAL_WHOLE_STATIC_LIBRARIES := PluginProtocolStatic
LOCAL_LDLIBS := -landroid
LOCAL_LDLIBS += -llog
include $(BUILD_STATIC_LIBRARY)
$(call import-module, protocols/proj.android/jni)

View File

@ -0,0 +1,7 @@
# it is needed for ndk-r5
APP_STL := gnustl_static
APP_CPPFLAGS += -frtti
APP_MODULES := PluginTwitterStatic
APP_ABI :=armeabi
#APP_ABI :=x86
#APP_ABI :=mips mips-r2 mips-r2-sf armeabi

View File

@ -0,0 +1,16 @@
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system edit
# "ant.properties", and override values to adapt the script to your
# project structure.
#
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
# Project target.
target=android-7
android.library=true
android.library.reference.1=../../../protocols/proj.android

View File

View File

@ -0,0 +1 @@
62d02b6f0d450b3b64d061280594018742ddcd27

View File

@ -0,0 +1,9 @@
package org.cocos2dx.plugin;
public interface Consts {
public static int EGETTING_ACCESS_TOKEN =0;
public static int EUSER_CANCELED = 1;
public static int EGETTING_REQUEST_TOKEN=2;
public static int EFAILED_OPENING_AUTHORIZATION_PAGE=3;
public static int EPAGE_ERROR =4;
}

View File

@ -0,0 +1,172 @@
package org.cocos2dx.plugin;
import java.util.Hashtable;
import org.cocos2dx.plugin.InterfaceSocial.ShareAdapter;
import org.cocos2dx.plugin.TwitterApp.TwDialogListener;
import android.app.Activity;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.util.Log;
public class SocialTwitter implements ShareAdapter {
private static final String LOG_TAG = "SocialTwitter";
private static Activity mContext = null;
protected static boolean bDebug = false;
private static String CONSUMER_KEY="";
private static String CONSUMER_SECRET="";
private static TwitterApp mTwitter = null;
private static boolean isInitialized = false;
private static Hashtable<String, String> mShareInfo = null;
public static String KEY_TEXT="text";
public static String KEY_IMAGE_PATH = "imagePath";
protected static void LogE(String msg, Exception e) {
Log.e(LOG_TAG, msg, e);
e.printStackTrace();
}
protected static void LogD(String msg) {
if (bDebug) {
Log.d(LOG_TAG, msg);
}
}
public SocialTwitter(Context context) {
mContext = (Activity) context;
}
@Override
public void initDeveloperInfo(Hashtable<String, String> cpInfo) {
LogD("initDeveloperInfo invoked " + cpInfo.toString());
mShareInfo = cpInfo;
mShareInfo = cpInfo;
try {
SocialTwitter.CONSUMER_KEY = cpInfo.get("consumerkey");
SocialTwitter.CONSUMER_SECRET = cpInfo.get("consumersecret");
if(isInitialized){
return;
}
isInitialized = true;
PluginWrapper.runOnMainThread(new Runnable() {
@Override
public void run() {
mTwitter = new TwitterApp(PluginWrapper.getContext(), SocialTwitter.CONSUMER_KEY, SocialTwitter.CONSUMER_SECRET);
mTwitter.setListener(mTwLoginDialogListener);
}
});
} catch (Exception e) {
LogE("Developer info is wrong!", e);
}
}
@Override
public void share(Hashtable<String, String> info) {
LogD("share invoked " + info.toString());
mShareInfo = info;
if (! networkReachable()) {
shareResult(InterfaceSocial.SHARERESULT_FAIL, "网络不可用");
return;
}
// need login
if(!mTwitter.hasAccessToken()){
PluginWrapper.runOnMainThread(new Runnable() {
@Override
public void run() {
mTwitter.authorize();
}
});
return;
}
PluginWrapper.runOnMainThread(new Runnable() {
@Override
public void run() {
String text = mShareInfo.get(KEY_TEXT);
String imagePath = mShareInfo.get(KEY_IMAGE_PATH);
try {
if(imagePath != null && imagePath.length() > 0){
mTwitter.updateStatus(text, imagePath);
}else{
mTwitter.updateStatus(text);
}
LogD("Posted to Twitter!");
shareResult(InterfaceSocial.SHARERESULT_SUCCESS, "user lihex");
} catch (Exception e) {
LogD("Post to Twitter failed!");
shareResult(InterfaceSocial.SHARERESULT_FAIL, "user lihex");
e.printStackTrace();
}
}
});
}
@Override
public void setDebugMode(boolean debug) {
bDebug = debug;
}
@Override
public String getSDKVersion() {
return "Unknown version";
}
private boolean networkReachable() {
boolean bRet = false;
try {
ConnectivityManager conn = (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = conn.getActiveNetworkInfo();
bRet = (null == netInfo) ? false : netInfo.isAvailable();
} catch (Exception e) {
LogE("Fail to check network status", e);
}
LogD("NetWork reachable : " + bRet);
return bRet;
}
private static void shareResult(int ret, String msg) {
InterfaceSocial.shareResult(ret, msg);
LogD("SocialTwitter result : " + ret + " msg : " + msg);
}
private static final TwDialogListener mTwLoginDialogListener = new TwDialogListener() {
@Override
public void onError(int flag, String value) {
LogD("Twitter connection failed!");
shareResult(InterfaceSocial.SHARERESULT_FAIL, value);
}
@Override
public void onComplete(String value) {
String username = mTwitter.getUsername();
LogD("Connected to Twitter as" + username);
String text = mShareInfo.get(KEY_TEXT);
String imagePath = mShareInfo.get(KEY_IMAGE_PATH);
try {
if(imagePath != null && imagePath.length() > 0){
mTwitter.updateStatus(text, imagePath);
}else{
mTwitter.updateStatus(text);
}
LogD("Posted to Twitter!");
shareResult(InterfaceSocial.SHARERESULT_SUCCESS, username);
} catch (Exception e) {
LogD("Post to Twitter failed!");
shareResult(InterfaceSocial.SHARERESULT_FAIL, username);
e.printStackTrace();
}
}
};
}

View File

@ -0,0 +1,237 @@
/**
* @author Lorensius W. L. T <lorenz@londatiga.net>
*
* http://www.londatiga.net
*/
package org.cocos2dx.plugin;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import oauth.signpost.OAuthProvider;
import oauth.signpost.basic.DefaultOAuthProvider;
import oauth.signpost.commonshttp.CommonsHttpOAuthConsumer;
import twitter4j.StatusUpdate;
import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.User;
import twitter4j.auth.AccessToken;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Window;
public class TwitterApp {
private Twitter mTwitter;
private TwitterSession mSession;
private AccessToken mAccessToken;
private CommonsHttpOAuthConsumer mHttpOauthConsumer;
private OAuthProvider mHttpOauthprovider;
private String mConsumerKey;
private String mSecretKey;
private ProgressDialog mProgressDlg;
private TwDialogListener mListener;
private Context context;
private boolean mInit = true;
private static final String LOG_TAG = "TwitterApp";
public static final String CALLBACK_URL = "twitterapp://connect";
protected static void LogE(String msg, Exception e) {
Log.e(LOG_TAG, msg, e);
e.printStackTrace();
}
protected static void LogD(String msg) {
if (SocialTwitter.bDebug) {
Log.d(LOG_TAG, msg);
}
}
public TwitterApp(Context context, String consumerKey, String secretKey) {
this.context = context;
mTwitter = new TwitterFactory().getInstance();
mSession = new TwitterSession(context);
mProgressDlg = new ProgressDialog(context);
mProgressDlg.setCancelable(false);
mProgressDlg.requestWindowFeature(Window.FEATURE_NO_TITLE);
mConsumerKey = consumerKey;
mSecretKey = secretKey;
mHttpOauthConsumer = new CommonsHttpOAuthConsumer(mConsumerKey, mSecretKey);
mHttpOauthprovider = new DefaultOAuthProvider("https://twitter.com/oauth/request_token",
"https://twitter.com/oauth/access_token",
"https://twitter.com/oauth/authorize");
mAccessToken = mSession.getAccessToken();
configureToken();
}
public void setListener(TwDialogListener listener) {
mListener = listener;
}
private void configureToken() {
if (mAccessToken != null) {
if (mInit) {
mTwitter.setOAuthConsumer(mConsumerKey, mSecretKey);
mInit = false;
}
mTwitter.setOAuthAccessToken(mAccessToken);
}
}
public boolean hasAccessToken() {
return (mAccessToken == null) ? false : true;
}
public void resetAccessToken() {
if (mAccessToken != null) {
mSession.resetAccessToken();
mAccessToken = null;
}
}
public String getUsername() {
return mSession.getUsername();
}
public void updateStatus(String status) throws Exception {
try {
mTwitter.updateStatus(status);
} catch (TwitterException e) {
throw e;
}
}
public void updateStatus(String status, String imagePath) throws Exception {
StatusUpdate update = new StatusUpdate(status);
update.setMedia(new File(imagePath));
try {
mTwitter.updateStatus(update);
} catch (TwitterException e) {
throw e;
}
}
public void authorize() {
mProgressDlg.setMessage("Initializing ...");
mProgressDlg.show();
new Thread() {
@Override
public void run() {
String authUrl = "";
int what = 1;
try {
authUrl = mHttpOauthprovider.retrieveRequestToken(mHttpOauthConsumer, CALLBACK_URL);
what = 0;
LogD("Request token url " + authUrl);
} catch (Exception e) {
LogD("Failed to get request token");
e.printStackTrace();
}
mHandler.sendMessage(mHandler.obtainMessage(what, 1, 0, authUrl));
}
}.start();
}
public void processToken(String callbackUrl) {
mProgressDlg.setMessage("Finalizing ...");
mProgressDlg.show();
final String verifier = getVerifier(callbackUrl);
new Thread() {
@Override
public void run() {
int what = 1;
try {
mHttpOauthprovider.retrieveAccessToken(mHttpOauthConsumer, verifier);
mAccessToken = new AccessToken(mHttpOauthConsumer.getToken(), mHttpOauthConsumer.getTokenSecret());
configureToken();
User user = mTwitter.verifyCredentials();
mSession.storeAccessToken(mAccessToken, user.getName());
what = 0;
} catch (Exception e){
LogD("Error getting access token");
e.printStackTrace();
}
mHandler.sendMessage(mHandler.obtainMessage(what, 2, 0));
}
}.start();
}
private String getVerifier(String callbackUrl) {
String verifier = "";
try {
callbackUrl = callbackUrl.replace("twitterapp", "http");
URL url = new URL(callbackUrl);
String query = url.getQuery();
String array[] = query.split("&");
for (String parameter : array) {
String v[] = parameter.split("=");
if (URLDecoder.decode(v[0]).equals(oauth.signpost.OAuth.OAUTH_VERIFIER)) {
verifier = URLDecoder.decode(v[1]);
break;
}
}
} catch (MalformedURLException e) {
e.printStackTrace();
}
return verifier;
}
private void showLoginDialog(String url) {
final TwDialogListener listener = new TwDialogListener() {
@Override
public void onComplete(String value) {
processToken(value);
}
@Override
public void onError(int flag, String value) {
mListener.onError(Consts.EFAILED_OPENING_AUTHORIZATION_PAGE, "Failed opening authorization page");
}
};
new TwitterDialog(context, url, listener).show();
}
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
mProgressDlg.dismiss();
if (msg.what == 1) {
if (msg.arg1 == 1)
mListener.onError(Consts.EGETTING_REQUEST_TOKEN, "Error getting request token");
else
mListener.onError(Consts.EGETTING_ACCESS_TOKEN, "Error getting access token");
}else {
if (msg.arg1 == 1)
showLoginDialog((String) msg.obj);
else
mListener.onComplete("");
}
}
};
public interface TwDialogListener {
public void onComplete(String value);
public void onError(int flag, String value);
}
}

View File

@ -0,0 +1,182 @@
/**
* Modified from FbDialog from Facebook SDK
*
* Lorensius W. L. T <lorenz@londatiga.net>
*/
package org.cocos2dx.plugin;
import org.cocos2dx.plugin.TwitterApp.TwDialogListener;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Typeface;
import android.os.Bundle;
import android.util.Log;
import android.view.Display;
import android.view.ViewGroup;
import android.view.Window;
import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;
public class TwitterDialog extends Dialog {
static final FrameLayout.LayoutParams FILL = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.FILL_PARENT);
static final int MARGIN = 4;
static final int PADDING = 2;
private String mUrl;
private TwDialogListener mListener;
private ProgressDialog mSpinner;
private WebView mWebView;
private LinearLayout mContent;
private TextView mTitle;
private static final String LOG_TAG = "Twitter-WebView";
protected static void LogD(String msg) {
if (SocialTwitter.bDebug) {
Log.d(LOG_TAG, msg);
}
}
public TwitterDialog(Context context, String url, TwDialogListener listener) {
super(context);
mUrl = url;
mListener = listener;
setOnCancelListener(mCancelListener);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mSpinner = new ProgressDialog(getContext());
mSpinner.requestWindowFeature(Window.FEATURE_NO_TITLE);
mSpinner.setMessage("Loading...");
mSpinner.setCancelable(false);
mContent = new LinearLayout(getContext());
mContent.setOrientation(LinearLayout.VERTICAL);
setUpTitle();
setUpWebView();
Display display = getWindow().getWindowManager().getDefaultDisplay();
double[] dimensions = new double[2];
if (display.getWidth() < display.getHeight()) {
dimensions[0] = 0.87 * display.getWidth();
dimensions[1] = 0.82 * display.getHeight();
} else {
dimensions[0] = 0.75 * display.getWidth();
dimensions[1] = 0.75 * display.getHeight();
}
addContentView(mContent, new FrameLayout.LayoutParams((int) dimensions[0], (int) dimensions[1]));
}
private void setUpTitle() {
requestWindowFeature(Window.FEATURE_NO_TITLE);
// Drawable icon = getContext().getResources().getDrawable(R.drawable.twitter_icon);
mTitle = new TextView(getContext());
mTitle.setText("Twitter");
mTitle.setTextColor(Color.WHITE);
mTitle.setTypeface(Typeface.DEFAULT_BOLD);
mTitle.setBackgroundColor(0xFFbbd7e9);
mTitle.setPadding(MARGIN + PADDING, MARGIN, MARGIN, MARGIN);
mTitle.setCompoundDrawablePadding(MARGIN + PADDING);
// mTitle.setCompoundDrawablesWithIntrinsicBounds(icon, null, null, null);
mTitle.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null);
mContent.addView(mTitle);
}
private void setUpWebView() {
CookieSyncManager.createInstance(getContext());
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.removeAllCookie();
mWebView = new WebView(getContext());
mWebView.setVerticalScrollBarEnabled(false);
mWebView.setHorizontalScrollBarEnabled(false);
mWebView.setWebViewClient(new TwitterWebViewClient());
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.loadUrl(mUrl);
mWebView.setLayoutParams(FILL);
mContent.addView(mWebView);
}
private class TwitterWebViewClient extends WebViewClient {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
LogD("Redirecting URL " + url);
if (url.startsWith(TwitterApp.CALLBACK_URL)) {
mListener.onComplete(url);
TwitterDialog.this.dismiss();
return true;
} else if (url.startsWith("authorize")) {
return false;
}
return true;
}
@Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
LogD("Page error: " + description);
super.onReceivedError(view, errorCode, description, failingUrl);
mListener.onError(Consts.EPAGE_ERROR, description);
TwitterDialog.this.dismiss();
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
LogD("Loading URL: " + url);
super.onPageStarted(view, url, favicon);
mSpinner.show();
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
String title = mWebView.getTitle();
if (title != null && title.length() > 0) {
mTitle.setText(title);
}
mSpinner.dismiss();
}
}
private DialogInterface.OnCancelListener mCancelListener = new OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
mSpinner.dismiss();
mListener.onError(Consts.EUSER_CANCELED, "User canceled!");
}
};
}

View File

@ -0,0 +1,56 @@
/**
* @author Lorensius W. L. T <lorenz@londatiga.net>
*
* http://www.londatiga.net
*/
package org.cocos2dx.plugin;
import twitter4j.auth.AccessToken;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
public class TwitterSession {
private SharedPreferences sharedPref;
private Editor editor;
private static final String TWEET_AUTH_KEY = "auth_key";
private static final String TWEET_AUTH_SECRET_KEY = "auth_secret_key";
private static final String TWEET_USER_NAME = "user_name";
private static final String SHARED = "Twitter_Preferences";
public TwitterSession(Context context) {
sharedPref = context.getSharedPreferences(SHARED, Context.MODE_PRIVATE);
editor = sharedPref.edit();
}
public void storeAccessToken(AccessToken accessToken, String username) {
editor.putString(TWEET_AUTH_KEY, accessToken.getToken());
editor.putString(TWEET_AUTH_SECRET_KEY, accessToken.getTokenSecret());
editor.putString(TWEET_USER_NAME, username);
editor.commit();
}
public void resetAccessToken() {
editor.putString(TWEET_AUTH_KEY, null);
editor.putString(TWEET_AUTH_SECRET_KEY, null);
editor.putString(TWEET_USER_NAME, null);
editor.commit();
}
public String getUsername() {
return sharedPref.getString(TWEET_USER_NAME, "");
}
public AccessToken getAccessToken() {
String token = sharedPref.getString(TWEET_AUTH_KEY, null);
String tokenSecret = sharedPref.getString(TWEET_AUTH_SECRET_KEY, null);
if (token != null && tokenSecret != null)
return new AccessToken(token, tokenSecret);
else
return null;
}
}

View File

@ -0,0 +1,89 @@
#ifndef __CXX_PROTOCOL_SOCIAL_H__
#define __CXX_PROTOCOL_SOCIAL_H__
#include "PluginProtocol.h"
#include <map>
#include <string>
namespace cocos2d { namespace plugin {
typedef std::map<std::string, std::string> TDeveloperInfo;
typedef std::map<std::string, std::string> TShareInfo;
typedef enum
{
eShareSuccess = 0,
eShareFail,
eShareCancel,
eShareTimeOut,
} EShareResult;
class ShareResultListener
{
public:
virtual void shareResult(EShareResult ret, const char* msg, TShareInfo info) = 0;
};
class ProtocolSocial : public PluginProtocol
{
public:
/**
@brief plugin initialization
*/
virtual bool init();
/**
@brief initialize the developer info
@param devInfo This parameter is the info of developer,
different plugin have different format
@warning Must invoke this interface before other interfaces.
And invoked only once.
*/
virtual void initDeveloperInfo(TDeveloperInfo devInfo);
/**
@brief share information
@param info The info of share, must contains key:
text The text of share
@warning For different plugin, the parameter should have other keys to share.
Look at the manual of plugins.
*/
virtual void share(TShareInfo info);
/**
@brief Set whether needs to output logs to console.
@param debug if true debug mode enabled, or debug mode disabled.
*/
virtual void setDebugMode(bool debug);
/**
@breif set the result listener
@param pListener The callback object for share result
@wraning Must invoke this interface before share
*/
static void setResultListener(ShareResultListener* pListener);
/**
@brief share result callback
*/
static void shareResult(EShareResult ret, const char* msg);
virtual const char* getPluginVersion() { return "ProtocolSocial, v0.1.00 , subclass should override this interface!"; };
virtual const char* getSDKVersion();
virtual const char* getPluginName() = 0;
protected:
ProtocolSocial();
public:
virtual ~ProtocolSocial();
protected:
static bool m_bSharing;
static ShareResultListener* m_pListener;
static TShareInfo m_curInfo;
};
}} // namespace cocos2d { namespace plugin {
#endif /* ----- #ifndef __CXX_PROTOCOL_SOCIAL_H__ ----- */

View File

@ -0,0 +1,151 @@
#include "ProtocolSocial.h"
#include "PluginJniHelper.h"
#include <android/log.h>
#include "PluginUtils.h"
#include "PluginJavaData.h"
#if 1
#define LOG_TAG "ProtocolSocial"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
#else
#define LOGD(...)
#endif
namespace cocos2d { namespace plugin {
extern "C" {
JNIEXPORT void JNICALL Java_org_cocos2dx_plugin_InterfaceSocial_nativeShareResult(JNIEnv* env, jobject thiz, jint ret, jstring msg)
{
std::string strMsg = PluginJniHelper::jstring2string(msg);
ProtocolSocial::shareResult((EShareResult) ret, strMsg.c_str());
}
}
bool ProtocolSocial::m_bSharing = false;
ShareResultListener* ProtocolSocial::m_pListener = NULL;
TShareInfo ProtocolSocial::m_curInfo;
ProtocolSocial::ProtocolSocial()
{
}
ProtocolSocial::~ProtocolSocial()
{
PluginUtils::erasePluginJavaData(this);
}
bool ProtocolSocial::init()
{
return true;
}
void ProtocolSocial::initDeveloperInfo(TDeveloperInfo devInfo)
{
if (devInfo.empty())
{
LOGD("The developer info is empty!");
return;
}
else
{
PluginJavaData* pData = PluginUtils::getPluginJavaData(this);
PluginJniMethodInfo t;
if (PluginJniHelper::getMethodInfo(t
, pData->jclassName.c_str()
, "initDeveloperInfo"
, "(Ljava/util/Hashtable;)V"))
{
// generate the hashtable from map
jobject obj_Map = PluginUtils::createJavaMapObject(t, &devInfo);
// invoke java method
t.env->CallVoidMethod(pData->jobj, t.methodID, obj_Map);
t.env->DeleteLocalRef(obj_Map);
t.env->DeleteLocalRef(t.classID);
}
}
}
void ProtocolSocial::share(TShareInfo info)
{
if (m_bSharing)
{
LOGD("Now is sharing");
return;
}
if (info.empty())
{
if (NULL != m_pListener)
{
shareResult(eShareFail, "Share info error");
}
LOGD("The Share info is empty!");
return;
}
else
{
m_bSharing = true;
m_curInfo = info;
PluginJavaData* pData = PluginUtils::getPluginJavaData(this);
PluginJniMethodInfo t;
if (PluginJniHelper::getMethodInfo(t
, pData->jclassName.c_str()
, "share"
, "(Ljava/util/Hashtable;)V"))
{
// generate the hashtable from map
jobject obj_Map = PluginUtils::createJavaMapObject(t, &info);
// invoke java method
t.env->CallVoidMethod(pData->jobj, t.methodID, obj_Map);
t.env->DeleteLocalRef(obj_Map);
t.env->DeleteLocalRef(t.classID);
}
}
}
void ProtocolSocial::setResultListener(ShareResultListener* pListener)
{
m_pListener = pListener;
}
void ProtocolSocial::shareResult(EShareResult ret, const char* msg)
{
m_bSharing = false;
if (m_pListener)
{
m_pListener->shareResult(ret, msg, m_curInfo);
}
else
{
LOGD("Result listener is null!");
}
m_curInfo.clear();
LOGD("Share result is : %d(%s)", (int) ret, msg);
}
const char* ProtocolSocial::getSDKVersion()
{
std::string verName;
PluginJavaData* pData = PluginUtils::getPluginJavaData(this);
PluginJniMethodInfo t;
if (PluginJniHelper::getMethodInfo(t
, pData->jclassName.c_str()
, "getSDKVersion"
, "()Ljava/lang/String;"))
{
jstring ret = (jstring)(t.env->CallObjectMethod(pData->jobj, t.methodID));
verName = PluginJniHelper::jstring2string(ret);
}
return verName.c_str();
}
void ProtocolSocial::setDebugMode(bool debug)
{
PluginUtils::callJavaFunctionWithName_oneBaseType(this, "setDebugMode", "(Z)V", debug);
}
}} // namespace cocos2d { namespace plugin {

1
plugin/protocols/proj.android/jni/Android.mk Normal file → Executable file
View File

@ -13,6 +13,7 @@ $(addprefix ../../platform/android/, \
ProtocolAnalytics.cpp \
ProtocolIAP.cpp \
ProtocolAds.cpp \
ProtocolSocial.cpp \
) \
../../PluginManager.cpp \
../../RegisterPlugin.cpp \

View File

@ -0,0 +1,29 @@
package org.cocos2dx.plugin;
import java.util.Hashtable;
public class InterfaceSocial {
public static final int SHARERESULT_SUCCESS = 0;
public static final int SHARERESULT_FAIL = 1;
public static final int SHARERESULT_CANCEL = 2;
public static final int SHARERESULT_TIMEOUT = 3;
public interface ShareAdapter {
public void initDeveloperInfo(Hashtable<String, String> cpInfo);
public void share(Hashtable<String, String> cpInfo);
public void setDebugMode(boolean debug);
public String getSDKVersion();
}
public static void shareResult(int ret, String msg) {
final int curRet = ret;
final String curMsg = msg;
PluginWrapper.runOnGLThread(new Runnable() {
@Override
public void run() {
nativeShareResult(curRet, curMsg);
}
});
}
private static native void nativeShareResult(int ret, String msg);
}

View File

@ -0,0 +1,60 @@
#include "AppDelegate.h"
#include "cocos2d.h"
#include "HelloWorldScene.h"
#include "PluginManager.h"
#include "MyShareManager.h"
using namespace cocos2d::plugin;
USING_NS_CC;
AppDelegate::AppDelegate()
{
}
AppDelegate::~AppDelegate()
{
}
bool AppDelegate::applicationDidFinishLaunching()
{
MyShareManager::sharedManager()->loadSocialPlugin();
// initialize director
CCDirector *pDirector = CCDirector::sharedDirector();
pDirector->setOpenGLView(CCEGLView::sharedOpenGLView());
CCEGLView* pEGLView = CCEGLView::sharedOpenGLView();
pEGLView->setDesignResolutionSize(960.0f, 640.0f, kResolutionNoBorder);
// turn on display FPS
pDirector->setDisplayStats(true);
// set FPS. the default value is 1.0/60 if you don't call this
pDirector->setAnimationInterval(1.0 / 60);
// create a scene. it's an autorelease object
CCScene *pScene = HelloWorld::scene();
// run
pDirector->runWithScene(pScene);
return true;
}
// This function will be called when the app is inactive. When comes a phone call,it's be invoked too
void AppDelegate::applicationDidEnterBackground()
{
CCDirector::sharedDirector()->pause();
// if you use SimpleAudioEngine, it must be pause
// SimpleAudioEngine::sharedEngine()->pauseBackgroundMusic();
}
// this function will be called when the app is active again
void AppDelegate::applicationWillEnterForeground()
{
CCDirector::sharedDirector()->resume();
// if you use SimpleAudioEngine, it must resume here
// SimpleAudioEngine::sharedEngine()->resumeBackgroundMusic();
}

View File

@ -0,0 +1,40 @@
#ifndef _APP_DELEGATE_H_
#define _APP_DELEGATE_H_
#include "CCApplication.h"
/**
@brief The cocos2d Application.
The reason for implement as private inheritance is to hide some interface call by CCDirector.
*/
class AppDelegate : private cocos2d::CCApplication
{
public:
AppDelegate();
virtual ~AppDelegate();
/**
@brief Implement CCDirector and CCScene init code here.
@return true Initialize success, app continue.
@return false Initialize failed, app terminate.
*/
virtual bool applicationDidFinishLaunching();
/**
@brief The function be called when the application enter background
@param the pointer of the application
*/
virtual void applicationDidEnterBackground();
/**
@brief The function be called when the application enter foreground
@param the pointer of the application
*/
virtual void applicationWillEnterForeground();
static void loadAnalyticsPlugin();
};
#endif // _APP_DELEGATE_H_

View File

@ -0,0 +1,126 @@
#include "HelloWorldScene.h"
#include "PluginManager.h"
#include "AppDelegate.h"
#include "MyShareManager.h"
using namespace cocos2d;
using namespace cocos2d::plugin;
enum {
TAG_PAY_BY_ALIPAY = 100,
TAG_PAY_BY_ND91,
};
typedef struct tagEventMenuItem {
std::string id;
int tag;
}EventMenuItem;
static EventMenuItem s_EventMenuItem[] = {
{"twitter.jpeg", TAG_PAY_BY_ALIPAY}
};
CCScene* HelloWorld::scene()
{
// 'scene' is an autorelease object
CCScene *scene = CCScene::create();
// 'layer' is an autorelease object
HelloWorld *layer = HelloWorld::create();
// add layer as a child to scene
scene->addChild(layer);
// return the scene
return scene;
}
// on "init" you need to initialize your instance
bool HelloWorld::init()
{
//////////////////////////////
// 1. super init first
if ( !CCLayer::init() )
{
return false;
}
CCSize size = CCDirector::sharedDirector()->getVisibleSize();
CCSprite* pBackground = CCSprite::create("background.png");
pBackground->setPosition(ccp(size.width / 2, size.height / 2));
addChild(pBackground);
/////////////////////////////
// 2. add a menu item with "X" image, which is clicked to quit the program
// you may modify it.
CCEGLView* pEGLView = CCEGLView::sharedOpenGLView();
CCPoint posBR = ccp(pEGLView->getVisibleOrigin().x + pEGLView->getVisibleSize().width, pEGLView->getVisibleOrigin().y);
CCPoint posBC = ccp(pEGLView->getVisibleOrigin().x + pEGLView->getVisibleSize().width/2, pEGLView->getVisibleOrigin().y);
CCPoint posTL = ccp(pEGLView->getVisibleOrigin().x, pEGLView->getVisibleOrigin().y + pEGLView->getVisibleSize().height);
// add a "close" icon to exit the progress. it's an autorelease object
CCMenuItemImage *pCloseItem = CCMenuItemImage::create(
"CloseNormal.png",
"CloseSelected.png",
this,
menu_selector(HelloWorld::menuCloseCallback) );
pCloseItem->setPosition( ccp(posBR.x - 20, posBR.y + 20) );
// create menu, it's an autorelease object
CCMenu* pMenu = CCMenu::create(pCloseItem, NULL);
pMenu->setPosition( CCPointZero );
this->addChild(pMenu, 1);
CCPoint posStep = ccp(220, -150);
CCPoint beginPos = ccpAdd(posTL, ccpMult(posStep, 0.5f));
int line = 0;
int row = 0;
for (int i = 0; i < sizeof(s_EventMenuItem)/sizeof(s_EventMenuItem[0]); i++) {
CCMenuItemImage* pMenuItem = CCMenuItemImage::create(s_EventMenuItem[i].id.c_str(), s_EventMenuItem[i].id.c_str(),
this, menu_selector(HelloWorld::eventMenuCallback));
pMenu->addChild(pMenuItem, 0, s_EventMenuItem[i].tag);
CCPoint pos = ccpAdd(beginPos, ccp(posStep.x * row, posStep.y * line));
CCSize itemSize = pMenuItem->getContentSize();
if ((pos.x + itemSize.width / 2) > posBR.x)
{
line += 1;
row = 0;
pos = ccpAdd(beginPos, ccp(posStep.x * row, posStep.y * line));
}
row += 1;
pMenuItem->setPosition(pos);
}
CCLabelTTF* label = CCLabelTTF::create("Reload all plugins", "Arial", 24);
CCMenuItemLabel* pMenuItem = CCMenuItemLabel::create(label, this, menu_selector(HelloWorld::reloadPluginMenuCallback));
pMenuItem->setAnchorPoint(ccp(0.5f, 0));
pMenu->addChild(pMenuItem, 0);
pMenuItem->setPosition(posBC);
return true;
}
void HelloWorld::reloadPluginMenuCallback(CCObject* pSender)
{
MyShareManager::sharedManager()->unloadSocialPlugin();
MyShareManager::sharedManager()->loadSocialPlugin();
}
void HelloWorld::eventMenuCallback(CCObject* pSender)
{
TShareInfo pInfo;
pInfo["text"] = "MyFirst tweet!";
// pInfo["imagePath"] = "Full/path/to/image";
MyShareManager::sharedManager()->shareByMode(pInfo, MyShareManager::eTwitter);
}
void HelloWorld::menuCloseCallback(CCObject* pSender)
{
MyShareManager::purgeManager();
CCDirector::sharedDirector()->end();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
exit(0);
#endif
}

View File

@ -0,0 +1,24 @@
#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__
#include "cocos2d.h"
class HelloWorld : public cocos2d::CCLayer
{
public:
// Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
virtual bool init();
// there's no 'id' in cpp, so we recommand to return the exactly class pointer
static cocos2d::CCScene* scene();
// a selector callback
void menuCloseCallback(CCObject* pSender);
void eventMenuCallback(CCObject* pSender);
void reloadPluginMenuCallback(CCObject* pSender);
// implement the "static node()" method manually
CREATE_FUNC(HelloWorld);
};
#endif // __HELLOWORLD_SCENE_H__

View File

@ -0,0 +1,106 @@
#include "MyShareManager.h"
#include "PluginManager.h"
#include "cocos2d.h"
using namespace cocos2d::plugin;
using namespace cocos2d;
MyShareManager* MyShareManager::s_pManager = NULL;
MyShareManager::MyShareManager()
: s_pRetListener(NULL)
, s_pTwitter(NULL)
{
}
MyShareManager::~MyShareManager()
{
unloadSocialPlugin();
if (s_pRetListener)
{
delete s_pRetListener;
}
}
MyShareManager* MyShareManager::sharedManager()
{
if (s_pManager == NULL) {
s_pManager = new MyShareManager();
}
return s_pManager;
}
void MyShareManager::purgeManager()
{
if (s_pManager)
{
delete s_pManager;
}
}
void MyShareManager::loadSocialPlugin()
{
{
// init twitter plugin
s_pTwitter = dynamic_cast<SocialTwitter*>(PluginManager::getInstance()->loadPlugin("SocialTwitter"));
TDeveloperInfo pTwitterInfo;
/* Warning: must set your twiiter dev info here */
// pTwitterInfo["consumerkey"] = "your consumerkey";
// pTwitterInfo["consumersecret"] = "your consumersecret";
if (pTwitterInfo.empty())
{
char msg[256] = { 0 };
sprintf(msg, "Developer info is empty. PLZ fill your twitter info in %s(nearby line %d)", __FILE__, __LINE__);
CCMessageBox(msg, "Twitter Warning");
}
s_pTwitter->setDebugMode(true);
s_pTwitter->initDeveloperInfo(pTwitterInfo);
}
if (s_pRetListener == NULL)
{
s_pRetListener = new MyShareResult();
ProtocolSocial::setResultListener(s_pRetListener);
}
}
void MyShareManager::unloadSocialPlugin()
{
if (s_pTwitter)
{
PluginManager::getInstance()->unloadPlugin("SocialTwitter");
s_pTwitter = NULL;
}
}
void MyShareManager::shareByMode(TShareInfo info, MyShareMode mode)
{
ProtocolSocial* pShare = NULL;
switch(mode)
{
case eTwitter:
pShare = s_pTwitter;
break;
default:
break;
}
if (pShare) {
pShare->share(info);
}
}
void MyShareResult::shareResult(EShareResult ret, const char* msg, TShareInfo info)
{
char shareInfo[1024] = { 0 };
char shareStatus[1024] = { 0 };
sprintf(shareStatus, "Share info:%s", (ret == eShareSuccess)? "Successed" : "Failed");
sprintf(shareInfo, " %s\ntext:%s",
shareStatus,
info.find("text")->second.c_str()
);
CCMessageBox(shareInfo , msg);
}

View File

@ -0,0 +1,37 @@
#ifndef __MY_SHARE_MANAGER_H__
#define __MY_SHARE_MANAGER_H__
#include "SocialTwitter.h"
class MyShareResult : public cocos2d::plugin::ShareResultListener
{
public:
virtual void shareResult(cocos2d::plugin::EShareResult ret, const char* msg, cocos2d::plugin::TShareInfo info);
};
class MyShareManager
{
public:
static MyShareManager* sharedManager();
static void purgeManager();
typedef enum {
eNoneMode = 0,
eTwitter,
} MyShareMode;
void unloadSocialPlugin();
void loadSocialPlugin();
void shareByMode(cocos2d::plugin::TShareInfo info, MyShareMode mode);
private:
MyShareManager();
virtual ~MyShareManager();
static MyShareManager* s_pManager;
cocos2d::plugin::SocialTwitter* s_pTwitter;
MyShareResult* s_pRetListener;
};
#endif // __MY_SHARE_MANAGER_H__

View File

@ -0,0 +1 @@
b2e4ae6ce873ef4a74cf0230693ef26e939d2778

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
<classpathentry exported="true" kind="lib" path="publish/protocols/android/libPluginProtocol.jar"/>
<classpathentry exported="true" kind="lib" path="/Users/lihex/cocos2d-x/plugin/publish/plugins/twitter/android/libPluginSocialTwitter.jar"/>
<classpathentry exported="true" kind="lib" path="publish/plugins/twitter/android/signpost-commonshttp4-1.2.1.1.jar"/>
<classpathentry exported="true" kind="lib" path="publish/plugins/twitter/android/signpost-core-1.2.1.1.jar"/>
<classpathentry exported="true" kind="lib" path="publish/plugins/twitter/android/signpost-jetty6-1.2.1.1.jar"/>
<classpathentry exported="true" kind="lib" path="publish/plugins/twitter/android/twitter4j-core-android-3.0.1.jar"/>
<classpathentry kind="output" path="bin/classes"/>
</classpath>

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>HelloSocial</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
<linkedResources>
<link>
<name>Classes</name>
<type>2</type>
<locationURI>PARENT-1-PROJECT_LOC/Classes</locationURI>
</link>
<link>
<name>publish</name>
<type>2</type>
<locationURI>PARENT-3-PROJECT_LOC/publish</locationURI>
</link>
</linkedResources>
</projectDescription>

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.cocos2dx.helloSocial"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="8"/>
<application android:label="@string/app_name"
android:debuggable="true"
android:icon="@drawable/icon">
<activity android:name=".HelloSocial"
android:label="@string/app_name"
android:screenOrientation="landscape"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:configChanges="orientation">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<!-- Twitter permission -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
</manifest>

View File

@ -0,0 +1,17 @@
# This file is used to override default values used by the Ant build system.
#
# This file must be checked into Version Control Systems, as it is
# integral to the build system of your project.
# This file is only used by the Ant script.
# You can use this to override default values such as
# 'source.dir' for the location of your java source folder and
# 'out.dir' for the location of your output folder.
# You can also use it define how the release builds are signed by declaring
# the following properties:
# 'key.store' for the location of your keystore and
# 'key.alias' for the name of the key to use.
# The password will be asked during the build when you use the 'release' target.

View File

@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="HelloAnalytics" default="help">
<!-- The local.properties file is created and updated by the 'android' tool.
It contains the path to the SDK. It should *NOT* be checked into
Version Control Systems. -->
<property file="local.properties" />
<!-- The ant.properties file can be created by you. It is only edited by the
'android' tool to add properties to it.
This is the place to change some Ant specific build properties.
Here are some properties you may want to change/update:
source.dir
The name of the source directory. Default is 'src'.
out.dir
The name of the output directory. Default is 'bin'.
For other overridable properties, look at the beginning of the rules
files in the SDK, at tools/ant/build.xml
Properties related to the SDK location or the project target should
be updated using the 'android' tool with the 'update' action.
This file is an integral part of the build system for your
application and should be checked into Version Control Systems.
-->
<property file="ant.properties" />
<!-- if sdk.dir was not set from one of the property file, then
get it from the ANDROID_HOME env var.
This must be done before we load project.properties since
the proguard config can use sdk.dir -->
<property environment="env" />
<condition property="sdk.dir" value="${env.ANDROID_HOME}">
<isset property="env.ANDROID_HOME" />
</condition>
<!-- The project.properties file is created and updated by the 'android'
tool, as well as ADT.
This contains project specific properties such as project target, and library
dependencies. Lower level build properties are stored in ant.properties
(or in .classpath for Eclipse projects).
This file is an integral part of the build system for your
application and should be checked into Version Control Systems. -->
<loadproperties srcFile="project.properties" />
<!-- quick check on sdk.dir -->
<fail
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
unless="sdk.dir"
/>
<!--
Import per project custom build rules if present at the root of the project.
This is the place to put custom intermediary targets such as:
-pre-build
-pre-compile
-post-compile (This is typically used for code obfuscation.
Compiled code location: ${out.classes.absolute.dir}
If this is not done in place, override ${out.dex.input.absolute.dir})
-post-package
-post-build
-pre-clean
-->
<import file="custom_rules.xml" optional="true" />
<!-- Import the actual build file.
To customize existing targets, there are two options:
- Customize only one target:
- copy/paste the target into this file, *before* the
<import> task.
- customize it to your needs.
- Customize the whole content of build.xml
- copy/paste the content of the rules files (minus the top node)
into this file, replacing the <import> task.
- customize to your needs.
***********************
****** IMPORTANT ******
***********************
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
in order to avoid having your file be overridden by tools such as "android update project"
-->
<!-- version-tag: 1 -->
<import file="${sdk.dir}/tools/ant/build.xml" />
</project>

View File

@ -0,0 +1,81 @@
APPNAME="HelloAnalytics"
# options
buildexternalsfromsource=
usage(){
cat << EOF
usage: $0 [options]
Build C/C++ code for $APPNAME using Android NDK
OPTIONS:
-s Build externals from source
-h this help
EOF
}
while getopts "sh" OPTION; do
case "$OPTION" in
s)
buildexternalsfromsource=1
;;
h)
usage
exit 0
;;
esac
done
# paths
if [ -z "${NDK_ROOT+aaa}" ];then
echo "please define NDK_ROOT"
exit 1
fi
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# ... use paths relative to current directory
PLUGIN_ROOT="$DIR/../../.."
COCOS2DX_ROOT="$DIR/../../../.."
APP_ROOT="$DIR/.."
APP_ANDROID_ROOT="$DIR"
echo "PLUGIN_ROOT = $PLUGIN_ROOT"
echo "NDK_ROOT = $NDK_ROOT"
echo "COCOS2DX_ROOT = $COCOS2DX_ROOT"
echo "APP_ROOT = $APP_ROOT"
echo "APP_ANDROID_ROOT = $APP_ANDROID_ROOT"
echo "---------------------------------------------------------"
# make sure assets is exist
if [ -d "$APP_ANDROID_ROOT"/assets ]; then
rm -rf "$APP_ANDROID_ROOT"/assets
fi
mkdir "$APP_ANDROID_ROOT"/assets
# copy resources
for file in "$APP_ROOT"/Resources/*
do
if [ -d "$file" ]; then
cp -rf "$file" "$APP_ANDROID_ROOT"/assets
fi
if [ -f "$file" ]; then
cp "$file" "$APP_ANDROID_ROOT"/assets
fi
done
if [[ "$buildexternalsfromsource" ]]; then
echo "Building external dependencies from source"
set -x
"$NDK_ROOT"/ndk-build -j 4 -C "$APP_ANDROID_ROOT" $* \
"NDK_MODULE_PATH=${PLUGIN_ROOT}/publish:${COCOS2DX_ROOT}:${COCOS2DX_ROOT}/cocos2dx/platform/third_party/android/source"
else
echo "Using prebuilt externals"
set -x
"$NDK_ROOT"/ndk-build -j 4 -C "$APP_ANDROID_ROOT" $* \
"NDK_MODULE_PATH=${PLUGIN_ROOT}/publish:${COCOS2DX_ROOT}:${COCOS2DX_ROOT}/cocos2dx/platform/third_party/android/prebuilt"
fi

View File

@ -0,0 +1,24 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := game_shared
LOCAL_MODULE_FILENAME := libgame
LOCAL_SRC_FILES := hellocpp/main.cpp \
../../Classes/AppDelegate.cpp \
../../Classes/HelloWorldScene.cpp \
../../Classes/MyShareManager.cpp
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../Classes
LOCAL_WHOLE_STATIC_LIBRARIES := cocos2dx_static \
PluginTwitterStatic \
PluginProtocolStatic
include $(BUILD_SHARED_LIBRARY)
$(call import-module,cocos2dx) \
$(call import-module,plugins/twitter/android) \
$(call import-module,protocols/android)

View File

@ -0,0 +1,2 @@
APP_STL := gnustl_static
APP_CPPFLAGS += -frtti

View File

@ -0,0 +1,47 @@
#include "AppDelegate.h"
#include "platform/android/jni/JniHelper.h"
#include "PluginJniHelper.h"
#include <jni.h>
#include <android/log.h>
#include "HelloWorldScene.h"
#define LOG_TAG "main"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
using namespace cocos2d;
extern "C"
{
jint JNI_OnLoad(JavaVM *vm, void *reserved)
{
JniHelper::setJavaVM(vm);
PluginJniHelper::setJavaVM(vm);
return JNI_VERSION_1_4;
}
void Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInit(JNIEnv* env, jobject thiz, jint w, jint h)
{
if (!CCDirector::sharedDirector()->getOpenGLView())
{
CCEGLView *view = CCEGLView::sharedOpenGLView();
view->setFrameSize(w, h);
AppDelegate *pAppDelegate = new AppDelegate();
CCApplication::sharedApplication()->run();
}
else
{
ccDrawInit();
ccGLInvalidateStateCache();
CCShaderCache::sharedShaderCache()->reloadDefaultShaders();
CCTextureCache::reloadAllTextures();
CCNotificationCenter::sharedNotificationCenter()->postNotification(EVNET_COME_TO_FOREGROUND, NULL);
CCDirector::sharedDirector()->setGLDefaultValues();
}
}
}

View File

@ -0,0 +1,20 @@
# To enable ProGuard in your project, edit project.properties
# to define the proguard.config property as described in that file.
#
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in ${sdk.dir}/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the ProGuard
# include property in project.properties.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

View File

@ -0,0 +1,15 @@
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system edit
# "ant.properties", and override values to adapt the script to your
# project structure.
#
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
# Project target.
target=android-8
android.library.reference.1=../../../../cocos2dx/platform/android/java

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">HelloSocial</string>
</resources>

View File

@ -0,0 +1,43 @@
/****************************************************************************
Copyright (c) 2010-2012 cocos2d-x.org
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
package org.cocos2dx.helloSocial;
import org.cocos2dx.lib.Cocos2dxActivity;
import org.cocos2dx.lib.Cocos2dxGLSurfaceView;
import org.cocos2dx.plugin.PluginWrapper;
import android.os.Bundle;
public class HelloSocial extends Cocos2dxActivity{
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
PluginWrapper.init(this);
PluginWrapper.setGLSurfaceView(Cocos2dxGLSurfaceView.getInstance());
}
static {
System.loadLibrary("game");
}
}

View File

@ -1,7 +1,8 @@
#define plugins array
export ALL_PLUGINS=("flurry" "umeng" \
"alipay" "nd91" \
"admob")
"admob" \
"twitter")
# define the plugin root directory & publish target directory
export TARGET_DIR_NAME="publish"