首页 >Unity3D频道 >【Unity3D研究院之游戏开发】 > Unity3D研究院之在Android中调用新浪微博接口(三十七)
2012
09-21

Unity3D研究院之在Android中调用新浪微博接口(三十七)

         最近工作比较忙 加上感觉自己好像有点上了年纪 整个人感觉非常的疲惫啊, 希望国庆期间可以好好休息一下,调养一下自己。这两天研究了一下如何在Unity中调用新浪微博接口, 上一篇已经IOS平台分享新浪微博,那么本篇文章将写在结合Unity 在 Android平台分享新浪微博。 使用起来我还是觉得IOS平台的接口比较好用,开始基本傻瓜化,可Android平台的接口新手的话估计导入后都无法运行。借此,雨松MOMO希望新浪微博尽快让Android平台下的接口也能好用,废话就不多说了,我们进入正题。

如下图所示,这是MOMO在Android手机中Unity3D下调用新浪微博分享接口。

Unity3D研究院之在Android中调用新浪微博接口(三十七) - 雨松MOMO程序研究院 - 1

 

在继续学习之前请朋友确认你所需要的微薄密钥是否准备完毕。

1.没有密钥的朋友

请在这里注册一个移动应用,http://open.weibo.com/ 。注册成功后在应用信息-》基本信息中即可获得APP KEY 和 APP SECRET,没有这两个KEY你是无法发送微薄的。 仅仅这些还是不够,因为是刚刚注册的新密钥所以是不能被公众所使用的,你应当继续在 应用信息-> 测试帐号 中添加测试账号,只有添加过的测试帐号才能使用新注册的密钥发送微薄。

2.有密钥的朋友

可以直接使用你的密钥来进行开发。

 

接着我们下载新浪微博Andoid下API接口, 下载地址:http://code.google.com/p/android-weibo-sdk/downloads/list     我个人在选择API的时候习惯选择最新的版本,页面中最上面的下载地址就是最新的API

解压后使用Eclipse将整个工程引入,一定要从解压后的顶层的文件夹将下面的两个工程同时的引入Eclipse,不然你会出现错误 “@style/ContentOverlay” 无法找到。这样的话就会将两个工程都引入至elipse,com_weibo_android 是API包, com_weibo_android_exampe 就是例子程序,直接运行它即可。

然后我们需要在Unity3D中制作Android的插件来调用新浪微博接口,如果你现在对Android的插件还是不是很了解,请阅读Unity3D研究院之打开Activity与调用JAVA代码传递参数(十八)文章。

开始MOMO使用com_weibo_android_exampe 来制作Android插件的时候发现最终Unity导出项目的时候无法运行,并且在手机中也无法找到刚刚编译的项目。非常奇怪,后来我就重新把API的代码整理了一遍,问题就解决了。

SinaMessageActivity.java  它是我们写的Activity插件, 当Unity 中准备好 文字与图片数据的时候调用它即可发送信息。

/*
 * Copyright 2011 Sina.
 *
 * Licensed under the Apache License and Weibo License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.open.weibo.com
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.yusong.momo;

import java.io.IOException;
import java.net.MalformedURLException;

import com.unity3d.player.UnityPlayerActivity;
import com.yusong.momo.AsyncWeiboRunner.RequestListener;

import android.app.Activity;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.text.TextUtils;
import android.widget.Toast;

public class SinaMessageActivity extends UnityPlayerActivity implements RequestListener {

//public class SinaMessageActivity extends Activity implements RequestListener {
	//这个是你的密钥
	private static final String CONSUMER_KEY = "1626952933";
	private static final String CONSUMER_SECRET = "d92012d3d2ffa5630554723e1825b11c";

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

	}

	//在Unity中调用此方法进行登录、发送微薄
	public void pressed(String name)
	{
		Weibo weibo = Weibo.getInstance();
		weibo.setupConsumerConfig(CONSUMER_KEY, CONSUMER_SECRET);
		weibo.setRedirectUrl("http://xuanyusong.com");

		SharedPreferences settings = getSharedPreferences("MOMO",
				Activity.MODE_PRIVATE);

		//token 和 expires_in 是登录一次成功后服务器返回给你的。
		//因为我们不需要用户每次发送微薄时都登录
		//所以应当记录用户第一次登录时返回的token 和 expires_in
		//发送微博时直接使用之前保存的token和expires_in即可

		String token = settings.getString("token", "");
		String expires_in = settings.getString("expires_in", "");

		//SharedPreferences 中如果有数据就直接发微薄,否则让用户重新登录
		if (!TextUtils.isEmpty(token)
				&& !TextUtils.isEmpty(expires_in)) {
			AccessToken accessToken = new AccessToken(token,
					CONSUMER_SECRET);
			accessToken.setExpiresIn(expires_in);
			weibo.setAccessToken(accessToken);
			accessToken = new AccessToken(weibo.getAccessToken()
					.getToken(), weibo.getAccessToken().getSecret());
			accessToken = new AccessToken(token, CONSUMER_SECRET);

			weibo.setAccessToken(accessToken);

			//这里代码一定要加, 不然即时你保存了之前的 token 和 expires_in也 无法发送微薄
			Utility.setAuthorization(new Oauth2AccessTokenHeader());
			try {
				//发送一条文字信息
				update(weibo, Weibo.getAppKey(), "test1", "",
						"");
			} catch (MalformedURLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (WeiboException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		} else {

			//开始让用户登录
			weibo.authorize(SinaMessageActivity.this,
					new AuthDialogListener());

		}

	}

	public void onResume() {
		super.onResume();
	}

	class AuthDialogListener implements WeiboDialogListener {

		@Override
		public void onComplete(Bundle values) {

			//用户登录成功后直接发送微薄
			String token = values.getString("access_token");
			String expires_in = values.getString("expires_in");

			SharedPreferences settings = getSharedPreferences("MOMO",
					Activity.MODE_PRIVATE);
			SharedPreferences.Editor editor = settings.edit();
			editor.putString("token", token);
			editor.putString("expires_in", expires_in);
			editor.commit();

			AccessToken accessToken = new AccessToken(token, CONSUMER_SECRET);
			accessToken.setExpiresIn(expires_in);
			Weibo weibo = Weibo.getInstance();
			weibo.setAccessToken(accessToken);
			accessToken = new AccessToken(weibo.getAccessToken().getToken(),
					weibo.getAccessToken().getSecret());
			accessToken = new AccessToken(token, CONSUMER_SECRET);

			weibo.setAccessToken(accessToken);
			//这里代码一定要加, 不然即时你保存了之前的 token 和 expires_in也 无法发送微薄
			Utility.setAuthorization(new Oauth2AccessTokenHeader());

				try {
					//在这里发送一条 文字+ 图片的微薄
					//路径比较重要,在Unity中将图片保存在这个路径下
					//在Android插件中直接通过这个路径即可拿到图片对象
					upload(weibo, Weibo.getAppKey(), "/data/data/com.yusong.momo/files/Screenshot.png",
							"Unity3D 中调用新浪微博接口 分享自 @雨松MOMO  ", "", "") ;

				} catch (WeiboException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

		}

		@Override
		public void onError(DialogError e) {
			Toast.makeText(getApplicationContext(),
					"Auth error : " + e.getMessage(), Toast.LENGTH_LONG).show();
		}

		@Override
		public void onCancel() {
			Toast.makeText(getApplicationContext(), "Auth cancel",
					Toast.LENGTH_LONG).show();
		}

		@Override
		public void onWeiboException(WeiboException e) {
			Toast.makeText(getApplicationContext(),
					"Auth exception : " + e.getMessage(), Toast.LENGTH_LONG)
					.show();
		}

	}

	// 发送文字
	private String upload(Weibo weibo, String source, String file,
			String status, String lon, String lat) throws WeiboException {
		WeiboParameters bundle = new WeiboParameters();
		bundle.add("source", source);
		bundle.add("pic", file);
		bundle.add("status", status);
		if (!TextUtils.isEmpty(lon)) {
			bundle.add("lon", lon);
		}
		if (!TextUtils.isEmpty(lat)) {
			bundle.add("lat", lat);
		}
		String rlt = "";
		String url = Weibo.SERVER + "statuses/upload.json";
		AsyncWeiboRunner weiboRunner = new AsyncWeiboRunner(weibo);
		weiboRunner.request(this, url, bundle, Utility.HTTPMETHOD_POST, this);

		return rlt;
	}

	// 发送文字 + 图片
	private String update(Weibo weibo, String source, String status,
			String lon, String lat) throws MalformedURLException, IOException,
			WeiboException {
		WeiboParameters bundle = new WeiboParameters();
		bundle.add("source", source);
		bundle.add("status", status);
		if (!TextUtils.isEmpty(lon)) {
			bundle.add("lon", lon);
		}
		if (!TextUtils.isEmpty(lat)) {
			bundle.add("lat", lat);
		}
		String rlt = "";
		String url = Weibo.SERVER + "statuses/update.json";
		AsyncWeiboRunner weiboRunner = new AsyncWeiboRunner(weibo);
		weiboRunner.request(this, url, bundle, Utility.HTTPMETHOD_POST, this);
		return rlt;
	}

	@Override
	public void onComplete(String response) {
		runOnUiThread(new Runnable() {

			@Override
			public void run() {
				Toast.makeText(SinaMessageActivity.this, "微薄分享成功",
						Toast.LENGTH_LONG).show();
			}
		});

	}

	@Override
	public void onIOException(IOException e) {
		runOnUiThread(new Runnable() {

			@Override
			public void run() {
				Toast.makeText(SinaMessageActivity.this, "微薄分享错误",
						Toast.LENGTH_LONG).show();
			}
		});

	}

	@Override
	public void onError(WeiboException e) {
		runOnUiThread(new Runnable() {
			@Override
			public void run() {
				Toast.makeText(SinaMessageActivity.this, "微薄分享失败",
						Toast.LENGTH_LONG).show();
			}
		});

	}

}

 

当插件准备完毕后,将它导入至Unity3D中,如果不会的朋友请看我之前的文章。Unity3D研究院之打开Activity与调用JAVA代码传递参数(十八)

我们在看看Unity中是如何调用插件中的分享接口的。

Test.cs

using System.Collections;
using System.IO;
using System.Collections.Generic;
using System;

public class Test : MonoBehaviour {

	void Start () 
	{
		//在Unity截取一张图片
                //该图片的路径保存在"/data/data/com.yusong.momo/files/Screenshot.png"
                //在Android插件中根据这个路径即可拿到该图片
		Application.CaptureScreenshot("Screenshot.png");

	}

	void Update () 
	{

	}

	void OnGUI()
	{
		if(GUILayout.Button("sendSinaMessage",GUILayout.Width(200),GUILayout.Height(100)))
		{

			//开始登录新浪微博
			using (AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
            {
                using( AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity"))
                {
                      //在这里直接调用pressed方法进行登录与发送微薄
                      jo.Call("pressed","");
                }
            }

		}

	}
}

 

调用接口后会调用新浪登录界面,继续发送新浪微薄。

Unity3D研究院之在Android中调用新浪微博接口(三十七) - 雨松MOMO程序研究院 - 2

 

 

最后我把文本的Android插件代码 以及 Unity工程放出来, 下载完毕后解压即可看到工程。雨松MOMO希望大家学习愉快。

下载地址 http://vdisk.weibo.com/s/d3xA1

 

2013年3月23日补充

 

在调用新浪微薄Android接口的时候我还出现了一个 Can’t create handler inside thread that has not called Looper.prepare() 错误。

这个错误前段时间一直因为别的事情没有能即时的解决。 这几天MOMO在做Android for QQzone的插件中也遇到了同样的错误。出现这个错误的额原因就是unity调用插件中的方法中又开启了新的线程。

先改动一下上面的unity C#脚本,方法名我就不换了。。。主要说原理。。

 

		if(GUILayout.Button(" Send QQ zone", GUILayout.Height(50)))
		{

                         AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");

			 using (AndroidJavaObject jo = jc.GetStatic("currentActivity"))
  			 {
				jo.Call("LoginAndSend",jo);

  		  	 }

		}

 这段代码的意思就是在unity中把当前的Activity对象传递给Android插件中。在插件中这样来写。

	public void LoginAndSend(final Activity currentActivity) 
	{
		currentActivity.runOnUiThread(new Runnable() {

			@Override
			public void run() {
				//doyourcode

                         });
		}

	}

 

在插件中通过调用UI主线程来执行原先的子线程。。

最后编辑:
作者:雨松MOMO
专注移动互联网,Unity3D游戏开发
捐 赠写博客不易,如果您想请我喝一杯星巴克的话?就进来看吧!

Unity3D研究院之在Android中调用新浪微博接口(三十七)》有 54 条评论

  1. Chorus09说:

    请问大神用最新sdk的oauth时授权页面弹不出来是该如何解决啊。ssohandler是封装的,根本无法控制会使用sso登陆或是oauth,这是该怎么办呢?

  2. YYC说:

    http://pan.baidu.com/s/1hq4Ahm8 雨松哥我我对着这个平台的登陆一直报错, 在Java- ADT 里面运行没错,只要Unity 一调用就报NULL 找不到 求解 求解 已经被折磨了一天了

  3. 苦逼脸说:

    momo大神,为什么我在UnityPlayerActivity里点击登录授权,新浪授权页面弹不出来的

  4. 黄旭烽说:

    为什么老是在授权的时候出现Auth exception :failed to receive access token 呢,求大神指点~~

  5. 发送完成貌似木有callback?现有个需求,unity调用android方法需要传入一个Callback接口对象,以便发送完成后回调。 这个该怎么处理,求大神指点~

留下一个回复

你的email不会被公开。 必填项已用 * 标注。