最近研究了一下Android下 Unity分享 for QQ空间,作法类似以前我在博客中写过分享新浪微博的方法,也就是自己写插件。测试用的手机Google Nexus ,Unity版本4.1,如下图所示,这是我发布成功后在QQ空间的截图。
写插件的方式我就不再说了,如果不懂的朋友看我之前的博客吧,写的很清楚。
QQ空间分享属于腾讯开放平台。然而腾讯开放平台的东西也比较多,移动平台包括:空间分享、说说分享、微薄分享。这一篇就说空间分享,如果空间分享搞定后可以按照同样的方式实现微薄分享。
先下载腾讯开放平台的API。
API我下载后里面有一个DEMO。我在MAC OS系统下Eclipse尽然不能运行,提示错误。后来我简单改了一下才可以运行,好蛋疼啊。
废话就不多说了,先来在Elipse下Android的插件。下段代码是Eclipse中的Android代码。
package com.example.qqzone;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Date;
import org.apache.http.conn.ConnectTimeoutException;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.Menu;
import android.widget.Toast;
import com.tencent.open.HttpStatusException;
import com.tencent.open.NetworkUnavailableException;
import com.tencent.tauth.Constants;
import com.tencent.tauth.IRequestListener;
import com.tencent.tauth.IUiListener;
import com.tencent.tauth.Tencent;
import com.tencent.tauth.UiError;
import com.unity3d.player.UnityPlayerActivity;
public class MainActivity extends UnityPlayerActivity {
// public class MainActivity extends Activity {
public Tencent mTencent;
public SharedPreferences sharedPrefrences;
public Editor editor;
public Context context;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
sharedPrefrences = this.getSharedPreferences("info",
MODE_WORLD_READABLE);
editor = sharedPrefrences.edit();
context = this.getApplicationContext();
}
//这个方法是在Unity中调用的。参数是当前的Activity。
public void LoginAndSend(final Activity currentActivity)
{
//一定要在UI线程中来执行腾讯API中的方法。
//API中的方法应该是开启了一个线程,一切由Unity调用的方法里面只要开启线程就会出现
//Can’t create handler inside thread that has not called Looper.prepare() 错误
//写在runOnUiThread 的线程中可以避免这个错误没,以前在处理Unity发送新浪微博的时候也遇到这样的错误。
//同样可以按照这种方法来解决。
currentActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
//得到Tencent实例, 腾讯API的方法都写在这里类中。
//"222222"是APPID 这个是腾讯DEMO里带的, 你最好自己申请一个。
mTencent = Tencent.createInstance("222222",context
);
//这里是处理Token的, 避免用户重复授权应用,每次登录成功后会获取一个新Token
//得到新Token后一定要保存在本地中。用上次保存的token就可以避免再次登录。
//Token的过期时间是3个月,3个月后需要重新登录。
//登录后返回值
String openid = sharedPrefrences.getString("openid", null);
//登录后返回值
String access_token = sharedPrefrences.getString("access_token", null);
//过期时间
long expires_in = sharedPrefrences.getLong("expires_in", 0);
if (openid != null && access_token != null && expires_in != 0)
{
//如果以前保存过Token 这里直接使用上次保存的openid 和access_token
//这里最好在判断一下token过期时间
mTencent.setOpenId(openid);
mTencent.setAccessToken(access_token, expires_in + "");
//发送说说
SendMessage();
} else
{
//如果之前没有保存过token信息,在这里让用户先登录
if (!mTencent.isSessionValid()) {
IUiListener listener = new IUiListener() {
@Override
public void onError(UiError arg0) {
Toast.makeText(getApplicationContext(), "登录错误",
Toast.LENGTH_SHORT).show();
}
@Override
public void onComplete(JSONObject arg0) {
Log.v("登录成功", "登录成功");
//发送信息
SendMessage();
//登录成功后把token信息保存在本地中
editor.putString("openid", mTencent.getOpenId());
editor.putString("access_token",
mTencent.getAccessToken());
//777600 表示token的过期时间。 它是以秒为单位的, 24(小时)*60(分钟)*60(秒) *90(天) = 777600(秒)
//每次登录后需要获取现在时间 然后减去以前保存的
//如果过期了 让用户重新登录
editor.putLong("expires_in", 7776000);
editor.commit();
}
@Override
public void onCancel() {
Log.v("登录取消", "登录取消");
}
};
mTencent.login(currentActivity, "all", listener);
} else {
mTencent.logout(context);
}
}
}
});
}
private void SendMessage() {
//下面这段代码基本上是API中的,我简单的改了一下。
if (mTencent.isSessionValid() && mTencent.getOpenId() != null) {
Bundle parmas = new Bundle();
parmas.putString("title", "雨松MOMO程序研究院");// 必须。feeds的标题,最长36个中文字,超出部分会被截断。
parmas.putString(
"url",
"http://www.xuanyusong.com" + "#"
+ System.currentTimeMillis());// 必须。分享所在网页资源的链接,点击后跳转至第三方网页,
// 请以http://开头。
parmas.putString("comment", ("欢迎光临雨松MOMO程序研究院。" + new Date()));// 用户评论内容,也叫发表分享时的分享理由。禁止使用系统生产的语句进行代替。最长40个中文字,超出部分会被截断。
parmas.putString("summary", "在Unity3D中调用QQ空间分享接口,哇咔咔哇咔咔");// 所分享的网页资源的摘要内容,或者是网页的概要描述。
// 最长80个中文字,超出部分会被截断。
parmas.putString("images",
"http://www.xuanyusong.com/wp-content/uploads/2012/04/0.jpg");// 所分享的网页资源的代表性图片链接",请以http://开头,长度限制255字符。多张图片以竖线(|)分隔,目前只有第一张图片有效,图片规格100*100为佳。
parmas.putString("type", "4");// 分享内容的类型。
mTencent.requestAsync(Constants.GRAPH_ADD_SHARE, parmas,
Constants.HTTP_POST, new BaseApiListener(), null);
}
}
//这个方法一定要加, 不然有错误、、
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
mTencent.onActivityResult(requestCode, resultCode, data);
}
private class BaseApiListener implements IRequestListener {
@Override
public void onComplete(final JSONObject response, Object state) {
doComplete(response, state);
}
protected void doComplete(JSONObject response, Object state) {
Log.v("发送成功", "发送成功");
}
@Override
public void onIOException(final IOException e, Object state) {
Log.v("发表错误", "onIOException");
}
@Override
public void onMalformedURLException(final MalformedURLException e,
Object state) {
Log.v("发表错误", "onMalformedURLException");
}
@Override
public void onJSONException(final JSONException e, Object state) {
Log.v("发表错误", "onJSONException");
}
@Override
public void onConnectTimeoutException(ConnectTimeoutException arg0,
Object arg1) {
Log.v("发表错误", "onConnectTimeoutException");
}
@Override
public void onSocketTimeoutException(SocketTimeoutException arg0,
Object arg1) {
Log.v("发表错误", "onSocketTimeoutException");
}
@Override
public void onUnknowException(Exception arg0, Object arg1) {
Log.v("发表错误", "onUnknowException");
}
@Override
public void onHttpStatusException(HttpStatusException arg0, Object arg1) {
Log.v("发表错误", "onHttpStatusException");
}
@Override
public void onNetworkUnavailableException(
NetworkUnavailableException arg0, Object arg1) {
Log.v("发表错误", "onNetworkUnavailableException");
}
}
}
如果你不需要在U3d中分享说说?把上段代码简单的改一改吧。把登录放在Creat()方法中吧,会安卓的都知道嘿嘿。然后在U3D中,绑定在任意对象中, 把Activity传递给Android插件中。using UnityEngine; using System.Collections; public class NewBehaviourScript : MonoBehaviour { void OnGUI() { if(GUILayout.Button(" Send QQ zone", GUILayout.Height(50))) { AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); using (AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity")) { jo.Call("LoginAndSend",jo); } } } }
下面是Andorid插件的路径,记住把open_Sdk放进去,这个是腾讯提供的第三方包。运行后点击按钮就可以登录与分享说说。然后在Android手机上编译运行吧。最后我在说说我使用QQ空间的感受。 空间分享包括2部分 分享链接 和分享说说,仔细查了一下才发现这两个东西差别挺大的。 文档上说这两个分享接口会被合并,最重要的是暂时不能分享本地图片、如果想分享本地图片有一个办法就是先调用上传图片的接口,把本地图片上传至QQ相册中,然后拿到URL后分享。总体来说希望企鹅的文档以后能写的在清楚一点,我是“连蒙带猜” 哎~本文的源码下载,包括Android工程和U3D工程。