操作步骤:
1、在share官网注册应用生成AppKey并下载SDK 网址:http://www.shareSDK.cn
2、在QQ空间平台注册应用生成AppId和AppKey 网址:http://connect.qq.com/intro/login/
3、导入SDK包。只实现QQ空间登录分享的话只需要导入ShareSDK-Core.jar(核心包)、ShareSDK-QZone.jar(QQ空间)、cn.sharesdk.onekeyshare.jar(快捷分享)
4、配置:需要配置assets里面的ShareSDKDevInfor.xml和AndroidManifest.xml(后面有示例介绍)
5、添加代码实现登录、获取信息、分享等功能(见下面示例)。
ShareSDKDevInfor.xml:
<?xml version="1.0" encoding="utf-8"?> <DevInfor> <!--说明: 1、表格中的第一项 <ShareSDK AppKey="api20" /> 是必须的,其中的AppKey是你在Share SDK上注册的开发者帐号的AppKey 2、所有集成到你项目的平台都应该为其在表格中填写相对应的开发者信息,以新浪微博为例: <SinaWeibo SortId="此平台在分享列表中的位置,由开发者自行定义,可以是任何整型数字,数值越大越靠后" AppKey="填写你在新浪微博上注册的AppKey" AppSecret="填写你在新浪微博上注册到的AppKey" Id="自定义字段,整形,用于你项目中对此平台的识别符" RedirectUrl="填写你在新浪微博上注册的RedirectUrl" /> 各个平台注册应用信息的地址如下: 新浪微博:http://open.weibo.com 腾讯微博:http://dev.t.qq.com QQ空间:http://connect.qq.com/intro/login/ 网易微博:http://open.t.163.com 搜狐微博:http://open.t.sohu.com 豆瓣:http://developers.douban.com 人人网:http://dev.renren.com 开心网:http://open.kaixin001.com Instapaper:http://www.instapaper.com/main/request_oauth_consumer_token 有道云笔记:http://note.youdao.com/open/developguide.html#app facebook:https://developers.facebook.com twitter:https://dev.twitter.com 搜狐随身看:https://open.sohu.com QQ好友分享:http://mobile.qq.com/api/ 微信:http://open.weixin.qq.com--> <ShareSDK AppKey = "123d2e98bef8"/> <!-- AppKey="104972cdd48" "23a9371d3a8"--> <QZone SortId="1" AppId="100371282" AppKey="aed9b0303e3ed1e27bae87c33761161d" Id="1" RedirectUrl="http://www.shareSDK.cn" /> </DevInfor>
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.home.testqqshare" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.WRITE_APN_SETTINGS" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.home.testqqshare.LoginActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name="com.home.testqqshare.MainActivity" /> <activity android:name="com.home.testqqshare.ShowInfoActivity" /> <!-- share SDK 里面的组件 --> <activity android:name="cn.sharesdk.framework.AuthorizeActivity" android:configChanges="keyboardHidden|orientation" android:screenOrientation="portrait" android:theme="@android:style/Theme.Translucent.NoTitleBar" android:windowSoftInputMode="stateHidden|adjustResize" > </activity> <activity android:name="cn.sharesdk.onekeyshare.ShareAllGird" android:configChanges="keyboardHidden|orientation" android:screenOrientation="portrait" android:theme="@android:style/Theme.Translucent.NoTitleBar" android:windowSoftInputMode="adjustPan|stateHidden" /> <activity android:name="cn.sharesdk.onekeyshare.SharePage" android:configChanges="keyboardHidden|orientation" android:screenOrientation="portrait" android:windowSoftInputMode="stateHidden|adjustResize" /> </application> </manifest>
LoginActivity:
package com.home.testqqshare; import java.util.HashMap; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.os.Handler.Callback; import android.os.Message; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast; import cn.sharesdk.framework.AbstractWeibo; import cn.sharesdk.framework.WeiboActionListener; import cn.sharesdk.tencent.qzone.QZone; public class LoginActivity extends Activity implements OnClickListener, WeiboActionListener, Callback { private Button loginBtn; private Handler handler; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.login); // 初始化ShareSDK AbstractWeibo.initSDK(this); loginBtn = (Button) findViewById(R.id.login_btn_QQ); loginBtn.setOnClickListener(this); handler = new Handler(this); } @Override public void onClick(View v) { if (v == loginBtn) { AbstractWeibo weibo = AbstractWeibo.getWeibo(this, QZone.NAME); weibo.setWeiboActionListener(this); weibo.showUser(null); } } @Override public void onComplete(AbstractWeibo weibo, int arg1, HashMap<String, Object> arg2) { Message msg = new Message(); msg.arg1 = 1; msg.obj = weibo; handler.sendMessage(msg); } @Override public void onError(AbstractWeibo weibo, int arg1, Throwable t) { t.printStackTrace(); Message msg = new Message(); msg.arg1 = 2; msg.obj = weibo; handler.sendMessage(msg); } @Override public void onCancel(AbstractWeibo weibo, int arg1) { Message msg = new Message(); msg.arg1 = 3; msg.obj = weibo; handler.sendMessage(msg); } @Override protected void onDestroy() { // 结束ShareSDK的统计功能并释放资源 AbstractWeibo.stopSDK(this); super.onDestroy(); } /** * 处理从授权页面返回的结果:异常则给出提示,正常则跳转页面 * */ @Override public boolean handleMessage(Message msg) { AbstractWeibo weibo = (AbstractWeibo) msg.obj; switch (msg.arg1) { case 1: { // 成功 Toast.makeText(this, weibo.getName() + "授权成功", Toast.LENGTH_SHORT) .show(); } break; case 2: { // 失败 Toast.makeText(this, weibo.getName() + "授权失败", Toast.LENGTH_SHORT) .show(); return false; } case 3: { // 取消 Toast.makeText(this, weibo.getName() + "授权取消", Toast.LENGTH_SHORT) .show(); return false; } } Intent intent = new Intent(LoginActivity.this, MainActivity.class); startActivity(intent); return false; } }
MainActivity:
package com.home.testqqshare; import java.io.File; import java.io.FileOutputStream; import java.util.HashMap; import android.app.Activity; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.Bitmap.CompressFormat; import android.graphics.BitmapFactory; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.Handler.Callback; import android.os.Message; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast; import cn.sharesdk.framework.AbstractWeibo; import cn.sharesdk.framework.WeiboActionListener; import cn.sharesdk.onekeyshare.ShareAllGird; import cn.sharesdk.tencent.qzone.QZone; public class MainActivity extends Activity implements OnClickListener, WeiboActionListener, Callback { private Button getInfoBtn; private Button noUIShareBtn; private Button hasUIShareBtn; private Button logoutBtn; private Handler handler; // 定义图片存放的地址 public static String TEST_IMAGE; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); AbstractWeibo.initSDK(this); initWidget(); initImage(); } /** * 初始化UI相关组件 */ private void initWidget() { getInfoBtn = (Button) findViewById(R.id.main_get_userinfo); noUIShareBtn = (Button) findViewById(R.id.main_share_noUI); hasUIShareBtn = (Button) findViewById(R.id.main_share_hasUI); logoutBtn = (Button) findViewById(R.id.main_btn_logout); getInfoBtn.setOnClickListener(this); noUIShareBtn.setOnClickListener(this); hasUIShareBtn.setOnClickListener(this); logoutBtn.setOnClickListener(this); handler = new Handler(this); } @Override public void onClick(View v) { if (v == getInfoBtn) { AbstractWeibo weibo = AbstractWeibo.getWeibo(this, QZone.NAME); weibo.setWeiboActionListener(this); weibo.showUser(null); } else if (v == noUIShareBtn) { showGrid(true); } else if (v == hasUIShareBtn) { showGrid(false); } else if (v == logoutBtn) {// 注销 AbstractWeibo weibo = AbstractWeibo.getWeibo(this, QZone.NAME); if (weibo.isValid()) { weibo.removeAccount(); finish(); } } } @Override public void onCancel(AbstractWeibo weibo, int arg1) { Message msg = new Message(); msg.arg1 = 3; msg.obj = weibo; handler.sendMessage(msg); } @Override public void onComplete(AbstractWeibo weibo, int arg1, HashMap<String, Object> res) { Message msg = new Message(); msg.arg1 = 1; JsonUtils ju = new JsonUtils(); String json = ju.fromHashMap(res); msg.obj = ju.format(json); handler.sendMessage(msg); } @Override public void onError(AbstractWeibo weibo, int arg1, Throwable arg2) { Message msg = new Message(); msg.arg1 = 2; msg.obj = weibo; handler.sendMessage(msg); } /** 处理操作结果 */ public boolean handleMessage(Message msg) { switch (msg.arg1) { case 1: { // 成功 Intent intent = new Intent(MainActivity.this, ShowInfoActivity.class); intent.putExtra("data", String.valueOf(msg.obj)); startActivity(intent); } break; case 2: {// 失败 AbstractWeibo weibo = (AbstractWeibo) msg.obj; Toast.makeText(this, weibo.getName() + "授权失败", Toast.LENGTH_SHORT) .show(); } break; case 3: {// 取消 AbstractWeibo weibo = (AbstractWeibo) msg.obj; Toast.makeText(this, weibo.getName() + "授权取消", Toast.LENGTH_SHORT) .show(); } break; } return false; } /** * 使用快捷分享完成图文分享 * * @param silent * 是否直接分享 */ private void showGrid(boolean silent) { Intent i = new Intent(this, ShareAllGird.class); // 分享时Notification的图标 i.putExtra("notif_icon", R.drawable.ic_launcher); // 分享时Notification的标题 i.putExtra("notif_title", this.getString(R.string.app_name)); // title标题,在印象笔记、邮箱、信息、微信(包括好友和朋友圈)、人人网和QQ空间使用,否则可以不提供 i.putExtra("title", this.getString(R.string.share)); // titleUrl是标题的网络链接,仅在人人网和QQ空间使用,否则可以不提供 i.putExtra("titleUrl", "http://sharesdk.cn"); // text是分享文本,所有平台都需要这个字段 i.putExtra("text", this.getString(R.string.share_content)); // imagePath是本地的图片路径,所有平台都支持这个字段,不提供,则表示不分享图片 i.putExtra("imagePath", MainActivity.TEST_IMAGE); // url仅在微信(包括好友和朋友圈)中使用,否则可以不提供 i.putExtra("url", "http://sharesdk.cn"); // thumbPath是缩略图的本地路径,仅在微信(包括好友和朋友圈)中使用,否则可以不提供 i.putExtra("thumbPath", MainActivity.TEST_IMAGE); // appPath是待分享应用程序的本地路劲,仅在微信(包括好友和朋友圈)中使用,否则可以不提供 i.putExtra("appPath", MainActivity.TEST_IMAGE); // comment是我对这条分享的评论,仅在人人网和QQ空间使用,否则可以不提供 i.putExtra("comment", this.getString(R.string.share)); // site是分享此内容的网站名称,仅在QQ空间使用,否则可以不提供 i.putExtra("site", this.getString(R.string.app_name)); // siteUrl是分享此内容的网站地址,仅在QQ空间使用,否则可以不提供 i.putExtra("siteUrl", "http://sharesdk.cn"); // 是否直接分享 i.putExtra("silent", silent); this.startActivity(i); } /** * 初始化分享的本地图片 */ private void initImage() { try {// 判断SD卡中是否存在此文件夹 if (Environment.MEDIA_MOUNTED.equals(Environment .getExternalStorageState()) && Environment.getExternalStorageDirectory().exists()) { File baseFile = new File( Environment.getExternalStorageDirectory(), "share"); if (!baseFile.exists()) { baseFile.mkdir(); } TEST_IMAGE = baseFile.getAbsolutePath() + "/picture.png"; } else { TEST_IMAGE = getApplication().getFilesDir().getAbsolutePath() + "/picture.png"; } File file = new File(TEST_IMAGE); // 判断图片是否存此文件夹中 if (!file.exists()) { file.createNewFile(); Bitmap pic = BitmapFactory.decodeResource(getResources(), R.drawable.picture); FileOutputStream fos = new FileOutputStream(file); pic.compress(CompressFormat.JPEG, 100, fos); fos.flush(); fos.close(); } } catch (Throwable t) { t.printStackTrace(); TEST_IMAGE = null; } } }
显示信息ShowInfoActivity:
package com.home.testqqshare; import android.app.Activity; import android.os.Bundle; import android.widget.TextView; public class ShowInfoActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.show_info); TextView show = (TextView) findViewById(R.id.show_info_tv); show.setText(getIntent().getStringExtra("data")); } }
JsonUtils工具类:
package com.home.testqqshare; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.Map.Entry; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; public class JsonUtils { /** * 将指定的json数据转成 HashMap<String, Object>对象 */ public HashMap<String, Object> fromJson(String jsonStr) { try { if (jsonStr.startsWith("[") && jsonStr.endsWith("]")) { jsonStr = "{\"fakelist\":" + jsonStr + "}"; } JSONObject json = new JSONObject(jsonStr); return fromJson(json); } catch (Throwable t) { t.printStackTrace(); } return new HashMap<String, Object>(); } private HashMap<String, Object> fromJson(JSONObject json) throws JSONException { HashMap<String, Object> map = new HashMap<String, Object>(); @SuppressWarnings("unchecked") Iterator<String> iKey = json.keys(); while (iKey.hasNext()) { String key = iKey.next(); Object value = json.opt(key); if (JSONObject.NULL.equals(value)) { value = null; } if (value != null) { if (value instanceof JSONObject) { value = fromJson((JSONObject) value); } else if (value instanceof JSONArray) { value = fromJson((JSONArray) value); } map.put(key, value); } } return map; } private ArrayList<Object> fromJson(JSONArray array) throws JSONException { ArrayList<Object> list = new ArrayList<Object>(); for (int i = 0, size = array.length(); i < size; i++) { Object value = array.opt(i); if (value instanceof JSONObject) { value = fromJson((JSONObject) value); } else if (value instanceof JSONArray) { value = fromJson((JSONArray) value); } list.add(value); } return list; } /** * 将指定的HashMap<String, Object>对象转成json数据 */ public String fromHashMap(HashMap<String, Object> map) { try { return getJSONObject(map).toString(); } catch (Throwable t) { t.printStackTrace(); } return ""; } @SuppressWarnings("unchecked") private JSONObject getJSONObject(HashMap<String, Object> map) throws JSONException { JSONObject json = new JSONObject(); for (Entry<String, Object> entry : map.entrySet()) { Object value = entry.getValue(); if (value instanceof HashMap<?, ?>) { value = getJSONObject((HashMap<String, Object>) value); } else if (value instanceof ArrayList<?>) { value = getJSONArray((ArrayList<Object>) value); } json.put(entry.getKey(), value); } return json; } @SuppressWarnings("unchecked") private JSONArray getJSONArray(ArrayList<Object> list) throws JSONException { JSONArray array = new JSONArray(); for (Object value : list) { if (value instanceof HashMap<?, ?>) { value = getJSONObject((HashMap<String, Object>) value); } else if (value instanceof ArrayList<?>) { value = getJSONArray((ArrayList<Object>) value); } array.put(value); } return array; } /** * 格式化一个json串 */ public String format(String jsonStr) { try { return format("", fromJson(jsonStr)); } catch (Throwable t) { t.printStackTrace(); } return ""; } @SuppressWarnings("unchecked") private String format(String sepStr, HashMap<String, Object> map) { StringBuffer sb = new StringBuffer(); sb.append("{\n"); String mySepStr = sepStr + "\t"; int i = 0; for (Entry<String, Object> entry : map.entrySet()) { if (i > 0) { sb.append(",\n"); } sb.append(mySepStr).append('\"').append(entry.getKey()) .append("\":"); Object value = entry.getValue(); if (value instanceof HashMap<?, ?>) { sb.append(format(mySepStr, (HashMap<String, Object>) value)); } else if (value instanceof ArrayList<?>) { sb.append(format(mySepStr, (ArrayList<Object>) value)); } else if (value instanceof String) { sb.append('\"').append(value).append('\"'); } else { sb.append(value); } i++; } sb.append('\n').append(sepStr).append('}'); return sb.toString(); } @SuppressWarnings("unchecked") private String format(String sepStr, ArrayList<Object> list) { StringBuffer sb = new StringBuffer(); sb.append("[\n"); String mySepStr = sepStr + "\t"; int i = 0; for (Object value : list) { if (i > 0) { sb.append(",\n"); } sb.append(mySepStr); if (value instanceof HashMap<?, ?>) { sb.append(format(mySepStr, (HashMap<String, Object>) value)); } else if (value instanceof ArrayList<?>) { sb.append(format(mySepStr, (ArrayList<Object>) value)); } else if (value instanceof String) { sb.append('\"').append(value).append('\"'); } else { sb.append(value); } i++; } sb.append('\n').append(sepStr).append(']'); return sb.toString(); } }
登录界面布局文件login.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:gravity="center_horizontal"> <Button android:id="@+id/login_btn_QQ" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="QQ授权登录" /> </LinearLayout>
主布局文件main.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <Button android:id="@+id/main_get_userinfo" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="获取用户信息" /> <Button android:id="@+id/main_share_noUI" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="分享(无界面)" /> <Button android:id="@+id/main_share_hasUI" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="分享(有界面)" /> <Button android:id="@+id/main_btn_logout" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="注销登录" /> </LinearLayout>
显示信息的布局show_info.xml:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <ScrollView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" > <TextView android:id="@+id/show_info_tv" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginRight="10dp" android:autoLink="all" android:textColor="#ff000000" /> </ScrollView> </RelativeLayout>
strings:
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">TestQQShare</string> <string name="action_settings">Settings</string> <string name="hello_world">Hello world!</string> <string name="share_content">测试使用shareSDK进行分享,感觉还不错,使用方便,功能强大!</string> <string name="share">分享</string> </resources>
DEMO下载地址:http://download.csdn.net/detail/u010142437/6885943