为应用添加分享到新浪微博
现在很多平台都开放了,并且提供了相应的接口。在过往你浏览论坛或者博客的时候,一个论坛/博客都需要自己的帐号,但是现在你会发现都有一个“用新浪微博登陆”,“用QQ帐号登录”等的字样。这样你经过授权以后就可以用新浪或这腾讯的帐号登录到论坛或者博客了,这确实是挺方便的事情,可以直接为你的社区带来用户流量。
最近开发的应用有涉及到分享的功能,android系统有内置的分享功能,但是内置的分享只要你有安装该应用的时候才会被显示在列表中,下面的是android系统内置的分享:如图:
在图上的分享选项中,你有看到“新浪微博”,这个是我自己添加的。意思就是说:如果你有安装“新浪微博”移动端,就用系统自己的分享;如果没有安装该应用则需自行添加分享到“新浪微博”的功能。我们先看看这个列表是怎么加载出来的:
Intent intent = new Intent(Intent.ACTION_SEND); intent.setType("text/plain"); ShareAdapter mAdapter = new ShareAdapter(mContext, intent); //对话框的适配器 public class ShareAdapter extends BaseAdapter { private final static String PACKAGENAME = "com.sina.weibo"; private Context mContext; private PackageManager mPackageManager; private Intent mIntent; private LayoutInflater mInflater; private List<ResolveInfo> mList; private List<DisplayResolveInfo> mDisplayResolveInfoList; public ShareAdapter(Context context, Intent intent) { mContext = context; mPackageManager = mContext.getPackageManager(); mIntent = new Intent(intent); mInflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); mList = mContext.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); // 排序 ResolveInfo.DisplayNameComparator comparator = new ResolveInfo.DisplayNameComparator( mPackageManager); Collections.sort(mList, comparator); mDisplayResolveInfoList = new ArrayList<DisplayResolveInfo>(); if (mList == null || mList.isEmpty()) { mList = new ArrayList<ResolveInfo>(); } final int N = mList.size(); for (int i = 0; i < N; i++) { ResolveInfo ri = mList.get(i); CharSequence label = ri.loadLabel(mPackageManager); DisplayResolveInfo d = new DisplayResolveInfo(ri, null, null, label, null); mDisplayResolveInfoList.add(d); } //考虑是否已安装新浪微博,如果没有则自行添加 if(!isInstallApplication(mContext, PACKAGENAME)){ Intent i = new Intent(mContext, ShareActivity.class); Drawable d = mContext.getResources().getDrawable(R.drawable.sina); CharSequence label = mContext.getString(R.string.about_sina_weibo); DisplayResolveInfo dr = new DisplayResolveInfo(null, i, null, label, d); mDisplayResolveInfoList.add(0, dr); } } @Override public int getCount() { return mDisplayResolveInfoList.size(); } @Override public Object getItem(int position) { return mDisplayResolveInfoList.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { View item; if(convertView == null) { item = mInflater.inflate(R.layout.share_item, null); } else { item = convertView; } DisplayResolveInfo info = mDisplayResolveInfoList.get(position); ImageView i = (ImageView) item.findViewById(R.id.share_item_icon); if(info.mDrawable == null){ i.setImageDrawable(info.mResoleInfo.loadIcon(mPackageManager)); }else{ i.setImageDrawable(info.mDrawable); } TextView t = (TextView) item.findViewById(R.id.share_item_text); t.setText(info.mLabel); return item; } public ResolveInfo getResolveInfo(int index){ if(mDisplayResolveInfoList == null){ return null; } DisplayResolveInfo d = mDisplayResolveInfoList.get(index); if(d.mResoleInfo == null){ return null; } return d.mResoleInfo; } //返回跳转intent public Intent getIntentForPosition(int index) { if(mDisplayResolveInfoList == null){ return null; } DisplayResolveInfo d = mDisplayResolveInfoList.get(index); Intent i = new Intent(d.mIntent == null ? mIntent : d.mIntent); i.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT | Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP); if(d.mResoleInfo != null){ ActivityInfo a = d.mResoleInfo.activityInfo; i.setComponent(new ComponentName(a.applicationInfo.packageName, a.name)); } return i; } //检查是否安装该app boolean isInstallApplication(Context context, String packageName){ try { mPackageManager .getApplicationInfo(packageName, PackageManager.GET_UNINSTALLED_PACKAGES); return true; } catch (NameNotFoundException e) { return false; } } /** * 打包数据 vo * @author Administrator */ class DisplayResolveInfo { private Intent mIntent; private ResolveInfo mResoleInfo; private CharSequence mLabel; private Drawable mDrawable; DisplayResolveInfo(ResolveInfo resolveInfo, Intent intent, CharSequence info, CharSequence label, Drawable d) { this.mIntent = intent; this.mResoleInfo = resolveInfo; this.mLabel = label; this.mDrawable = d; } } }
以上就加载弹出框的数据适配器,如果系统有安装则直接读取系统的分享,没有则添加。当你点击分享微博的时候,就需要一列的验证和授权了,这边采用的机制是先获取requestToken,然后通过requestToken获取AccessToken,然后才可以分享分享微博,开始的时候自己也是从新浪官方的现在的sdk不知道是1.0还是2.0,但是始终都不能发送微博,诡异的是用官方的sdk可以认证完成,并能够获取微博内容,但是死活发不了微博,郁闷好几天!但是看到它的官方论坛里面有那么多的受害者,我表示沉默,一个诺大的公司提供一个接口居然成这样。现在自己用的这个sdk版本里面的Weibo.java有很多其他的方法,如获取用户信息,收藏微博等,大家可以自己看看。
接下来是在你点击“分享到微博”的时候进行认证用户了,说先说明一下这边的认证是读取新浪提供的页面,显示的界面如第二章图片,下面是部分代码:
Weibo weibo = new Weibo(); RequestToken requestToken = weibo.getOAuthRequestToken("yunmai://ShareActivity");<span style="color:#e53333;">//与配置中对应</span> Log.i(TAG, "token:" + requestToken.getToken() + ",tokenSecret:" + requestToken.getTokenSecret()); OAuthConstant.getInstance().setRequestToken(requestToken); Uri uri = Uri.parse(requestToken.getAuthenticationURL() + "&display=mobile"); url = uri.toString();
上面的地址url就是你请求新浪提供的登录界面的地址了,这边会涉及到webview的使用,在android里面webview其实就是一个小型浏览器,功能很强大,强大到可以执行脚本。有了地址可以通过webview.loadurl(url)请求登录界面。也有很多网友可能会想自己设计一个登录界面,但是新浪官方有说明通过getXauthAccessToken方式认证是可以自行设计登录界面的,其他认证方式是不能够自行设计的。在你点击“授权”按钮是需要跳转到我们自己的activity这里的配置是需要在androidmanifest.xml中配置,比如我这边跳转的是shareactivity.java
<activity android:name="cn.yunmai.cclauncher.ShareActivity" android:screenOrientation="portrait" > <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:host="ShareActivity" android:scheme="yunmai" /> </intent-filter> </activity>
需要注意的是<data>标签里面的内容需要和你显示授权窗口的中weibo.getOAuthRequestToken("yunmai://ShareActivity")相对应。你授权完成之后就会跳转到你定义的activity,授权完成之后就发微博了跳转之后的activity就比较清楚明白了吧,简单点就可以放一个发送按钮,一个editText就可以了。在你点击发送按钮的时候,你要获取你刚才授权成功的RequestToken然后再获取accessToken最后发送微博,需要注意的是RequestToken只需获取一次,然后保存你的accessToekn这个才你每次都需要使用的口令,这里就可以优化一下体验了。点击发送按钮的操作是:
Uri uri = this.getIntent().getData(); RequestToken requestToken = OAuthConstant.getInstance().getRequestToken(); AccessToken accessToken = requestToken.getAccessToken(uri.getQueryParameter("oauth_verifier")); saveAccessToken(accessToken);//保存accessToken Log.i(TAG, "oauth_verifier:" + uri.getQueryParameter("oauth_verifier") + ",Token" + accessToken.getToken() + ",TokenSecret:" + accessToken.getTokenSecret()); OAuthConstant.getInstance().setAccessToken(accessToken);
这边所执行的操作是获取授权的之后的accessToken,然后就发送微博:
Weibo weibo = OAuthConstant.getInstance().getWeibo();
weibo.setToken(OAuthConstant.getInstance().getToken(), OAuthConstant.getInstance().getTokenSecret());
Status s = weibo.updateStatus(mEdit.getText().toString());
status返回了一些详细的信息,有发送时间,用户ID等。这就样就完成了分享的功能了。
最后分享一些关于新浪分享的地址:
新浪官方论坛(建议不要寄予太大希望,会完整的回答你的问题):
新浪官方接口以及错误说明:
http://open.weibo.com/development
自己使用的sdk代码和jar包:
http://www.oschina.net/code/snippet_127095_9003
sdk下载完成后第一件事情就是把jar加载到项目,接着就是把weibo中的两个属性CONSUMER_KEY/CONSUMER_SECRET分别换成你自己申请appkey和secret