测试
diff --git a/platforms/android/android.json b/platforms/android/android.json
index 8d319b4..105b5f2 100644
--- a/platforms/android/android.json
+++ b/platforms/android/android.json
@@ -67,6 +67,46 @@
             {
               "xml": "<feature name=\"screenshotName\"><param name=\"android-package\" value=\"com.coffice.ScreenshotBlocker\" /><param name=\"onload\" value=\"true\" /></feature>",
               "count": 1
+            },
+            {
+              "xml": "<feature name=\"QQSDK\"><param name=\"android-package\" value=\"me.vanpan.qqsdk.QQSDKPlugin\" /></feature>",
+              "count": 1
+            },
+            {
+              "xml": "<access origin=\"https://openmobile.qq.com/*\" />",
+              "count": 1
+            },
+            {
+              "xml": "<access origin=\"http://qzonestyle.gtimg.cn/*\" />",
+              "count": 1
+            },
+            {
+              "xml": "<access origin=\"http://pub.idqqimg.com/*\" />",
+              "count": 1
+            },
+            {
+              "xml": "<access origin=\"http://qzs.qq.com/*\" />",
+              "count": 1
+            },
+            {
+              "xml": "<access origin=\"http://m.qzone.com/*\" />",
+              "count": 1
+            },
+            {
+              "xml": "<access origin=\"http://*.ptlogin2.qq.com/*\" />",
+              "count": 1
+            },
+            {
+              "xml": "<access origin=\"http://*.qq.com/*\" />",
+              "count": 1
+            },
+            {
+              "xml": "<access origin=\"http://q2.qlogo.cn/*\" />",
+              "count": 1
+            },
+            {
+              "xml": "<preference name=\"QQ_APP_ID\" value=\"101885581\" />",
+              "count": 1
             }
           ]
         }
@@ -266,6 +306,34 @@
             }
           ]
         }
+      },
+      "app/src/main/AndroidManifest.xml": {
+        "parents": {
+          "/manifest": [
+            {
+              "xml": "<uses-permission android:name=\"android.permission.INTERNET\" />",
+              "count": 1
+            },
+            {
+              "xml": "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\" />",
+              "count": 1
+            },
+            {
+              "xml": "<uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\" />",
+              "count": 1
+            }
+          ],
+          "/manifest/application": [
+            {
+              "xml": "<activity android:launchMode=\"singleTask\" android:name=\"com.tencent.tauth.AuthActivity\" android:noHistory=\"true\"><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:scheme=\"tencent101885581\" /></intent-filter></activity>",
+              "count": 1
+            },
+            {
+              "xml": "<activity android:configChanges=\"orientation|keyboardHidden\" android:name=\"com.tencent.connect.common.AssistActivity\" android:screenOrientation=\"portrait\" android:theme=\"@android:style/Theme.Translucent.NoTitleBar\"></activity>",
+              "count": 1
+            }
+          ]
+        }
       }
     }
   },
@@ -329,6 +397,10 @@
     },
     "cordova-plugin-prevent-screenshot-coffice": {
       "PACKAGE_NAME": "com.dalipolice.app"
+    },
+    "cordova-plugin-qqsdk": {
+      "QQ_APP_ID": "101885581",
+      "PACKAGE_NAME": "com.dalipolice.app"
     }
   },
   "dependent_plugins": {},
@@ -684,6 +756,14 @@
       "clobbers": [
         "window.plugins.preventscreenshot"
       ]
+    },
+    {
+      "id": "cordova-plugin-qqsdk.QQSDK",
+      "file": "plugins/cordova-plugin-qqsdk/www/qq.js",
+      "pluginId": "cordova-plugin-qqsdk",
+      "clobbers": [
+        "QQSDK"
+      ]
     }
   ],
   "plugin_metadata": {
@@ -705,6 +785,7 @@
     "cordova-plugin-wkwebview-engine": "1.2.1",
     "cordova-plugin-brightness": "0.1.5",
     "cordova-plugin-fingerprint-aio": "3.0.1",
-    "cordova-plugin-prevent-screenshot-coffice": "1.0.1"
+    "cordova-plugin-prevent-screenshot-coffice": "1.0.1",
+    "cordova-plugin-qqsdk": "0.9.7"
   }
 }
diff --git a/platforms/android/app/libs/mta-sdk-1.6.2.jar b/platforms/android/app/libs/mta-sdk-1.6.2.jar
new file mode 100644
index 0000000..49b7787
--- /dev/null
+++ b/platforms/android/app/libs/mta-sdk-1.6.2.jar
Binary files differ
diff --git a/platforms/android/app/libs/open_sdk_r5793.jar b/platforms/android/app/libs/open_sdk_r5793.jar
new file mode 100644
index 0000000..eae0e84
--- /dev/null
+++ b/platforms/android/app/libs/open_sdk_r5793.jar
Binary files differ
diff --git a/platforms/android/app/src/main/AndroidManifest.xml b/platforms/android/app/src/main/AndroidManifest.xml
index b7ece77..4b6fab6 100644
--- a/platforms/android/app/src/main/AndroidManifest.xml
+++ b/platforms/android/app/src/main/AndroidManifest.xml
@@ -81,6 +81,15 @@
         <meta-data android:name="JPUSH_CHANNEL" android:value="developer-default" />
         <meta-data android:name="JPUSH_APPKEY" android:value="1fc62c8c6204ec4b0ae65ee2" />
         <activity android:exported="true" android:name="de.niklasmerz.cordova.biometric.BiometricActivity" android:theme="@style/TransparentTheme" />
+        <activity android:launchMode="singleTask" android:name="com.tencent.tauth.AuthActivity" android:noHistory="true">
+            <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:scheme="tencent101885581" />
+            </intent-filter>
+        </activity>
+        <activity android:configChanges="orientation|keyboardHidden" android:name="com.tencent.connect.common.AssistActivity" android:screenOrientation="portrait" android:theme="@android:style/Theme.Translucent.NoTitleBar" />
     </application>
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.CAMERA" android:required="false" />
diff --git a/platforms/android/app/src/main/assets/www/cordova_plugins.js b/platforms/android/app/src/main/assets/www/cordova_plugins.js
index a989701..08297e5 100644
--- a/platforms/android/app/src/main/assets/www/cordova_plugins.js
+++ b/platforms/android/app/src/main/assets/www/cordova_plugins.js
@@ -351,6 +351,14 @@
       "clobbers": [
         "window.plugins.preventscreenshot"
       ]
+    },
+    {
+      "id": "cordova-plugin-qqsdk.QQSDK",
+      "file": "plugins/cordova-plugin-qqsdk/www/qq.js",
+      "pluginId": "cordova-plugin-qqsdk",
+      "clobbers": [
+        "QQSDK"
+      ]
     }
   ];
   module.exports.metadata = {
@@ -372,6 +380,7 @@
     "cordova-plugin-wkwebview-engine": "1.2.1",
     "cordova-plugin-brightness": "0.1.5",
     "cordova-plugin-fingerprint-aio": "3.0.1",
-    "cordova-plugin-prevent-screenshot-coffice": "1.0.1"
+    "cordova-plugin-prevent-screenshot-coffice": "1.0.1",
+    "cordova-plugin-qqsdk": "0.9.7"
   };
 });
\ No newline at end of file
diff --git a/platforms/android/app/src/main/java/me/vanpan/qqsdk/QQSDKPlugin.java b/platforms/android/app/src/main/java/me/vanpan/qqsdk/QQSDKPlugin.java
new file mode 100644
index 0000000..0d8f2bc
--- /dev/null
+++ b/platforms/android/app/src/main/java/me/vanpan/qqsdk/QQSDKPlugin.java
@@ -0,0 +1,687 @@
+package me.vanpan.qqsdk;
+
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.util.Base64;
+import android.util.Log;
+import android.webkit.URLUtil;
+import com.tencent.connect.common.Constants;
+import com.tencent.connect.share.QQShare;
+import com.tencent.connect.share.QzonePublish;
+import com.tencent.connect.share.QzoneShare;
+import com.tencent.open.GameAppOperation;
+import com.tencent.tauth.IUiListener;
+import com.tencent.tauth.Tencent;
+import com.tencent.tauth.UiError;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import org.apache.cordova.CallbackContext;
+import org.apache.cordova.CordovaArgs;
+import org.apache.cordova.CordovaPlugin;
+import org.apache.cordova.PluginResult;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import static org.apache.cordova.CordovaActivity.TAG;
+
+/**
+ * Project: QQSDKPlugin
+ * Created by Van on 2016/12/16.
+ */
+
+class ShareScene {
+  public static final int QQ = 0;
+  public static final int QQZone = 1;
+  public static final int Favorite = 2;
+}
+
+public class QQSDKPlugin extends CordovaPlugin {
+  private static Tencent mTencent;
+  private CallbackContext currentCallbackContext;
+  private String APP_ID;
+  private static final String QQ_APP_ID = "qq_app_id";
+  private static final String QQ_CANCEL_BY_USER = "cancelled by user";
+  private static final String QQ_RESPONSE_ERROR = "QQ response is error";
+  private static final String QZONE_SHARE_CANCEL = "QZone share is cancelled";
+  private static final String QQFAVORITES_CANCEL = "QQ Favorites is cancelled";
+  private static final String QQ_Client_NOT_INSYALLED_ERROR = "QQ client is not installed";
+  private static final String QQ_PARAM_ERROR = "param incorrect";
+
+  @Override protected void pluginInitialize() {
+    super.pluginInitialize();
+    APP_ID = webView.getPreferences().getString(QQ_APP_ID, "");
+    mTencent = Tencent.createInstance(APP_ID, this.cordova.getActivity().getApplicationContext());
+  }
+
+  @Override
+  public boolean execute(String action, final CordovaArgs args, final CallbackContext callbackContext)
+      throws JSONException {
+    if (action.equalsIgnoreCase("checkClientInstalled")) {
+      return checkClientInstalled(callbackContext);
+    }
+    if (action.equals("ssoLogin")) {
+      return ssoLogin(callbackContext);
+    }
+    if (action.equals("logout")) {
+      return logout(callbackContext);
+    }
+    if (action.equals("shareText")) {
+      return shareText(args,callbackContext);
+    }
+    if (action.equals("shareImage")) {
+      return shareImage(args,callbackContext);
+    }
+    if (action.equals("shareNews")) {
+      return shareNews(args,callbackContext);
+    }
+    if (action.equals("shareAudio")) {
+      return shareAudio(args,callbackContext);
+    }
+    return super.execute(action, args, callbackContext);
+  }
+
+  /**
+   * 检查手机QQ客户端是否安装
+   */
+  private boolean checkClientInstalled(CallbackContext callbackContext) {
+    Boolean installed = mTencent.isSupportSSOLogin(QQSDKPlugin.this.cordova.getActivity());
+    if (installed) {
+      callbackContext.success();
+    } else {
+      callbackContext.error(QQ_Client_NOT_INSYALLED_ERROR);
+    }
+    return true;
+  }
+
+  /**
+   * QQ 单点登录
+   */
+  private boolean ssoLogin(CallbackContext callbackContext) {
+    currentCallbackContext = callbackContext;
+      Runnable runnable = new Runnable() {
+        @Override public void run() {
+          mTencent.login(QQSDKPlugin.this.cordova.getActivity(), "all", loginListener);
+        }
+      };
+      this.cordova.getActivity().runOnUiThread(runnable);
+      this.cordova.setActivityResultCallback(this);
+      return true;
+  }
+
+  /**
+   * QQ 登出
+   */
+  private boolean logout(CallbackContext callbackContext) {
+    mTencent.logout(this.cordova.getActivity());
+    callbackContext.success();
+    return true;
+  }
+
+  public boolean shareText(CordovaArgs args, CallbackContext callbackContext) {
+    final Bundle params = new Bundle();
+    currentCallbackContext = callbackContext;
+    final JSONObject data;
+    try {
+      data = args.getJSONObject(0);
+      String text = data.has("text")?  data.getString("text"): "";
+      int shareScene = data.has("scene")? data.getInt("scene"): 0;
+      switch (shareScene) {
+        case ShareScene.QQ:
+          callbackContext.error("Android 不支持分享文字到 QQ");
+          break;
+        case ShareScene.Favorite:
+          params.putInt(GameAppOperation.QQFAV_DATALINE_REQTYPE,
+              GameAppOperation.QQFAV_DATALINE_TYPE_TEXT);
+          params.putString(GameAppOperation.QQFAV_DATALINE_TITLE, getAppName());
+          params.putString(GameAppOperation.QQFAV_DATALINE_DESCRIPTION, text);
+          params.putString(GameAppOperation.QQFAV_DATALINE_APPNAME, getAppName());
+          Runnable favoritesRunnable = new Runnable() {
+            @Override public void run() {
+              mTencent.addToQQFavorites(QQSDKPlugin.this.cordova.getActivity(), params,
+                  addToQQFavoritesListener);
+            }
+          };
+          this.cordova.getActivity().runOnUiThread(favoritesRunnable);
+          this.cordova.setActivityResultCallback(this);
+          break;
+        case ShareScene.QQZone:
+          params.putInt(QzoneShare.SHARE_TO_QZONE_KEY_TYPE,
+              QzonePublish.PUBLISH_TO_QZONE_TYPE_PUBLISHMOOD);
+          params.putString(QzoneShare.SHARE_TO_QQ_TITLE, text);
+          Runnable zoneRunnable = new Runnable() {
+
+            @Override public void run() {
+              mTencent.publishToQzone(QQSDKPlugin.this.cordova.getActivity(), params,
+                  qZoneShareListener);
+            }
+          };
+          this.cordova.getActivity().runOnUiThread(zoneRunnable);
+          this.cordova.setActivityResultCallback(this);
+          break;
+        default:
+          break;
+      }
+    } catch (JSONException e) {
+      callbackContext.error(QQ_PARAM_ERROR);
+      return true;
+    }
+    return true;
+  }
+
+  public boolean shareImage(CordovaArgs args, CallbackContext callbackContext) {
+    currentCallbackContext = callbackContext;
+    final JSONObject data;
+    try {
+      data = args.getJSONObject(0);
+      String title = data.has("title")?  data.getString("title"): "";
+      String description = data.has("description")?  data.getString("description"): "";
+      String image = data.has("image")?  data.getString("image"): "";
+      int shareScene = data.has("scene")? data.getInt("scene"): 0;
+      image = processImage(image);
+      final Bundle params = new Bundle();
+      switch (shareScene) {
+        case ShareScene.QQ:
+          params.putInt(QQShare.SHARE_TO_QQ_KEY_TYPE, QQShare.SHARE_TO_QQ_TYPE_IMAGE);
+          params.putString(QQShare.SHARE_TO_QQ_IMAGE_LOCAL_URL, image);
+          params.putString(QQShare.SHARE_TO_QQ_TITLE, title);
+          params.putString(QQShare.SHARE_TO_QQ_SUMMARY, description);
+          Runnable qqRunnable = new Runnable() {
+
+            @Override public void run() {
+              mTencent.shareToQQ(QQSDKPlugin.this.cordova.getActivity(), params, qqShareListener);
+            }
+          };
+          this.cordova.getActivity().runOnUiThread(qqRunnable);
+          this.cordova.setActivityResultCallback(this);
+          break;
+        case ShareScene.Favorite:
+          ArrayList<String> imageUrls = new ArrayList<String>();
+          imageUrls.add(image);
+          params.putInt(GameAppOperation.QQFAV_DATALINE_REQTYPE,
+              GameAppOperation.QQFAV_DATALINE_TYPE_IMAGE_TEXT);
+          params.putString(GameAppOperation.QQFAV_DATALINE_TITLE, title);
+          params.putString(GameAppOperation.QQFAV_DATALINE_DESCRIPTION, description);
+          params.putString(GameAppOperation.QQFAV_DATALINE_IMAGEURL, image);
+          params.putString(GameAppOperation.QQFAV_DATALINE_APPNAME, getAppName());
+          params.putStringArrayList(GameAppOperation.QQFAV_DATALINE_FILEDATA, imageUrls);
+          Runnable favoritesRunnable = new Runnable() {
+            @Override public void run() {
+              mTencent.addToQQFavorites(QQSDKPlugin.this.cordova.getActivity(), params,
+                  addToQQFavoritesListener);
+            }
+          };
+          this.cordova.getActivity().runOnUiThread(favoritesRunnable);
+          this.cordova.setActivityResultCallback(this);
+          break;
+        case ShareScene.QQZone:
+          params.putInt(QQShare.SHARE_TO_QQ_KEY_TYPE, QQShare.SHARE_TO_QQ_TYPE_IMAGE);
+          params.putString(QQShare.SHARE_TO_QQ_IMAGE_LOCAL_URL, image);
+          params.putString(QQShare.SHARE_TO_QQ_TITLE, title);
+          params.putString(QQShare.SHARE_TO_QQ_SUMMARY, description);
+          params.putInt(QQShare.SHARE_TO_QQ_EXT_INT, QQShare.SHARE_TO_QQ_FLAG_QZONE_AUTO_OPEN);
+          Runnable zoneRunnable = new Runnable() {
+
+            @Override public void run() {
+              mTencent.shareToQQ(QQSDKPlugin.this.cordova.getActivity(), params, qqShareListener);
+            }
+          };
+          this.cordova.getActivity().runOnUiThread(zoneRunnable);
+          this.cordova.setActivityResultCallback(this);
+          break;
+        default:
+          break;
+      }
+    } catch (JSONException e) {
+      callbackContext.error(QQ_PARAM_ERROR);
+      return true;
+    }
+    return true;
+  }
+
+  public boolean shareNews(CordovaArgs args, CallbackContext callbackContext) {
+    currentCallbackContext = callbackContext;
+    final JSONObject data;
+    try {
+      data = args.getJSONObject(0);
+      String title = data.has("title")?  data.getString("title"): "";
+      String description = data.has("description")?  data.getString("description"): "";
+      String image = data.has("image")?  data.getString("image"): "";
+      String url = data.has("url")?  data.getString("url"): "";
+      int shareScene = data.has("scene")? data.getInt("scene"): 0;
+      final Bundle params = new Bundle();
+      switch (shareScene) {
+        case ShareScene.QQ:
+          params.putInt(QQShare.SHARE_TO_QQ_KEY_TYPE, QQShare.SHARE_TO_QQ_TYPE_DEFAULT);
+          if(URLUtil.isHttpUrl(image) || URLUtil.isHttpsUrl(image)) {
+            params.putString(QQShare.SHARE_TO_QQ_IMAGE_URL,image);
+          } else {
+            params.putString(QQShare.SHARE_TO_QQ_IMAGE_LOCAL_URL,processImage(image));
+          }
+          params.putString(QQShare.SHARE_TO_QQ_TITLE, title);
+          params.putString(QQShare.SHARE_TO_QQ_TARGET_URL, url);
+          params.putString(QQShare.SHARE_TO_QQ_SUMMARY, description);
+          Runnable qqRunnable = new Runnable() {
+
+            @Override public void run() {
+              mTencent.shareToQQ(QQSDKPlugin.this.cordova.getActivity(), params, qqShareListener);
+            }
+          };
+          this.cordova.getActivity().runOnUiThread(qqRunnable);
+          this.cordova.setActivityResultCallback(this);
+          break;
+        case ShareScene.Favorite:
+          image = processImage(image);
+          params.putInt(GameAppOperation.QQFAV_DATALINE_REQTYPE,
+              GameAppOperation.QQFAV_DATALINE_TYPE_DEFAULT);
+          params.putString(GameAppOperation.QQFAV_DATALINE_TITLE, title);
+          params.putString(GameAppOperation.QQFAV_DATALINE_DESCRIPTION, description);
+          params.putString(GameAppOperation.QQFAV_DATALINE_IMAGEURL, image);
+          params.putString(GameAppOperation.QQFAV_DATALINE_URL, url);
+          params.putString(GameAppOperation.QQFAV_DATALINE_APPNAME, getAppName());
+          Runnable favoritesRunnable = new Runnable() {
+            @Override public void run() {
+              mTencent.addToQQFavorites(QQSDKPlugin.this.cordova.getActivity(), params,
+                  addToQQFavoritesListener);
+            }
+          };
+          this.cordova.getActivity().runOnUiThread(favoritesRunnable);
+          this.cordova.setActivityResultCallback(this);
+          break;
+        case ShareScene.QQZone:
+          image = processImage(image);
+          ArrayList<String> imageUrls = new ArrayList<String>();
+          imageUrls.add(image);
+          params.putInt(QzoneShare.SHARE_TO_QZONE_KEY_TYPE,
+              QzoneShare.SHARE_TO_QZONE_TYPE_IMAGE_TEXT);
+          params.putString(QzoneShare.SHARE_TO_QQ_TITLE, title);
+          params.putString(QzoneShare.SHARE_TO_QQ_SUMMARY, description);
+          params.putString(QzoneShare.SHARE_TO_QQ_TARGET_URL, url);
+          params.putStringArrayList(QzoneShare.SHARE_TO_QQ_IMAGE_URL, imageUrls);
+          Runnable zoneRunnable = new Runnable() {
+
+            @Override public void run() {
+              mTencent.shareToQzone(QQSDKPlugin.this.cordova.getActivity(), params,
+                  qZoneShareListener);
+            }
+          };
+          this.cordova.getActivity().runOnUiThread(zoneRunnable);
+          this.cordova.setActivityResultCallback(this);
+          break;
+        default:
+          break;
+      }
+    } catch (JSONException e) {
+      callbackContext.error(QQ_PARAM_ERROR);
+      return true;
+    }
+    return true;
+  }
+
+  public boolean shareAudio(CordovaArgs args, CallbackContext callbackContext) {
+    currentCallbackContext = callbackContext;
+    final JSONObject data;
+    try {
+      data = args.getJSONObject(0);
+      String title = data.has("title")?  data.getString("title"): "";
+      String description = data.has("description")?  data.getString("description"): "";
+      String image = data.has("image")?  data.getString("image"): "";
+      String url = data.has("url")?  data.getString("url"): "";
+      String flashUrl = data.has("flashUrl")?  data.getString("flashUrl"): "";
+      int shareScene = data.has("scene")? data.getInt("scene"): 0;
+      final Bundle params = new Bundle();
+      switch (shareScene) {
+        case ShareScene.QQ:
+          params.putInt(QQShare.SHARE_TO_QQ_KEY_TYPE, QQShare.SHARE_TO_QQ_TYPE_DEFAULT);
+          if(URLUtil.isHttpUrl(image) || URLUtil.isHttpsUrl(image)) {
+            params.putString(QQShare.SHARE_TO_QQ_IMAGE_URL,image);
+          } else {
+            params.putString(QQShare.SHARE_TO_QQ_IMAGE_LOCAL_URL,processImage(image));
+          }
+          params.putString(QQShare.SHARE_TO_QQ_AUDIO_URL, flashUrl);
+          params.putString(QQShare.SHARE_TO_QQ_TITLE, title);
+          params.putString(QQShare.SHARE_TO_QQ_TARGET_URL, url);
+          params.putString(QQShare.SHARE_TO_QQ_SUMMARY, description);
+          Runnable qqRunnable = new Runnable() {
+
+            @Override public void run() {
+              mTencent.shareToQQ(QQSDKPlugin.this.cordova.getActivity(), params, qqShareListener);
+            }
+          };
+          this.cordova.getActivity().runOnUiThread(qqRunnable);
+          this.cordova.setActivityResultCallback(this);
+          break;
+        case ShareScene.Favorite:
+          image = processImage(image);
+          params.putInt(GameAppOperation.QQFAV_DATALINE_REQTYPE,
+              GameAppOperation.QQFAV_DATALINE_TYPE_DEFAULT);
+          params.putString(GameAppOperation.QQFAV_DATALINE_TITLE, title);
+          params.putString(GameAppOperation.QQFAV_DATALINE_DESCRIPTION, description);
+          params.putString(GameAppOperation.QQFAV_DATALINE_IMAGEURL, image);
+          params.putString(GameAppOperation.QQFAV_DATALINE_URL, url);
+          params.putString(GameAppOperation.QQFAV_DATALINE_APPNAME, getAppName());
+          params.putString(GameAppOperation.QQFAV_DATALINE_AUDIOURL, flashUrl);
+          Runnable favoritesRunnable = new Runnable() {
+            @Override public void run() {
+              mTencent.addToQQFavorites(QQSDKPlugin.this.cordova.getActivity(), params,
+                  addToQQFavoritesListener);
+            }
+          };
+          this.cordova.getActivity().runOnUiThread(favoritesRunnable);
+          this.cordova.setActivityResultCallback(this);
+          break;
+        case ShareScene.QQZone:
+          image = processImage(image);
+          ArrayList<String> imageUrls = new ArrayList<String>();
+          imageUrls.add(image);
+          params.putInt(QzoneShare.SHARE_TO_QZONE_KEY_TYPE,
+              QzoneShare.SHARE_TO_QZONE_TYPE_IMAGE_TEXT);
+          params.putString(QzoneShare.SHARE_TO_QQ_TITLE, title);
+          params.putString(QzoneShare.SHARE_TO_QQ_SUMMARY, description);
+          params.putString(QzoneShare.SHARE_TO_QQ_TARGET_URL, url);
+          params.putString(QzoneShare.SHARE_TO_QQ_AUDIO_URL, flashUrl);
+          params.putStringArrayList(QzoneShare.SHARE_TO_QQ_IMAGE_URL, imageUrls);
+          Runnable zoneRunnable = new Runnable() {
+
+            @Override public void run() {
+              mTencent.shareToQzone(QQSDKPlugin.this.cordova.getActivity(), params,
+                  qZoneShareListener);
+            }
+          };
+          this.cordova.getActivity().runOnUiThread(zoneRunnable);
+          this.cordova.setActivityResultCallback(this);
+          break;
+        default:
+          break;
+      }
+    } catch (JSONException e) {
+      callbackContext.error(QQ_PARAM_ERROR);
+      return true;
+    }
+    return true;
+  }
+
+  /**
+   * 保存token 和 openid
+   */
+  public static void initOpenidAndToken(JSONObject jsonObject) {
+    try {
+      String token = jsonObject.getString(Constants.PARAM_ACCESS_TOKEN);
+      String expires = jsonObject.getString(Constants.PARAM_EXPIRES_IN);
+      String openId = jsonObject.getString(Constants.PARAM_OPEN_ID);
+      if (!TextUtils.isEmpty(token) && !TextUtils.isEmpty(expires) && !TextUtils.isEmpty(openId)) {
+        mTencent.setAccessToken(token, expires);
+        mTencent.setOpenId(openId);
+      }
+    } catch (Exception e) {
+    }
+  }
+
+  /**
+   * 获取应用的名称
+   */
+  private String getAppName() {
+    PackageManager packageManager = this.cordova.getActivity().getPackageManager();
+    ApplicationInfo applicationInfo = null;
+    try {
+      applicationInfo =
+          packageManager.getApplicationInfo(this.cordova.getActivity().getPackageName(), 0);
+    } catch (final PackageManager.NameNotFoundException e) {
+    }
+    final String AppName =
+        (String) ((applicationInfo != null) ? packageManager.getApplicationLabel(applicationInfo)
+            : "AppName");
+    return AppName;
+  }
+
+  /**
+   * 处理图片
+   * @param image
+   * @return
+   */
+  private String processImage(String image) {
+    if(URLUtil.isHttpUrl(image) || URLUtil.isHttpsUrl(image)) {
+      return saveBitmapToFile(getBitmapFromURL(image));
+    } else if (isBase64(image)) {
+      return saveBitmapToFile(decodeBase64ToBitmap(image));
+    } else if (image.startsWith("/") ){
+      File file = new File(image);
+      return file.getAbsolutePath();
+    } else {
+      return null;
+    }
+  }
+
+  /**
+   * 检查图片字符串是不是Base64
+   * @param image
+   * @return
+   */
+  private boolean isBase64(String image) {
+    try {
+      byte[] decodedString = Base64.decode(image, Base64.DEFAULT);
+      Bitmap bitmap = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);
+      if (bitmap == null) {
+        return false;
+      }
+      return true;
+    } catch (Exception e) {
+      return false;
+    }
+  }
+
+
+  public static Bitmap getBitmapFromURL(String src) {
+    try {
+      URL url = new URL(src);
+      HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+      connection.setDoInput(true);
+      connection.connect();
+      InputStream input = connection.getInputStream();
+      Bitmap bitmap = BitmapFactory.decodeStream(input);
+      return bitmap;
+    } catch (IOException e) {
+      return null;
+    }
+  }
+
+  /**
+   * 将Base64解码成Bitmap
+   */
+
+  private Bitmap decodeBase64ToBitmap(String Base64String) {
+    byte[] decode = Base64.decode(Base64String, Base64.DEFAULT);
+    Bitmap bitmap = BitmapFactory.decodeByteArray(decode, 0, decode.length);
+    return bitmap;
+  }
+
+  /**
+   * 将bitmap 保存成文件
+   */
+  private String saveBitmapToFile(Bitmap bitmap) {
+    File pictureFile = getOutputMediaFile();
+    if (pictureFile == null) {
+      return null;
+    }
+    try {
+      FileOutputStream fos = new FileOutputStream(pictureFile);
+      bitmap.compress(Bitmap.CompressFormat.PNG, 90, fos);
+      fos.close();
+    } catch (FileNotFoundException e) {
+      Log.d(TAG, "File not found: " + e.getMessage());
+    } catch (IOException e) {
+      Log.d(TAG, "Error accessing file: " + e.getMessage());
+    }
+    return pictureFile.getAbsolutePath();
+  }
+
+  /**
+   * 生成文件用来存储图片
+   */
+  private File getOutputMediaFile() {
+    File mediaStorageDir = this.cordova.getActivity().getExternalCacheDir();
+    if (!mediaStorageDir.exists()) {
+      if (!mediaStorageDir.mkdirs()) {
+        return null;
+      }
+    }
+    String timeStamp = new SimpleDateFormat("ddMMyyyy_HHmm").format(new Date());
+    File mediaFile;
+    String mImageName = "Cordova_" + timeStamp + ".jpg";
+    mediaFile = new File(mediaStorageDir.getPath() + File.separator + mImageName);
+    return mediaFile;
+  }
+
+  /**
+   * 登录监听
+   */
+  IUiListener loginListener = new IUiListener() {
+    @Override public void onComplete(Object response) {
+      if (null == response) {
+        QQSDKPlugin.this.webView.sendPluginResult(
+            new PluginResult(PluginResult.Status.ERROR, QQ_RESPONSE_ERROR),
+            currentCallbackContext.getCallbackId());
+        return;
+      }
+      JSONObject jsonResponse = (JSONObject) response;
+      if (null != jsonResponse && jsonResponse.length() == 0) {
+        QQSDKPlugin.this.webView.sendPluginResult(
+            new PluginResult(PluginResult.Status.ERROR, QQ_RESPONSE_ERROR),
+            currentCallbackContext.getCallbackId());
+        return;
+      }
+      initOpenidAndToken(jsonResponse);
+      JSONObject jo =
+          makeJson(mTencent.getAccessToken(), mTencent.getOpenId(), mTencent.getExpiresIn());
+      QQSDKPlugin.this.webView.sendPluginResult(new PluginResult(PluginResult.Status.OK, jo),
+          currentCallbackContext.getCallbackId());
+    }
+
+    @Override public void onError(UiError e) {
+      QQSDKPlugin.this.webView.sendPluginResult(
+          new PluginResult(PluginResult.Status.ERROR, e.errorMessage),
+          currentCallbackContext.getCallbackId());
+    }
+
+    @Override public void onCancel() {
+      QQSDKPlugin.this.webView.sendPluginResult(
+          new PluginResult(PluginResult.Status.ERROR, QQ_CANCEL_BY_USER),
+          currentCallbackContext.getCallbackId());
+    }
+  };
+  /**
+   * QQ分享监听
+   */
+  IUiListener qqShareListener = new IUiListener() {
+    @Override public void onCancel() {
+      QQSDKPlugin.this.webView.sendPluginResult(
+          new PluginResult(PluginResult.Status.ERROR, QQ_CANCEL_BY_USER),
+          currentCallbackContext.getCallbackId());
+    }
+
+    @Override public void onComplete(Object response) {
+      QQSDKPlugin.this.webView.sendPluginResult(new PluginResult(PluginResult.Status.OK),
+          currentCallbackContext.getCallbackId());
+    }
+
+    @Override public void onError(UiError e) {
+      QQSDKPlugin.this.webView.sendPluginResult(
+          new PluginResult(PluginResult.Status.ERROR, e.errorMessage),
+          currentCallbackContext.getCallbackId());
+    }
+  };
+  /**
+   * QQZONE 分享监听
+   */
+  IUiListener qZoneShareListener = new IUiListener() {
+
+    @Override public void onCancel() {
+      QQSDKPlugin.this.webView.sendPluginResult(
+          new PluginResult(PluginResult.Status.ERROR, QZONE_SHARE_CANCEL),
+          currentCallbackContext.getCallbackId());
+    }
+
+    @Override public void onError(UiError e) {
+      QQSDKPlugin.this.webView.sendPluginResult(
+          new PluginResult(PluginResult.Status.ERROR, e.errorMessage),
+          currentCallbackContext.getCallbackId());
+    }
+
+    @Override public void onComplete(Object response) {
+      QQSDKPlugin.this.webView.sendPluginResult(new PluginResult(PluginResult.Status.OK),
+          currentCallbackContext.getCallbackId());
+    }
+  };
+  /**
+   * 添加到QQ收藏监听
+   */
+  IUiListener addToQQFavoritesListener = new IUiListener() {
+    @Override public void onCancel() {
+      QQSDKPlugin.this.webView.sendPluginResult(
+          new PluginResult(PluginResult.Status.ERROR, QQFAVORITES_CANCEL),
+          currentCallbackContext.getCallbackId());
+    }
+
+    @Override public void onComplete(Object response) {
+      QQSDKPlugin.this.webView.sendPluginResult(new PluginResult(PluginResult.Status.OK),
+          currentCallbackContext.getCallbackId());
+    }
+
+    @Override public void onError(UiError e) {
+      QQSDKPlugin.this.webView.sendPluginResult(
+          new PluginResult(PluginResult.Status.ERROR, e.errorMessage),
+          currentCallbackContext.getCallbackId());
+    }
+  };
+
+  /**
+   * 组装JSON
+   */
+  private JSONObject makeJson(String access_token, String userid, long expires_time) {
+    String json = "{\"access_token\": \"" + access_token + "\", " +
+        " \"userid\": \"" + userid + "\", " +
+        " \"expires_time\": \"" + String.valueOf(expires_time) + "\"" +
+        "}";
+    JSONObject jo = null;
+    try {
+      jo = new JSONObject(json);
+    } catch (JSONException e) {
+      e.printStackTrace();
+    }
+    return jo;
+  }
+
+  @Override public void onActivityResult(int requestCode, int resultCode, Intent intent) {
+    if (resultCode == Constants.ACTIVITY_OK) {
+      if (requestCode == Constants.REQUEST_LOGIN) {
+        Tencent.onActivityResultData(requestCode, resultCode, intent, loginListener);
+      }
+      if (requestCode == Constants.REQUEST_QQ_SHARE) {
+        Tencent.onActivityResultData(requestCode, resultCode, intent, qqShareListener);
+      }
+      if (requestCode == Constants.REQUEST_QQ_FAVORITES) {
+        Tencent.onActivityResultData(requestCode, resultCode, intent, addToQQFavoritesListener);
+      }
+    }
+    super.onActivityResult(requestCode, resultCode, intent);
+  }
+
+  @Override public void onDestroy() {
+    super.onDestroy();
+    if (mTencent != null) {
+      mTencent.releaseResource();
+    }
+  }
+}
diff --git a/platforms/android/app/src/main/res/xml/config.xml b/platforms/android/app/src/main/res/xml/config.xml
index 019dfb6..e85c38a 100644
--- a/platforms/android/app/src/main/res/xml/config.xml
+++ b/platforms/android/app/src/main/res/xml/config.xml
@@ -47,6 +47,17 @@
         <param name="android-package" value="com.coffice.ScreenshotBlocker" />
         <param name="onload" value="true" />
     </feature>
+    <feature name="QQSDK">
+        <param name="android-package" value="me.vanpan.qqsdk.QQSDKPlugin" />
+    </feature>
+    <access origin="https://openmobile.qq.com/*" />
+    <access origin="http://qzonestyle.gtimg.cn/*" />
+    <access origin="http://pub.idqqimg.com/*" />
+    <access origin="http://qzs.qq.com/*" />
+    <access origin="http://m.qzone.com/*" />
+    <access origin="http://*.ptlogin2.qq.com/*" />
+    <access origin="http://*.qq.com/*" />
+    <access origin="http://q2.qlogo.cn/*" />
     <name short="大理智警">dlapp</name>
     <description>
         A sample Apache Cordova application that responds to the deviceready event.
@@ -74,6 +85,7 @@
     </edit-config>
     <allow-intent href="market:*" />
     <preference name="loglevel" value="DEBUG" />
+    <preference name="QQ_APP_ID" value="101885581" />
     <preference name="AutoHideSplashScreen" value="true" />
     <preference name="SplashScreenDelay" value="0" />
     <preference name="SplashShowOnlyFirstTime" value="true" />
diff --git a/platforms/android/platform_www/cordova_plugins.js b/platforms/android/platform_www/cordova_plugins.js
index a989701..08297e5 100644
--- a/platforms/android/platform_www/cordova_plugins.js
+++ b/platforms/android/platform_www/cordova_plugins.js
@@ -351,6 +351,14 @@
       "clobbers": [
         "window.plugins.preventscreenshot"
       ]
+    },
+    {
+      "id": "cordova-plugin-qqsdk.QQSDK",
+      "file": "plugins/cordova-plugin-qqsdk/www/qq.js",
+      "pluginId": "cordova-plugin-qqsdk",
+      "clobbers": [
+        "QQSDK"
+      ]
     }
   ];
   module.exports.metadata = {
@@ -372,6 +380,7 @@
     "cordova-plugin-wkwebview-engine": "1.2.1",
     "cordova-plugin-brightness": "0.1.5",
     "cordova-plugin-fingerprint-aio": "3.0.1",
-    "cordova-plugin-prevent-screenshot-coffice": "1.0.1"
+    "cordova-plugin-prevent-screenshot-coffice": "1.0.1",
+    "cordova-plugin-qqsdk": "0.9.7"
   };
 });
\ No newline at end of file
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-qqsdk/www/qq.js b/platforms/android/platform_www/plugins/cordova-plugin-qqsdk/www/qq.js
new file mode 100644
index 0000000..cedb4c0
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-qqsdk/www/qq.js
@@ -0,0 +1,43 @@
+cordova.define("cordova-plugin-qqsdk.QQSDK", function(require, exports, module) {
+
+var cordova = require('cordova');
+module.exports = {
+	Scene: {
+        QQ:  0, // QQ 好友
+        QQZone: 1, // QQ 空间
+        Favorite: 2  // 收藏
+    },
+    ClientType: {
+        QQ:  0, // QQ 手机客户端
+        TIM: 1 // TIM 客户端
+    },
+	ssoLogin:function(successCallback, errorCallback, args){
+		if(args === undefined) {
+            args = {}
+        }
+		cordova.exec(successCallback, errorCallback, "QQSDK", "ssoLogin",[args]);
+	},
+	logout:function(successCallback, errorCallback){
+		cordova.exec(successCallback, errorCallback, "QQSDK", "logout", []);
+	},
+	checkClientInstalled:function(successCallback, errorCallback, args){
+		if(args === undefined) {
+            args = {}
+        }
+		cordova.exec(successCallback, errorCallback, "QQSDK", "checkClientInstalled", [args]);
+	},
+	shareText:function(successCallback, errorCallback, args){
+		cordova.exec(successCallback, errorCallback, "QQSDK", "shareText", [args]);
+	},
+	shareImage:function(successCallback, errorCallback, args){
+		cordova.exec(successCallback, errorCallback, "QQSDK", "shareImage", [args]);
+	},
+	shareNews:function(successCallback, errorCallback, args){
+		cordova.exec(successCallback, errorCallback, "QQSDK", "shareNews", [args]);
+	},
+	shareAudio:function(successCallback, errorCallback, args){
+		cordova.exec(successCallback, errorCallback, "QQSDK", "shareAudio", [args]);
+	},
+};
+
+});
diff --git a/platforms/android/project.properties b/platforms/android/project.properties
index a2f953f..0a6f4b6 100644
--- a/platforms/android/project.properties
+++ b/platforms/android/project.properties
@@ -14,4 +14,5 @@
 cordova.system.library.1=com.squareup.okhttp3:okhttp-urlconnection:3.10.0
 cordova.gradle.include.1=cordova-plugin-qrscanner/dlapp-qrscanner.gradle
 cordova.system.library.2=com.android.support:support-v4:24.1.1+
-cordova.gradle.include.2=cordova-plugin-fingerprint-aio/app-build.gradle
\ No newline at end of file
+cordova.gradle.include.2=cordova-plugin-fingerprint-aio/app-build.gradle
+cordova.system.library.3=com.android.support:support-v4:24.1.1+
\ No newline at end of file