diff --git a/.idea/file.template.settings.xml b/.idea/file.template.settings.xml
new file mode 100644
index 0000000..b6a82d9
--- /dev/null
+++ b/.idea/file.template.settings.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/fileTemplates/internal/Class.java b/.idea/fileTemplates/internal/Class.java
new file mode 100644
index 0000000..b09cd44
--- /dev/null
+++ b/.idea/fileTemplates/internal/Class.java
@@ -0,0 +1,5 @@
+#parse("File Header.java")
+#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end
+#parse("Class Header.java")
+public class ${NAME} {
+}
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
new file mode 100644
index 0000000..34bc08a
--- /dev/null
+++ b/.idea/gradle.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/__local_aars___D__AppItem_ShareLib_share_libs_open_sdk_r5990_lite_jar_unspecified_jar.xml b/.idea/libraries/__local_aars___D__AppItem_ShareLib_share_libs_open_sdk_r5990_lite_jar_unspecified_jar.xml
new file mode 100644
index 0000000..d51521a
--- /dev/null
+++ b/.idea/libraries/__local_aars___D__AppItem_ShareLib_share_libs_open_sdk_r5990_lite_jar_unspecified_jar.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/__local_aars___D__AppItem_ShareLib_share_libs_weiboSDKCore_3_1_4_jar_unspecified_jar.xml b/.idea/libraries/__local_aars___D__AppItem_ShareLib_share_libs_weiboSDKCore_3_1_4_jar_unspecified_jar.xml
new file mode 100644
index 0000000..4a79743
--- /dev/null
+++ b/.idea/libraries/__local_aars___D__AppItem_ShareLib_share_libs_weiboSDKCore_3_1_4_jar_unspecified_jar.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/com_android_support_animated_vector_drawable_25_0_0.xml b/.idea/libraries/com_android_support_animated_vector_drawable_25_0_0.xml
new file mode 100644
index 0000000..bc79748
--- /dev/null
+++ b/.idea/libraries/com_android_support_animated_vector_drawable_25_0_0.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/com_android_support_appcompat_v7_25_0_0.xml b/.idea/libraries/com_android_support_appcompat_v7_25_0_0.xml
new file mode 100644
index 0000000..2e68fdd
--- /dev/null
+++ b/.idea/libraries/com_android_support_appcompat_v7_25_0_0.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/com_android_support_support_annotations_25_0_0_jar.xml b/.idea/libraries/com_android_support_support_annotations_25_0_0_jar.xml
new file mode 100644
index 0000000..ce9c8c1
--- /dev/null
+++ b/.idea/libraries/com_android_support_support_annotations_25_0_0_jar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/com_android_support_support_compat_25_0_0.xml b/.idea/libraries/com_android_support_support_compat_25_0_0.xml
new file mode 100644
index 0000000..9c2033f
--- /dev/null
+++ b/.idea/libraries/com_android_support_support_compat_25_0_0.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/com_android_support_support_core_ui_25_0_0.xml b/.idea/libraries/com_android_support_support_core_ui_25_0_0.xml
new file mode 100644
index 0000000..0026044
--- /dev/null
+++ b/.idea/libraries/com_android_support_support_core_ui_25_0_0.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/com_android_support_support_core_utils_25_0_0.xml b/.idea/libraries/com_android_support_support_core_utils_25_0_0.xml
new file mode 100644
index 0000000..b308dcf
--- /dev/null
+++ b/.idea/libraries/com_android_support_support_core_utils_25_0_0.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/com_android_support_support_fragment_25_0_0.xml b/.idea/libraries/com_android_support_support_fragment_25_0_0.xml
new file mode 100644
index 0000000..52933ea
--- /dev/null
+++ b/.idea/libraries/com_android_support_support_fragment_25_0_0.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/com_android_support_support_media_compat_25_0_0.xml b/.idea/libraries/com_android_support_support_media_compat_25_0_0.xml
new file mode 100644
index 0000000..e316a71
--- /dev/null
+++ b/.idea/libraries/com_android_support_support_media_compat_25_0_0.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/com_android_support_support_v4_25_0_0.xml b/.idea/libraries/com_android_support_support_v4_25_0_0.xml
new file mode 100644
index 0000000..1f29fda
--- /dev/null
+++ b/.idea/libraries/com_android_support_support_v4_25_0_0.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/com_android_support_support_vector_drawable_25_0_0.xml b/.idea/libraries/com_android_support_support_vector_drawable_25_0_0.xml
new file mode 100644
index 0000000..a976d1c
--- /dev/null
+++ b/.idea/libraries/com_android_support_support_vector_drawable_25_0_0.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/com_squareup_okhttp3_okhttp_3_4_2_jar.xml b/.idea/libraries/com_squareup_okhttp3_okhttp_3_4_2_jar.xml
new file mode 100644
index 0000000..2b6f522
--- /dev/null
+++ b/.idea/libraries/com_squareup_okhttp3_okhttp_3_4_2_jar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/com_squareup_okio_okio_1_9_0_jar.xml b/.idea/libraries/com_squareup_okio_okio_1_9_0_jar.xml
new file mode 100644
index 0000000..f092095
--- /dev/null
+++ b/.idea/libraries/com_squareup_okio_okio_1_9_0_jar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/com_tencent_mm_opensdk_wechat_sdk_android_with_mta_5_1_0_jar.xml b/.idea/libraries/com_tencent_mm_opensdk_wechat_sdk_android_with_mta_5_1_0_jar.xml
new file mode 100644
index 0000000..00dab3a
--- /dev/null
+++ b/.idea/libraries/com_tencent_mm_opensdk_wechat_sdk_android_with_mta_5_1_0_jar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/com_tencent_mm_opensdk_wechat_sdk_android_with_mta_5_1_4_jar.xml b/.idea/libraries/com_tencent_mm_opensdk_wechat_sdk_android_with_mta_5_1_4_jar.xml
new file mode 100644
index 0000000..4526e44
--- /dev/null
+++ b/.idea/libraries/com_tencent_mm_opensdk_wechat_sdk_android_with_mta_5_1_4_jar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/io_reactivex_rxandroid_1_2_1.xml b/.idea/libraries/io_reactivex_rxandroid_1_2_1.xml
new file mode 100644
index 0000000..782f994
--- /dev/null
+++ b/.idea/libraries/io_reactivex_rxandroid_1_2_1.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/io_reactivex_rxjava_1_2_3_jar.xml b/.idea/libraries/io_reactivex_rxjava_1_2_3_jar.xml
new file mode 100644
index 0000000..bed9dfa
--- /dev/null
+++ b/.idea/libraries/io_reactivex_rxjava_1_2_3_jar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/junit_junit_4_12_jar.xml b/.idea/libraries/junit_junit_4_12_jar.xml
new file mode 100644
index 0000000..a026090
--- /dev/null
+++ b/.idea/libraries/junit_junit_4_12_jar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/org_hamcrest_hamcrest_core_1_3_jar.xml b/.idea/libraries/org_hamcrest_hamcrest_core_1_3_jar.xml
new file mode 100644
index 0000000..8bc8974
--- /dev/null
+++ b/.idea/libraries/org_hamcrest_hamcrest_core_1_3_jar.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..3963879
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..7d6122b
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml
new file mode 100644
index 0000000..7f68460
--- /dev/null
+++ b/.idea/runConfigurations.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..8cfaf9c
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,3802 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ \/\*\*\n \* Created by shaohui on 2016\/12\/3\.\n \*\/\n
+ /** * Created by shaohui on 2016/12/3. */
+ /** * Created by shaohui on 2016/12/3. *
+ /** * Created by shaohui on 2016/12/3.
+ qq_id
+ tencentass
+ tencentas
+ tencenta
+ tencent
+ a
+ app
+ app_
+ app_i
+ app_id
+ StatConfig
+ me.shaohui.shareutil
+
+
+
+ vip.devkit.common.share
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1517199098914
+
+
+ 1517199098914
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ShareLib.iml b/ShareLib.iml
new file mode 100644
index 0000000..fe32c28
--- /dev/null
+++ b/ShareLib.iml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/.gitignore b/app/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/app/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/app/app.iml b/app/app.iml
new file mode 100644
index 0000000..ff725f4
--- /dev/null
+++ b/app/app.iml
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ generateDebugSources
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
new file mode 100644
index 0000000..97c565b
--- /dev/null
+++ b/app/build.gradle
@@ -0,0 +1,39 @@
+apply plugin: 'com.android.application'
+
+android {
+ compileSdkVersion 25
+ buildToolsVersion "25.0.0"
+ defaultConfig {
+ applicationId "vip.devkit.share"
+ minSdkVersion 15
+ targetSdkVersion 25
+ versionCode 1
+ versionName "1.0"
+ manifestPlaceholders = [
+ qq_id: "1106535201"
+ ]
+ ndk {
+ abiFilters 'armeabi', 'x86', 'armeabi-v7a'//, 'x86_64', 'arm64-v8a'
+ }
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+ lintOptions {
+ abortOnError false
+ }
+ sourceSets {
+ main.jniLibs.srcDirs = ['libs']
+ }
+}
+
+dependencies {
+ compile fileTree(include: ['*.jar'], dir: 'libs')
+ testCompile 'junit:junit:4.12'
+ compile 'com.android.support:appcompat-v7:25.0.0'
+// compile 'vip.devkit:common.share:1.0.7'
+ compile project(':share')
+}
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
new file mode 100644
index 0000000..f1b4245
--- /dev/null
+++ b/app/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
diff --git a/app/src/androidTest/java/vip/devkit/share/ExampleInstrumentedTest.java b/app/src/androidTest/java/vip/devkit/share/ExampleInstrumentedTest.java
new file mode 100644
index 0000000..71e2bfc
--- /dev/null
+++ b/app/src/androidTest/java/vip/devkit/share/ExampleInstrumentedTest.java
@@ -0,0 +1,26 @@
+package vip.devkit.share;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see Testing documentation
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+ @Test
+ public void useAppContext() throws Exception {
+ // Context of the app under test.
+ Context appContext = InstrumentationRegistry.getTargetContext();
+
+ assertEquals("vip.devkit.share", appContext.getPackageName());
+ }
+}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..29bee82
--- /dev/null
+++ b/app/src/main/AndroidManifest.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/vip/devkit/share/MainActivity.java b/app/src/main/java/vip/devkit/share/MainActivity.java
new file mode 100644
index 0000000..8e7edee
--- /dev/null
+++ b/app/src/main/java/vip/devkit/share/MainActivity.java
@@ -0,0 +1,118 @@
+package vip.devkit.share;
+
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.Toast;
+
+import vip.devkit.common.share.LoginUtil;
+import vip.devkit.common.share.ShareConfig;
+import vip.devkit.common.share.ShareManager;
+import vip.devkit.common.share.ShareUtil;
+import vip.devkit.common.share.login.LoginListener;
+import vip.devkit.common.share.login.LoginPlatform;
+import vip.devkit.common.share.login.LoginResult;
+import vip.devkit.common.share.login.result.QQToken;
+import vip.devkit.common.share.login.result.QQUser;
+import vip.devkit.common.share.share.ShareListener;
+import vip.devkit.common.share.share.SharePlatform;
+
+public class MainActivity extends AppCompatActivity {
+ LoginListener mLoginListener;
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ // 初始化shareUtil
+ ShareConfig config = ShareConfig.instance()
+ .qqId("1106535201")
+ .weiboId("XXXXXX")
+ .wxId("xXXXXX");
+ ShareManager.init(config);
+ findViewById(R.id.btn_qq).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ /* ShareUtil.shareImage(MainActivity.this, SharePlatform.QQ,
+ "https://www.baidu.com/img/pcdongtai_b60a4b2d8e0d0d6392de47d4cec6fdc3.gif", new ShareListener() {
+ @Override
+ public void shareSuccess() {
+ Log.i("TAG", "分享成功");
+ }
+
+ @Override
+ public void shareFailure(Exception e) {
+ Log.i("TAG", "分享失败");
+ }
+
+ @Override
+ public void shareCancel() {
+ Log.i("TAG", "分享取消");
+ }
+ });*/
+ LoginUtil.login(MainActivity.this, LoginPlatform.QQ, mLoginListener);
+ }
+ });
+ findViewById(R.id.btn_qzone).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ ShareUtil.shareImage(MainActivity.this, SharePlatform.WEIBO,
+ "https://www.baidu.com/img/pcdongtai_b60a4b2d8e0d0d6392de47d4cec6fdc3.gif", new ShareListener() {
+ @Override
+ public void shareSuccess() {
+ Log.i("TAG", "分享成功");
+ }
+
+ @Override
+ public void shareFailure(Exception e) {
+ Log.i("TAG", "分享失败");
+ }
+
+ @Override
+ public void shareCancel() {
+ Log.i("TAG", "分享取消");
+ }
+ });
+ }
+ });
+ mLoginListener = new LoginListener() {
+ @Override
+ public void loginSuccess(LoginResult result) {
+ Toast.makeText(MainActivity.this,
+ result.getUserInfo() != null ? result.getUserInfo().getNickname()
+ : "" + "登录成功", Toast.LENGTH_SHORT).show();
+
+ // 处理result
+ switch (result.getPlatform()) {
+ case LoginPlatform.QQ:
+ QQUser user = (QQUser) result.getUserInfo();
+ QQToken token = (QQToken) result.getToken();
+ Log.i("atag",user+"/"+token+"/"+result.getUserInfo());
+ break;
+ case LoginPlatform.WEIBO:
+ // 处理信息
+ break;
+ case LoginPlatform.WX:
+
+ break;
+ }
+ }
+
+ @Override
+ public void loginFailure(Exception e) {
+ Toast.makeText(MainActivity.this, "登录失败", Toast.LENGTH_SHORT).show();
+ }
+
+ @Override
+ public void loginCancel() {
+ Toast.makeText(MainActivity.this, "登录取消", Toast.LENGTH_SHORT).show();
+ }
+ };
+
+
+
+ }
+
+
+}
diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
new file mode 100644
index 0000000..c7bd21d
--- /dev/null
+++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..d5fccc5
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..83a287f
--- /dev/null
+++ b/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 0000000..eca70cf
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000..eca70cf
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..a2f5908
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000..1b52399
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..ff10afd
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000..115a4c7
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..dcd3cd8
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..459ca60
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..8ca12fe
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..8e19b41
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..b824ebd
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..4c19a13
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..3ab3e9c
--- /dev/null
+++ b/app/src/main/res/values/colors.xml
@@ -0,0 +1,6 @@
+
+
+ #3F51B5
+ #303F9F
+ #FF4081
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..1d5e05f
--- /dev/null
+++ b/app/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+
+ ShareLib
+
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..5885930
--- /dev/null
+++ b/app/src/main/res/values/styles.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
diff --git a/app/src/test/java/vip/devkit/share/ExampleUnitTest.java b/app/src/test/java/vip/devkit/share/ExampleUnitTest.java
new file mode 100644
index 0000000..d13f719
--- /dev/null
+++ b/app/src/test/java/vip/devkit/share/ExampleUnitTest.java
@@ -0,0 +1,17 @@
+package vip.devkit.share;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see Testing documentation
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() throws Exception {
+ assertEquals(4, 2 + 2);
+ }
+}
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..8aac9b8
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,42 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+ repositories {
+ jcenter()
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:2.0.0'
+ classpath 'com.novoda:bintray-release:0.3.4'
+
+
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+}
+
+allprojects {
+ repositories {
+ jcenter()
+ maven { url 'https://dl.bintray.com/yingzi/maven' }
+ maven { url "https://jitpack.io" }
+
+ }
+ tasks.withType(Javadoc) {
+ options.addStringOption('Xdoclint:none', '-quiet')
+ options.addStringOption('encoding', 'UTF-8')
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
+//添加
+ext {
+ userOrg = 'yingzi' //bintray注册的用户名
+ groupId = 'vip.devkit' //compile引用时的第1部分groupId
+ artifactId = 'common.share' //compile引用时的第2部分项目名
+ publishVersion = '1.0.8' //compile引用时的第3部分版本号
+ desc = 'This is a common.widget extend library'
+ website = 'https://github.com/yingzikeji/AndroidUtils'
+ licences = ['Apache-2.0']
+}
\ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 0000000..e4e4ea3
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1,18 @@
+# Project-wide Gradle settings.
+
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx1536m
+
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+android.useDeprecatedNdk=true
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..13372ae
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..122a0dc
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Mon Dec 28 10:00:20 PST 2015
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip
diff --git a/gradlew b/gradlew
new file mode 100644
index 0000000..9d82f78
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,160 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000..8a0b282
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..a151281
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1 @@
+include ':app', ':share'
diff --git a/share/.gitignore b/share/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/share/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/share/build.gradle b/share/build.gradle
new file mode 100644
index 0000000..c2d6ba4
--- /dev/null
+++ b/share/build.gradle
@@ -0,0 +1,47 @@
+apply plugin: 'com.android.library'
+apply plugin: 'com.novoda.bintray-release'
+
+publish {
+ userOrg = 'yingzi' //bintray注册的用户名
+ groupId = 'vip.devkit' //compile引用时的第1部分groupId
+ artifactId = 'common.share' //compile引用时的第2部分项目名
+ publishVersion = '1.0.8' //compile引用时的第3部分版本号
+ desc = 'This is a androud-utils extend library'
+ website = 'https://github.com/yingzikeji/AndroidUtils'
+ /*
+ * 上传命令
+ * gradlew clean build bintrayUpload -PbintrayUser=yingzi -PbintrayKey=ed9a147c9625f44063e1504a6879b344eb7d76fd -PdryRun=false
+ * */
+}
+android {
+ compileSdkVersion 25
+ buildToolsVersion "25.0.0"
+
+ defaultConfig {
+ minSdkVersion 15
+ targetSdkVersion 25
+ versionCode 1
+ versionName "1.0"
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+ lintOptions {
+ abortOnError false
+ }
+}
+
+dependencies {
+ compile fileTree(include: ['*.jar'], dir: 'libs')
+ testCompile 'junit:junit:4.12'
+ compile 'com.android.support:appcompat-v7:25.0.0'
+ compile 'io.reactivex:rxjava:1.2.3'
+ compile 'io.reactivex:rxandroid:1.2.1'
+ compile 'com.squareup.okhttp3:okhttp:3.4.2'
+ compile 'com.tencent.mm.opensdk:wechat-sdk-android-with-mta:+'
+ compile files('libs/open_sdk_r5990_lite.jar')
+ compile files('libs/weiboSDKCore_3.1.4.jar')
+}
diff --git a/share/libs/open_sdk_r5990_lite.jar b/share/libs/open_sdk_r5990_lite.jar
new file mode 100644
index 0000000..f9e328c
Binary files /dev/null and b/share/libs/open_sdk_r5990_lite.jar differ
diff --git a/share/libs/weiboSDKCore_3.1.4.jar b/share/libs/weiboSDKCore_3.1.4.jar
new file mode 100644
index 0000000..97696ed
Binary files /dev/null and b/share/libs/weiboSDKCore_3.1.4.jar differ
diff --git a/share/proguard-rules.pro b/share/proguard-rules.pro
new file mode 100644
index 0000000..f1b4245
--- /dev/null
+++ b/share/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
diff --git a/share/share.iml b/share/share.iml
new file mode 100644
index 0000000..48f5166
--- /dev/null
+++ b/share/share.iml
@@ -0,0 +1,114 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ generateDebugSources
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/share/src/main/AndroidManifest.xml b/share/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..174c2aa
--- /dev/null
+++ b/share/src/main/AndroidManifest.xml
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/share/src/main/ic_launcher-web.png b/share/src/main/ic_launcher-web.png
new file mode 100644
index 0000000..0de3dec
Binary files /dev/null and b/share/src/main/ic_launcher-web.png differ
diff --git a/share/src/main/java/vip/devkit/common/share/LoginUtil.java b/share/src/main/java/vip/devkit/common/share/LoginUtil.java
new file mode 100644
index 0000000..4b4915b
--- /dev/null
+++ b/share/src/main/java/vip/devkit/common/share/LoginUtil.java
@@ -0,0 +1,110 @@
+package vip.devkit.common.share;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+
+import vip.devkit.common.share.login.LoginListener;
+import vip.devkit.common.share.login.LoginPlatform;
+import vip.devkit.common.share.login.LoginResult;
+import vip.devkit.common.share.login.instance.LoginInstance;
+import vip.devkit.common.share.login.instance.QQLoginInstance;
+import vip.devkit.common.share.login.instance.WeiboLoginInstance;
+import vip.devkit.common.share.login.instance.WxLoginInstance;
+import vip.devkit.common.share.login.result.BaseToken;
+
+public class LoginUtil {
+
+ private static LoginInstance mLoginInstance;
+
+ private static LoginListener mLoginListener;
+
+ private static int mPlatform;
+
+ private static boolean isFetchUserInfo;
+
+ static final int TYPE = 799;
+
+ public static void login(Context context, @LoginPlatform.Platform int platform,
+ LoginListener listener) {
+ login(context, platform, listener, true);
+ }
+
+ public static void login(Context context, @LoginPlatform.Platform int platform,
+ LoginListener listener, boolean fetchUserInfo) {
+ mPlatform = platform;
+ mLoginListener = new LoginListenerProxy(listener);
+ isFetchUserInfo = fetchUserInfo;
+ context.startActivity(_ShareActivity.newInstance(context, TYPE));
+ }
+
+ static void action(Activity activity) {
+ switch (mPlatform) {
+ case LoginPlatform.QQ:
+ mLoginInstance = new QQLoginInstance(activity, mLoginListener, isFetchUserInfo);
+ break;
+ case LoginPlatform.WEIBO:
+ mLoginInstance = new WeiboLoginInstance(activity, mLoginListener, isFetchUserInfo);
+ break;
+ case LoginPlatform.WX:
+ mLoginInstance = new WxLoginInstance(activity, mLoginListener, isFetchUserInfo);
+ break;
+ default:
+ mLoginListener.loginFailure(new Exception(ShareLogger.INFO.UNKNOW_PLATFORM));
+ activity.finish();
+ }
+ mLoginInstance.doLogin(activity, mLoginListener, isFetchUserInfo);
+ }
+
+ static void handleResult(int requestCode, int resultCode, Intent data) {
+ if (mLoginInstance != null) {
+ mLoginInstance.handleResult(requestCode, resultCode, data);
+ }
+ }
+
+ public static void recycle() {
+ if (mLoginInstance != null) {
+ mLoginInstance.recycle();
+ }
+ mLoginInstance = null;
+ mLoginListener = null;
+ mPlatform = 0;
+ isFetchUserInfo = false;
+ }
+
+ private static class LoginListenerProxy extends LoginListener {
+
+ private LoginListener mListener;
+
+ LoginListenerProxy(LoginListener listener) {
+ mListener = listener;
+ }
+
+ @Override
+ public void loginSuccess(LoginResult result) {
+ ShareLogger.i(ShareLogger.INFO.LOGIN_SUCCESS);
+ mListener.loginSuccess(result);
+ recycle();
+ }
+
+ @Override
+ public void loginFailure(Exception e) {
+ ShareLogger.i(ShareLogger.INFO.LOGIN_FAIl);
+ mListener.loginFailure(e);
+ recycle();
+ }
+
+ @Override
+ public void loginCancel() {
+ ShareLogger.i(ShareLogger.INFO.LOGIN_CANCEL);
+ mListener.loginCancel();
+ recycle();
+ }
+
+ @Override
+ public void beforeFetchUserInfo(BaseToken token) {
+ ShareLogger.i(ShareLogger.INFO.LOGIN_AUTH_SUCCESS);
+ mListener.beforeFetchUserInfo(token);
+ }
+ }
+}
diff --git a/share/src/main/java/vip/devkit/common/share/ShareConfig.java b/share/src/main/java/vip/devkit/common/share/ShareConfig.java
new file mode 100644
index 0000000..ff6a5e8
--- /dev/null
+++ b/share/src/main/java/vip/devkit/common/share/ShareConfig.java
@@ -0,0 +1,105 @@
+/*
+******************************* Copyright (c)*********************************\
+**
+** (c) Copyright 2017, DevKit.vip, china, qd. sd
+** All Rights Reserved
+**
+** By(K)
+********************************End of Head************************************\
+*/
+package vip.devkit.common.share;
+
+/**
+ * 文 件 名: ShareConfig
+ * 功能描述:
+ * 创 建 人: By k
+ * 邮 箱:vip@devkit.vip
+ * 网 站:www.devkit.vip
+ * 创建日期: 2018/1/29
+ * 版 本: V 1.0
+ * 代码修改:(修改人 - 修改时间)
+ * 修改备注:
+ */
+public class ShareConfig {
+
+ private String wxId;
+
+ private String wxSecret;
+
+ private String qqId;
+
+ private String weiboId;
+
+ private String weiboRedirectUrl = "https://api.weibo.com/oauth2/default.html";
+
+ private String weiboScope = "email";
+
+ private boolean debug;
+
+ public static ShareConfig instance() {
+ return new ShareConfig();
+ }
+
+ public ShareConfig wxId(String id) {
+ wxId = id;
+ return this;
+ }
+
+ public ShareConfig wxSecret(String id) {
+ wxSecret = id;
+ return this;
+ }
+
+ public ShareConfig qqId(String id) {
+ qqId = id;
+ return this;
+ }
+
+ public ShareConfig weiboId(String id) {
+ weiboId = id;
+ return this;
+ }
+
+ public ShareConfig weiboRedirectUrl(String url) {
+ weiboRedirectUrl = url;
+ return this;
+ }
+
+ public ShareConfig weiboScope(String scope) {
+ weiboScope = scope;
+ return this;
+ }
+
+ public ShareConfig debug(boolean isDebug) {
+ debug = isDebug;
+ return this;
+ }
+
+ public String getWxId() {
+ return wxId;
+ }
+
+ public String getWxSecret() {
+ return wxSecret;
+ }
+
+ public String getQqId() {
+ return qqId;
+ }
+
+ public String getWeiboId() {
+ return weiboId;
+ }
+
+ public String getWeiboRedirectUrl() {
+ return weiboRedirectUrl;
+ }
+
+ public String getWeiboScope() {
+ return weiboScope;
+ }
+
+ public boolean isDebug() {
+ return debug;
+ }
+}
diff --git a/share/src/main/java/vip/devkit/common/share/ShareLogger.java b/share/src/main/java/vip/devkit/common/share/ShareLogger.java
new file mode 100644
index 0000000..0bc83fe
--- /dev/null
+++ b/share/src/main/java/vip/devkit/common/share/ShareLogger.java
@@ -0,0 +1,64 @@
+package vip.devkit.common.share;
+
+import android.util.Log;
+
+
+public class ShareLogger {
+
+ private static final String TAG = "share_util_log";
+
+ public static void i(String info) {
+ if (ShareManager.CONFIG.isDebug()) {
+ Log.i(TAG, info);
+ }
+ }
+
+ public static void e(String error) {
+ if (ShareManager.CONFIG.isDebug()) {
+ Log.e(TAG, error);
+ }
+ }
+
+ public static class INFO {
+ public static final String SHARE_SUCCESS = "call share success";
+ public static final String SHARE_FAILURE = "call share failure";
+ public static final String SHARE_CANCEL = "call share cancel";
+ public static final String SHARE_REQUEST = "call share request";
+
+ // for share
+ public static final String HANDLE_DATA_NULL = "Handle the result, but the data is null, please check you app id";
+ public static final String UNKNOWN_ERROR = "Unknown error";
+ public static final String NOT_INSTALL = "The application is not install";
+ public static final String DEFAULT_QQ_SHARE_ERROR = "QQ share failed";
+ public static final String QQ_NOT_SUPPORT_SHARE_TXT = "QQ not support share text";
+ public static final String IMAGE_FETCH_ERROR = "Image fetch error";
+ public static final String SD_CARD_NOT_AVAILABLE = "The sd card is not available";
+
+ // for login
+ public static final String LOGIN_SUCCESS = "call login success";
+ public static final String LOGIN_FAIl = "call login failed";
+ public static final String LOGIN_CANCEL = "call login cancel";
+ public static final String LOGIN_AUTH_SUCCESS = "call before fetch user info";
+ public static final String ILLEGAL_TOKEN = "Illegal token, please check your config";
+ public static final String QQ_LOGIN_ERROR = "QQ login error";
+ public static final String QQ_AUTH_SUCCESS = "QQ auth success";
+ public static final String WEIBO_AUTH_ERROR = "weibo auth error";
+ public static final String UNKNOW_PLATFORM = "unknown platform";
+
+ public static final String WX_ERR_SENT_FAILED = "Wx sent failed";
+ public static final String WX_ERR_UNSUPPORT = "Wx UnSupport";
+ public static final String WX_ERR_AUTH_DENIED = "Wx auth denied";
+ public static final String WX_ERR_AUTH_ERROR = "Wx auth error";
+
+ public static final String AUTH_CANCEL = "auth cancel";
+ public static final String FETCH_USER_INOF_ERROR = "Fetch user info error";
+
+ // for shareActivity
+ public static final String ACTIVITY_CREATE = "ShareActivity onCreate";
+ public static final String ACTIVITY_RESUME = "ShareActivity onResume";
+ public static final String ACTIVITY_RESULT = "ShareActivity onActivityResult";
+ public static final String ACTIVITY_NEW_INTENT = "ShareActivity onNewIntent";
+
+ }
+
+}
diff --git a/share/src/main/java/vip/devkit/common/share/ShareManager.java b/share/src/main/java/vip/devkit/common/share/ShareManager.java
new file mode 100644
index 0000000..a774408
--- /dev/null
+++ b/share/src/main/java/vip/devkit/common/share/ShareManager.java
@@ -0,0 +1,30 @@
+/*
+******************************* Copyright (c)*********************************\
+**
+** (c) Copyright 2017, DevKit.vip, china, qd. sd
+** All Rights Reserved
+**
+** By(K)
+********************************End of Head************************************\
+*/
+package vip.devkit.common.share;
+
+/**
+ * 文 件 名: ShareManager
+ * 功能描述:
+ * 创 建 人: By k
+ * 邮 箱:vip@devkit.vip
+ * 网 站:www.devkit.vip
+ * 创建日期: 2018/1/29
+ * 版 本: V 1.0
+ * 代码修改:(修改人 - 修改时间)
+ * 修改备注:
+ */
+public class ShareManager {
+ private static boolean isInit = false;
+ public static ShareConfig CONFIG;
+ public static void init(ShareConfig config) {
+ isInit = true;
+ CONFIG = config;
+ }
+}
diff --git a/share/src/main/java/vip/devkit/common/share/ShareUtil.java b/share/src/main/java/vip/devkit/common/share/ShareUtil.java
new file mode 100644
index 0000000..eed4d25
--- /dev/null
+++ b/share/src/main/java/vip/devkit/common/share/ShareUtil.java
@@ -0,0 +1,300 @@
+/*
+******************************* Copyright (c)*********************************\
+**
+** (c) Copyright 2017, DevKit.vip, china, qd. sd
+** All Rights Reserved
+**
+** By(K)
+********************************End of Head************************************\
+*/
+package vip.devkit.common.share;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.graphics.Bitmap;
+import android.support.annotation.NonNull;
+import android.text.TextUtils;
+
+import com.sina.weibo.sdk.api.share.IWeiboShareAPI;
+import com.sina.weibo.sdk.api.share.WeiboShareSDK;
+import com.tencent.mm.opensdk.openapi.IWXAPI;
+import com.tencent.mm.opensdk.openapi.WXAPIFactory;
+
+import java.util.List;
+import java.util.Locale;
+
+import vip.devkit.common.share.share.ShareImageObject;
+import vip.devkit.common.share.share.ShareListener;
+import vip.devkit.common.share.share.SharePlatform;
+import vip.devkit.common.share.share.instance.DefaultShareInstance;
+import vip.devkit.common.share.share.instance.QQShareInstance;
+import vip.devkit.common.share.share.instance.ShareInstance;
+import vip.devkit.common.share.share.instance.WeiboShareInstance;
+import vip.devkit.common.share.share.instance.WxShareInstance;
+
+/**
+ * 文 件 名: ShareUtil
+ * 功能描述:
+ * 创 建 人: By k
+ * 邮 箱:vip@devkit.vip
+ * 网 站:www.devkit.vip
+ * 创建日期: 2018/1/29
+ * 版 本: V 1.0
+ * 代码修改:(修改人 - 修改时间)
+ * 修改备注:
+ */
+public class ShareUtil {
+ /**
+ * 测试case
+ *
+ * 1. 本地图片 vs 网络图片
+ * 2. 图片大小限制
+ * 3. 文字长度限制
+ */
+
+ public static final int TYPE = 798;
+
+ public static ShareListener mShareListener;
+
+ private static ShareInstance mShareInstance;
+
+ private final static int TYPE_IMAGE = 1;
+ private final static int TYPE_TEXT = 2;
+ private final static int TYPE_MEDIA = 3;
+
+ private static int mType;
+ private static int mPlatform;
+ private static String mText;
+ private static ShareImageObject mShareImageObject;
+ private static String mTitle;
+ private static String mSummary;
+ private static String mTargetUrl;
+
+ static void action(Activity activity) {
+ mShareInstance = getShareInstance(mPlatform, activity);
+ // 防止之后调用 NullPointException
+ if (mShareListener == null) {
+ activity.finish();
+ return;
+ }
+
+ if (!mShareInstance.isInstall(activity)) {
+ mShareListener.shareFailure(new Exception(ShareLogger.INFO.NOT_INSTALL));
+ activity.finish();
+ return;
+ }
+
+ switch (mType) {
+ case TYPE_TEXT:
+ mShareInstance.shareText(mPlatform, mText, activity, mShareListener);
+ break;
+ case TYPE_IMAGE:
+ mShareInstance.shareImage(mPlatform, mShareImageObject, activity, mShareListener);
+ break;
+ case TYPE_MEDIA:
+ mShareInstance.shareMedia(mPlatform, mTitle, mTargetUrl, mSummary,
+ mShareImageObject, activity, mShareListener);
+ break;
+ }
+ }
+
+ public static void shareText(Context context, @SharePlatform.Platform int platform, String text,
+ ShareListener listener) {
+ mType = TYPE_TEXT;
+ mText = text;
+ mPlatform = platform;
+ mShareListener = buildProxyListener(listener);
+
+ context.startActivity(_ShareActivity.newInstance(context, TYPE));
+ }
+
+ public static void shareImage(Context context, @SharePlatform.Platform final int platform,
+ final String urlOrPath, ShareListener listener) {
+ mType = TYPE_IMAGE;
+ mPlatform = platform;
+ mShareImageObject = new ShareImageObject(urlOrPath);
+ mShareListener = buildProxyListener(listener);
+
+ context.startActivity(_ShareActivity.newInstance(context, TYPE));
+ }
+
+ public static void shareImage(Context context, @SharePlatform.Platform final int platform,
+ final Bitmap bitmap, ShareListener listener) {
+ mType = TYPE_IMAGE;
+ mPlatform = platform;
+ mShareImageObject = new ShareImageObject(bitmap);
+ mShareListener = buildProxyListener(listener);
+
+ context.startActivity(_ShareActivity.newInstance(context, TYPE));
+ }
+
+ public static void shareMedia(Context context, @SharePlatform.Platform int platform,
+ String title, String summary, String targetUrl, Bitmap thumb, ShareListener listener) {
+ mType = TYPE_MEDIA;
+ mPlatform = platform;
+ mShareImageObject = new ShareImageObject(thumb);
+ mSummary = summary;
+ mTargetUrl = targetUrl;
+ mTitle = title;
+ mShareListener = buildProxyListener(listener);
+
+ context.startActivity(_ShareActivity.newInstance(context, TYPE));
+ }
+
+ public static void shareMedia(Context context, @SharePlatform.Platform int platform,
+ String title, String summary, String targetUrl, String thumbUrlOrPath,
+ ShareListener listener) {
+ mType = TYPE_MEDIA;
+ mPlatform = platform;
+ mShareImageObject = new ShareImageObject(thumbUrlOrPath);
+ mSummary = summary;
+ mTargetUrl = targetUrl;
+ mTitle = title;
+ mShareListener = buildProxyListener(listener);
+
+ context.startActivity(_ShareActivity.newInstance(context, TYPE));
+ }
+
+ private static ShareListener buildProxyListener(ShareListener listener) {
+ return new ShareListenerProxy(listener);
+ }
+
+ public static void handleResult(Intent data) {
+ // 微博分享会同时回调onActivityResult和onNewIntent, 而且前者返回的intent为null
+ if (mShareInstance != null && data != null) {
+ mShareInstance.handleResult(data);
+ } else if (data == null) {
+ if (mPlatform != SharePlatform.WEIBO) {
+ ShareLogger.e(ShareLogger.INFO.HANDLE_DATA_NULL);
+ }
+ } else {
+ ShareLogger.e(ShareLogger.INFO.UNKNOWN_ERROR);
+ }
+ }
+
+ private static ShareInstance getShareInstance(@SharePlatform.Platform int platform,
+ Context context) {
+ switch (platform) {
+ case SharePlatform.WX:
+ case SharePlatform.WX_TIMELINE:
+ return new WxShareInstance(context, ShareManager.CONFIG.getWxId());
+ case SharePlatform.QQ:
+ case SharePlatform.QZONE:
+ return new QQShareInstance(context, ShareManager.CONFIG.getQqId());
+ case SharePlatform.WEIBO:
+ return new WeiboShareInstance(context, ShareManager.CONFIG.getWeiboId());
+ case SharePlatform.DEFAULT:
+ default:
+ return new DefaultShareInstance();
+ }
+ }
+
+ public static void recycle() {
+ mTitle = null;
+ mSummary = null;
+ mShareListener = null;
+
+ // bitmap recycle
+ if (mShareImageObject != null
+ && mShareImageObject.getBitmap() != null
+ && !mShareImageObject.getBitmap().isRecycled()) {
+ mShareImageObject.getBitmap().recycle();
+ }
+ mShareImageObject = null;
+
+ if (mShareInstance != null) {
+ mShareInstance.recycle();
+ }
+ mShareInstance = null;
+ }
+
+ /**
+ * 检查客户端是否安装
+ */
+
+ public static boolean isInstalled(@SharePlatform.Platform int platform, Context context) {
+ switch (platform) {
+ case SharePlatform.QQ:
+ case SharePlatform.QZONE:
+ return isQQInstalled(context);
+ case SharePlatform.WEIBO:
+ return isWeiBoInstalled(context);
+ case SharePlatform.WX:
+ case SharePlatform.WX_TIMELINE:
+ return isWeiXinInstalled(context);
+ case SharePlatform.DEFAULT:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ @Deprecated
+ public static boolean isQQInstalled(@NonNull Context context) {
+ PackageManager pm = context.getPackageManager();
+ if (pm == null) {
+ return false;
+ }
+
+ List packageInfos = pm.getInstalledPackages(0);
+ for (PackageInfo info : packageInfos) {
+ if (TextUtils.equals(info.packageName.toLowerCase(Locale.getDefault()),
+ "com.tencent.mobileqq")) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Deprecated
+ public static boolean isWeiBoInstalled(@NonNull Context context) {
+ IWeiboShareAPI shareAPI =
+ WeiboShareSDK.createWeiboAPI(context, ShareManager.CONFIG.getWeiboId());
+ return shareAPI.isWeiboAppInstalled();
+ }
+
+ @Deprecated
+ public static boolean isWeiXinInstalled(Context context) {
+ IWXAPI api = WXAPIFactory.createWXAPI(context, ShareManager.CONFIG.getWxId(), true);
+ return api.isWXAppInstalled();
+ }
+
+ private static class ShareListenerProxy extends ShareListener {
+
+ private final ShareListener mShareListener;
+
+ ShareListenerProxy(ShareListener listener) {
+ mShareListener = listener;
+ }
+
+ @Override
+ public void shareSuccess() {
+ ShareLogger.i(ShareLogger.INFO.SHARE_SUCCESS);
+ ShareUtil.recycle();
+ mShareListener.shareSuccess();
+ }
+
+ @Override
+ public void shareFailure(Exception e) {
+ ShareLogger.i(ShareLogger.INFO.SHARE_FAILURE);
+ ShareUtil.recycle();
+ mShareListener.shareFailure(e);
+ }
+
+ @Override
+ public void shareCancel() {
+ ShareLogger.i(ShareLogger.INFO.SHARE_CANCEL);
+ ShareUtil.recycle();
+ mShareListener.shareCancel();
+ }
+
+ @Override
+ public void shareRequest() {
+ ShareLogger.i(ShareLogger.INFO.SHARE_REQUEST);
+ mShareListener.shareRequest();
+ }
+ }
+}
diff --git a/share/src/main/java/vip/devkit/common/share/_ShareActivity.java b/share/src/main/java/vip/devkit/common/share/_ShareActivity.java
new file mode 100644
index 0000000..bfa6078
--- /dev/null
+++ b/share/src/main/java/vip/devkit/common/share/_ShareActivity.java
@@ -0,0 +1,87 @@
+package vip.devkit.common.share;
+
+import android.app.Activity;
+import android.app.Application;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import vip.devkit.common.share.ShareLogger.INFO;
+
+
+public class _ShareActivity extends Activity {
+
+ private int mType;
+
+ private boolean isNew;
+
+ private static final String TYPE = "share_activity_type";
+
+ public static Intent newInstance(Context context, int type) {
+ Intent intent = new Intent(context, _ShareActivity.class);
+ if (context instanceof Application) {
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ }
+ intent.putExtra(TYPE, type);
+ return intent;
+ }
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ ShareLogger.i(INFO.ACTIVITY_CREATE);
+ isNew = true;
+
+ // init data
+ mType = getIntent().getIntExtra(TYPE, 0);
+ if (mType == ShareUtil.TYPE) {
+ // 分享
+ ShareUtil.action(this);
+ } else if (mType == LoginUtil.TYPE) {
+ // 登录
+ LoginUtil.action(this);
+ } else {
+ // handle 微信回调
+ LoginUtil.handleResult(-1, -1, getIntent());
+ ShareUtil.handleResult(getIntent());
+ finish();
+ }
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ ShareLogger.i(INFO.ACTIVITY_RESUME);
+ if (isNew) {
+ isNew = false;
+ } else {
+ finish();
+ }
+ }
+
+ @Override
+ protected void onNewIntent(Intent intent) {
+ super.onNewIntent(intent);
+ ShareLogger.i(INFO.ACTIVITY_NEW_INTENT);
+ // 处理回调
+ if (mType == LoginUtil.TYPE) {
+ LoginUtil.handleResult(0, 0, intent);
+ } else if (mType == ShareUtil.TYPE) {
+ ShareUtil.handleResult(intent);
+ }
+ finish();
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ ShareLogger.i(INFO.ACTIVITY_RESULT);
+ // 处理回调
+ if (mType == LoginUtil.TYPE) {
+ LoginUtil.handleResult(requestCode, resultCode, data);
+ } else if (mType == ShareUtil.TYPE) {
+ ShareUtil.handleResult(data);
+ }
+ finish();
+ }
+}
diff --git a/share/src/main/java/vip/devkit/common/share/login/LoginListener.java b/share/src/main/java/vip/devkit/common/share/login/LoginListener.java
new file mode 100644
index 0000000..5785bc5
--- /dev/null
+++ b/share/src/main/java/vip/devkit/common/share/login/LoginListener.java
@@ -0,0 +1,35 @@
+/*
+******************************* Copyright (c)*********************************\
+**
+** (c) Copyright 2017, DevKit.vip, china, qd. sd
+** All Rights Reserved
+**
+** By(K)
+********************************End of Head************************************\
+*/
+package vip.devkit.common.share.login;
+
+import vip.devkit.common.share.login.result.BaseToken;
+
+/**
+ * 文 件 名: LoginListener
+ * 功能描述:
+ * 创 建 人: By k
+ * 邮 箱:vip@devkit.vip
+ * 网 站:www.devkit.vip
+ * 创建日期: 2018/1/29
+ * 版 本: V 1.0
+ * 代码修改:(修改人 - 修改时间)
+ * 修改备注:
+ */
+public abstract class LoginListener {
+
+ public abstract void loginSuccess(LoginResult result);
+
+ public void beforeFetchUserInfo(BaseToken token) {
+ }
+
+ public abstract void loginFailure(Exception e);
+
+ public abstract void loginCancel();
+}
diff --git a/share/src/main/java/vip/devkit/common/share/login/LoginPlatform.java b/share/src/main/java/vip/devkit/common/share/login/LoginPlatform.java
new file mode 100644
index 0000000..0a313b5
--- /dev/null
+++ b/share/src/main/java/vip/devkit/common/share/login/LoginPlatform.java
@@ -0,0 +1,26 @@
+package vip.devkit.common.share.login;
+
+import android.support.annotation.IntDef;
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+
+public class LoginPlatform {
+
+ @Documented
+ @IntDef({QQ, WX, WEIBO})
+ @Retention(RetentionPolicy.SOURCE)
+ @Target(ElementType.PARAMETER)
+ public @interface Platform {
+
+ }
+
+ public static final int QQ = 1;
+
+ public static final int WX = 3;
+
+ public static final int WEIBO = 5;
+}
diff --git a/share/src/main/java/vip/devkit/common/share/login/LoginResult.java b/share/src/main/java/vip/devkit/common/share/login/LoginResult.java
new file mode 100644
index 0000000..e838767
--- /dev/null
+++ b/share/src/main/java/vip/devkit/common/share/login/LoginResult.java
@@ -0,0 +1,49 @@
+package vip.devkit.common.share.login;
+
+
+import vip.devkit.common.share.login.result.BaseToken;
+import vip.devkit.common.share.login.result.BaseUser;
+
+public class LoginResult {
+
+ private BaseToken mToken;
+
+ private BaseUser mUserInfo;
+
+ private int mPlatform;
+
+ public LoginResult(int platform, BaseToken token) {
+ mPlatform = platform;
+ mToken = token;
+ }
+
+ public LoginResult(int platform, BaseToken token, BaseUser userInfo) {
+ mPlatform = platform;
+ mToken = token;
+ mUserInfo = userInfo;
+ }
+
+ public int getPlatform() {
+ return mPlatform;
+ }
+
+ public void setPlatform(int platform) {
+ this.mPlatform = platform;
+ }
+
+ public BaseToken getToken() {
+ return mToken;
+ }
+
+ public void setToken(BaseToken token) {
+ mToken = token;
+ }
+
+ public BaseUser getUserInfo() {
+ return mUserInfo;
+ }
+
+ public void setUserInfo(BaseUser userInfo) {
+ mUserInfo = userInfo;
+ }
+}
diff --git a/share/src/main/java/vip/devkit/common/share/login/instance/LoginInstance.java b/share/src/main/java/vip/devkit/common/share/login/instance/LoginInstance.java
new file mode 100644
index 0000000..e14ac59
--- /dev/null
+++ b/share/src/main/java/vip/devkit/common/share/login/instance/LoginInstance.java
@@ -0,0 +1,26 @@
+package vip.devkit.common.share.login.instance;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+
+import vip.devkit.common.share.login.LoginListener;
+import vip.devkit.common.share.login.result.BaseToken;
+
+
+public abstract class LoginInstance {
+
+ public LoginInstance(Activity activity, LoginListener listener, boolean fetchUserInfo) {
+
+ }
+
+ public abstract void doLogin(Activity activity, LoginListener listener, boolean fetchUserInfo);
+
+ public abstract void fetchUserInfo(BaseToken token);
+
+ public abstract void handleResult(int requestCode, int resultCode, Intent data);
+
+ public abstract boolean isInstall(Context context);
+
+ public abstract void recycle();
+}
diff --git a/share/src/main/java/vip/devkit/common/share/login/instance/QQLoginInstance.java b/share/src/main/java/vip/devkit/common/share/login/instance/QQLoginInstance.java
new file mode 100644
index 0000000..e6092d4
--- /dev/null
+++ b/share/src/main/java/vip/devkit/common/share/login/instance/QQLoginInstance.java
@@ -0,0 +1,167 @@
+package vip.devkit.common.share.login.instance;
+
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.text.TextUtils;
+
+import com.tencent.tauth.IUiListener;
+import com.tencent.tauth.Tencent;
+import com.tencent.tauth.UiError;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.IOException;
+import java.util.List;
+
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+import rx.Emitter;
+import rx.Observable;
+import rx.android.schedulers.AndroidSchedulers;
+import rx.functions.Action1;
+import rx.schedulers.Schedulers;
+import vip.devkit.common.share.ShareLogger;
+import vip.devkit.common.share.ShareManager;
+import vip.devkit.common.share.login.LoginListener;
+import vip.devkit.common.share.login.LoginPlatform;
+import vip.devkit.common.share.login.LoginResult;
+import vip.devkit.common.share.login.result.BaseToken;
+import vip.devkit.common.share.login.result.QQToken;
+import vip.devkit.common.share.login.result.QQUser;
+
+public class QQLoginInstance extends LoginInstance {
+
+ private static final String SCOPE = "get_simple_userinfo";
+
+ private static final String URL = "https://graph.qq.com/user/get_user_info";
+
+ private Tencent mTencent;
+
+ private IUiListener mIUiListener;
+
+ private LoginListener mLoginListener;
+
+ public QQLoginInstance(Activity activity, final LoginListener listener,
+ final boolean fetchUserInfo) {
+ super(activity, listener, fetchUserInfo);
+ mTencent = Tencent.createInstance(ShareManager.CONFIG.getQqId(),
+ activity.getApplicationContext());
+ mLoginListener = listener;
+ mIUiListener = new IUiListener() {
+ @Override
+ public void onComplete(Object o) {
+ ShareLogger.i(ShareLogger.INFO.QQ_AUTH_SUCCESS);
+ try {
+ QQToken token = QQToken.parse((JSONObject) o);
+ if (fetchUserInfo) {
+ listener.beforeFetchUserInfo(token);
+ fetchUserInfo(token);
+ } else {
+ listener.loginSuccess(new LoginResult(LoginPlatform.QQ, token));
+ }
+ } catch (JSONException e) {
+ ShareLogger.i(ShareLogger.INFO.ILLEGAL_TOKEN);
+ mLoginListener.loginFailure(e);
+ }
+ }
+
+ @Override
+ public void onError(UiError uiError) {
+ ShareLogger.i(ShareLogger.INFO.QQ_LOGIN_ERROR);
+ listener.loginFailure(
+ new Exception("QQError: " + uiError.errorCode + uiError.errorDetail));
+ }
+
+ @Override
+ public void onCancel() {
+ ShareLogger.i(ShareLogger.INFO.AUTH_CANCEL);
+ listener.loginCancel();
+ }
+ };
+ }
+
+ @Override
+ public void doLogin(Activity activity, final LoginListener listener, boolean fetchUserInfo) {
+ mTencent.login(activity, SCOPE, mIUiListener);
+ }
+
+ @Override
+ public void fetchUserInfo(final BaseToken token) {
+ Observable.fromEmitter(new Action1>() {
+ @Override
+ public void call(Emitter qqUserEmitter) {
+ OkHttpClient client = new OkHttpClient();
+ Request request = new Request.Builder().url(buildUserInfoUrl(token, URL)).build();
+
+ try {
+ Response response = client.newCall(request).execute();
+ JSONObject jsonObject = new JSONObject(response.body().string());
+ QQUser user = QQUser.parse(token.getOpenid(), jsonObject);
+ qqUserEmitter.onNext(user);
+ } catch (IOException | JSONException e) {
+ ShareLogger.e(ShareLogger.INFO.FETCH_USER_INOF_ERROR);
+ qqUserEmitter.onError(e);
+ }
+ }
+ }, Emitter.BackpressureMode.DROP)
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(new Action1() {
+ @Override
+ public void call(QQUser qqUser) {
+ mLoginListener.loginSuccess(
+ new LoginResult(LoginPlatform.QQ, token, qqUser));
+ }
+ }, new Action1() {
+ @Override
+ public void call(Throwable throwable) {
+ mLoginListener.loginFailure(new Exception(throwable));
+ }
+ });
+ }
+
+ private String buildUserInfoUrl(BaseToken token, String base) {
+ return base
+ + "?access_token="
+ + token.getAccessToken()
+ + "&oauth_consumer_key="
+ + ShareManager.CONFIG.getQqId()
+ + "&openid="
+ + token.getOpenid();
+ }
+
+ @Override
+ public void handleResult(int requestCode, int resultCode, Intent data) {
+ Tencent.handleResultData(data, mIUiListener);
+ }
+
+ @Override
+ public boolean isInstall(Context context) {
+ PackageManager pm = context.getPackageManager();
+ if (pm == null) {
+ return false;
+ }
+
+ List packageInfos = pm.getInstalledPackages(0);
+ for (PackageInfo info : packageInfos) {
+ if (TextUtils.equals(info.packageName.toLowerCase(), "com.tencent.mobileqq")) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void recycle() {
+ mTencent.releaseResource();
+ mIUiListener = null;
+ mLoginListener = null;
+ mTencent = null;
+ }
+}
diff --git a/share/src/main/java/vip/devkit/common/share/login/instance/WeiboLoginInstance.java b/share/src/main/java/vip/devkit/common/share/login/instance/WeiboLoginInstance.java
new file mode 100644
index 0000000..402abd1
--- /dev/null
+++ b/share/src/main/java/vip/devkit/common/share/login/instance/WeiboLoginInstance.java
@@ -0,0 +1,139 @@
+package vip.devkit.common.share.login.instance;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import com.sina.weibo.sdk.api.share.IWeiboShareAPI;
+import com.sina.weibo.sdk.api.share.WeiboShareSDK;
+import com.sina.weibo.sdk.auth.AuthInfo;
+import com.sina.weibo.sdk.auth.Oauth2AccessToken;
+import com.sina.weibo.sdk.auth.WeiboAuthListener;
+import com.sina.weibo.sdk.auth.sso.SsoHandler;
+import com.sina.weibo.sdk.exception.WeiboException;
+import java.io.IOException;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+import org.json.JSONException;
+import org.json.JSONObject;
+import rx.Emitter;
+import rx.Observable;
+import rx.android.schedulers.AndroidSchedulers;
+import rx.functions.Action1;
+import rx.schedulers.Schedulers;
+import vip.devkit.common.share.ShareLogger;
+import vip.devkit.common.share.ShareManager;
+import vip.devkit.common.share.login.LoginListener;
+import vip.devkit.common.share.login.LoginPlatform;
+import vip.devkit.common.share.login.LoginResult;
+import vip.devkit.common.share.login.result.BaseToken;
+import vip.devkit.common.share.login.result.WeiboToken;
+import vip.devkit.common.share.login.result.WeiboUser;
+
+import static vip.devkit.common.share.ShareLogger.INFO;
+
+
+public class WeiboLoginInstance extends LoginInstance {
+
+ private static final String USER_INFO = "https://api.weibo.com/2/users/show.json";
+
+ private SsoHandler mSsoHandler;
+
+ private LoginListener mLoginListener;
+
+ public WeiboLoginInstance(Activity activity, LoginListener listener, boolean fetchUserInfo) {
+ super(activity, listener, fetchUserInfo);
+ AuthInfo authInfo = new AuthInfo(activity, ShareManager.CONFIG.getWeiboId(),
+ ShareManager.CONFIG.getWeiboRedirectUrl(), ShareManager.CONFIG.getWeiboScope());
+ mSsoHandler = new SsoHandler(activity, authInfo);
+ mLoginListener = listener;
+ }
+
+ @Override
+ public void doLogin(Activity activity, final LoginListener listener,
+ final boolean fetchUserInfo) {
+ mSsoHandler.authorize(new WeiboAuthListener() {
+ @Override
+ public void onComplete(Bundle bundle) {
+ Oauth2AccessToken accessToken = Oauth2AccessToken.parseAccessToken(bundle);
+ WeiboToken weiboToken = WeiboToken.parse(accessToken);
+ if (fetchUserInfo) {
+ listener.beforeFetchUserInfo(weiboToken);
+ fetchUserInfo(weiboToken);
+ } else {
+ listener.loginSuccess(new LoginResult(LoginPlatform.WEIBO, weiboToken));
+ }
+ }
+
+ @Override
+ public void onWeiboException(WeiboException e) {
+ ShareLogger.i(INFO.WEIBO_AUTH_ERROR);
+ listener.loginFailure(e);
+ }
+
+ @Override
+ public void onCancel() {
+ ShareLogger.i(INFO.AUTH_CANCEL);
+ listener.loginCancel();
+ }
+ });
+ }
+
+ @Override
+ public void fetchUserInfo(final BaseToken token) {
+ Observable.fromEmitter(new Action1>() {
+ @Override
+ public void call(Emitter weiboUserEmitter) {
+ OkHttpClient client = new OkHttpClient();
+ Request request =
+ new Request.Builder().url(buildUserInfoUrl(token, USER_INFO)).build();
+ try {
+ Response response = client.newCall(request).execute();
+ JSONObject jsonObject = new JSONObject(response.body().string());
+ WeiboUser user = WeiboUser.parse(jsonObject);
+ weiboUserEmitter.onNext(user);
+ } catch (IOException | JSONException e) {
+ ShareLogger.e(INFO.FETCH_USER_INOF_ERROR);
+ weiboUserEmitter.onError(e);
+ }
+ }
+ }, Emitter.BackpressureMode.DROP)
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(new Action1() {
+ @Override
+ public void call(WeiboUser weiboUser) {
+ mLoginListener.loginSuccess(
+ new LoginResult(LoginPlatform.WEIBO, token, weiboUser));
+ }
+ }, new Action1() {
+ @Override
+ public void call(Throwable throwable) {
+ mLoginListener.loginFailure(new Exception(throwable));
+ }
+ });
+ }
+
+ private String buildUserInfoUrl(BaseToken token, String baseUrl) {
+ return baseUrl + "?access_token=" + token.getAccessToken() + "&uid=" + token.getOpenid();
+ }
+
+ @Override
+ public void handleResult(int requestCode, int resultCode, Intent data) {
+ mSsoHandler.authorizeCallBack(requestCode, resultCode, data);
+ }
+
+ @Override
+ public boolean isInstall(Context context) {
+ IWeiboShareAPI shareAPI =
+ WeiboShareSDK.createWeiboAPI(context, ShareManager.CONFIG.getWeiboId());
+ return shareAPI.isWeiboAppInstalled();
+ }
+
+ @Override
+ public void recycle() {
+ mSsoHandler = null;
+ mLoginListener = null;
+ }
+}
diff --git a/share/src/main/java/vip/devkit/common/share/login/instance/WxLoginInstance.java b/share/src/main/java/vip/devkit/common/share/login/instance/WxLoginInstance.java
new file mode 100644
index 0000000..4e2f4e2
--- /dev/null
+++ b/share/src/main/java/vip/devkit/common/share/login/instance/WxLoginInstance.java
@@ -0,0 +1,199 @@
+package vip.devkit.common.share.login.instance;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+
+import com.tencent.mm.opensdk.modelbase.BaseReq;
+import com.tencent.mm.opensdk.modelbase.BaseResp;
+import com.tencent.mm.opensdk.modelmsg.SendAuth;
+import com.tencent.mm.opensdk.openapi.IWXAPI;
+import com.tencent.mm.opensdk.openapi.IWXAPIEventHandler;
+import com.tencent.mm.opensdk.openapi.WXAPIFactory;
+
+import java.io.IOException;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+import rx.Emitter;
+import rx.Observable;
+import rx.android.schedulers.AndroidSchedulers;
+import rx.functions.Action1;
+import rx.schedulers.Schedulers;
+import vip.devkit.common.share.ShareLogger;
+import vip.devkit.common.share.ShareManager;
+import vip.devkit.common.share.login.LoginListener;
+import vip.devkit.common.share.login.LoginPlatform;
+import vip.devkit.common.share.login.LoginResult;
+import vip.devkit.common.share.login.result.BaseToken;
+import vip.devkit.common.share.login.result.WxToken;
+import vip.devkit.common.share.login.result.WxUser;
+import vip.devkit.common.share.ShareLogger.INFO;
+
+public class WxLoginInstance extends LoginInstance {
+
+ public static final String SCOPE_USER_INFO = "snsapi_userinfo";
+ private static final String SCOPE_BASE = "snsapi_base";
+
+ private static final String BASE_URL = "https://api.weixin.qq.com/sns/";
+
+ private IWXAPI mIWXAPI;
+
+ private LoginListener mLoginListener;
+
+ private OkHttpClient mClient;
+
+ private boolean fetchUserInfo;
+
+ public WxLoginInstance(Activity activity, LoginListener listener, boolean fetchUserInfo) {
+ super(activity, listener, fetchUserInfo);
+ mLoginListener = listener;
+ mIWXAPI = WXAPIFactory.createWXAPI(activity, ShareManager.CONFIG.getWxId());
+ mClient = new OkHttpClient();
+ this.fetchUserInfo = fetchUserInfo;
+ }
+
+ @Override
+ public void doLogin(Activity activity, LoginListener listener, boolean fetchUserInfo) {
+ final SendAuth.Req req = new SendAuth.Req();
+ req.scope = SCOPE_USER_INFO;
+ req.state = String.valueOf(System.currentTimeMillis());
+ mIWXAPI.sendReq(req);
+ }
+
+ private void getToken(final String code) {
+ Observable.fromEmitter(new Action1>() {
+ @Override
+ public void call(Emitter wxTokenEmitter) {
+ Request request = new Request.Builder().url(buildTokenUrl(code)).build();
+ try {
+ Response response = mClient.newCall(request).execute();
+ JSONObject jsonObject = new JSONObject(response.body().string());
+ WxToken token = WxToken.parse(jsonObject);
+ wxTokenEmitter.onNext(token);
+ } catch (IOException | JSONException e) {
+ wxTokenEmitter.onError(e);
+ }
+ }
+ }, Emitter.BackpressureMode.DROP)
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(new Action1() {
+ @Override
+ public void call(WxToken wxToken) {
+ if (fetchUserInfo) {
+ mLoginListener.beforeFetchUserInfo(wxToken);
+ fetchUserInfo(wxToken);
+ } else {
+ mLoginListener.loginSuccess(new LoginResult(LoginPlatform.WX, wxToken));
+ }
+ }
+ }, new Action1() {
+ @Override
+ public void call(Throwable throwable) {
+ mLoginListener.loginFailure(new Exception(throwable.getMessage()));
+ }
+ });
+ }
+
+ @Override
+ public void fetchUserInfo(final BaseToken token) {
+ Observable.fromEmitter(new Action1>() {
+ @Override
+ public void call(Emitter wxUserEmitter) {
+ Request request = new Request.Builder().url(buildUserInfoUrl(token)).build();
+ try {
+ Response response = mClient.newCall(request).execute();
+ JSONObject jsonObject = new JSONObject(response.body().string());
+ WxUser user = WxUser.parse(jsonObject);
+ wxUserEmitter.onNext(user);
+ } catch (IOException | JSONException e) {
+ wxUserEmitter.onError(e);
+ }
+ }
+ }, Emitter.BackpressureMode.DROP)
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(new Action1() {
+ @Override
+ public void call(WxUser wxUser) {
+ mLoginListener.loginSuccess(
+ new LoginResult(LoginPlatform.WX, token, wxUser));
+ }
+ }, new Action1() {
+ @Override
+ public void call(Throwable throwable) {
+ mLoginListener.loginFailure(new Exception(throwable));
+ }
+ });
+ }
+
+ @Override
+ public void handleResult(int requestCode, int resultCode, Intent data) {
+ mIWXAPI.handleIntent(data, new IWXAPIEventHandler() {
+ @Override
+ public void onReq(BaseReq baseReq) {
+ }
+
+ @Override
+ public void onResp(BaseResp baseResp) {
+ if (baseResp instanceof SendAuth.Resp && baseResp.getType() == 1) {
+ SendAuth.Resp resp = (SendAuth.Resp) baseResp;
+ switch (resp.errCode) {
+ case BaseResp.ErrCode.ERR_OK:
+ getToken(resp.code);
+ break;
+ case BaseResp.ErrCode.ERR_USER_CANCEL:
+ mLoginListener.loginCancel();
+ break;
+ case BaseResp.ErrCode.ERR_SENT_FAILED:
+ mLoginListener.loginFailure(new Exception(ShareLogger.INFO.WX_ERR_SENT_FAILED));
+ break;
+ case BaseResp.ErrCode.ERR_UNSUPPORT:
+ mLoginListener.loginFailure(new Exception(ShareLogger.INFO.WX_ERR_UNSUPPORT));
+ break;
+ case BaseResp.ErrCode.ERR_AUTH_DENIED:
+ mLoginListener.loginFailure(new Exception(INFO.WX_ERR_AUTH_DENIED));
+ break;
+ default:
+ mLoginListener.loginFailure(new Exception(INFO.WX_ERR_AUTH_ERROR));
+ }
+ }
+ }
+ });
+ }
+
+ @Override
+ public boolean isInstall(Context context) {
+ return mIWXAPI.isWXAppInstalled();
+ }
+
+ @Override
+ public void recycle() {
+ if (mIWXAPI != null) {
+ mIWXAPI.detach();
+ }
+ }
+
+ private String buildTokenUrl(String code) {
+ return BASE_URL
+ + "oauth2/access_token?appid="
+ + ShareManager.CONFIG.getWxId()
+ + "&secret="
+ + ShareManager.CONFIG.getWxSecret()
+ + "&code="
+ + code
+ + "&grant_type=authorization_code";
+ }
+
+ private String buildUserInfoUrl(BaseToken token) {
+ return BASE_URL
+ + "userinfo?access_token="
+ + token.getAccessToken()
+ + "&openid="
+ + token.getOpenid();
+ }
+}
diff --git a/share/src/main/java/vip/devkit/common/share/login/result/BaseToken.java b/share/src/main/java/vip/devkit/common/share/login/result/BaseToken.java
new file mode 100644
index 0000000..01338e3
--- /dev/null
+++ b/share/src/main/java/vip/devkit/common/share/login/result/BaseToken.java
@@ -0,0 +1,25 @@
+package vip.devkit.common.share.login.result;
+
+
+public class BaseToken {
+
+ private String access_token;
+
+ private String openid;
+
+ public String getAccessToken() {
+ return access_token;
+ }
+
+ public void setAccessToken(String access_token) {
+ this.access_token = access_token;
+ }
+
+ public String getOpenid() {
+ return openid;
+ }
+
+ public void setOpenid(String openid) {
+ this.openid = openid;
+ }
+}
diff --git a/share/src/main/java/vip/devkit/common/share/login/result/BaseUser.java b/share/src/main/java/vip/devkit/common/share/login/result/BaseUser.java
new file mode 100644
index 0000000..5cafc71
--- /dev/null
+++ b/share/src/main/java/vip/devkit/common/share/login/result/BaseUser.java
@@ -0,0 +1,62 @@
+package vip.devkit.common.share.login.result;
+
+
+public class BaseUser {
+
+ /**
+ * sex
+ * 0. 未知
+ * 1. 男
+ * 2. 女
+ */
+
+ private String openId;
+
+ private String nickname;
+
+ private int sex;
+
+ private String headImageUrl;
+
+ private String headImageUrlLarge;
+
+ public String getOpenId() {
+ return openId;
+ }
+
+ public void setOpenId(String openId) {
+ this.openId = openId;
+ }
+
+ public String getNickname() {
+ return nickname;
+ }
+
+ public void setNickname(String nickname) {
+ this.nickname = nickname;
+ }
+
+ public int getSex() {
+ return sex;
+ }
+
+ public void setSex(int sex) {
+ this.sex = sex;
+ }
+
+ public String getHeadImageUrl() {
+ return headImageUrl;
+ }
+
+ public void setHeadImageUrl(String headImageUrl) {
+ this.headImageUrl = headImageUrl;
+ }
+
+ public String getHeadImageUrlLarge() {
+ return headImageUrlLarge;
+ }
+
+ public void setHeadImageUrlLarge(String headImageUrlLarge) {
+ this.headImageUrlLarge = headImageUrlLarge;
+ }
+}
diff --git a/share/src/main/java/vip/devkit/common/share/login/result/QQToken.java b/share/src/main/java/vip/devkit/common/share/login/result/QQToken.java
new file mode 100644
index 0000000..48034f6
--- /dev/null
+++ b/share/src/main/java/vip/devkit/common/share/login/result/QQToken.java
@@ -0,0 +1,16 @@
+package vip.devkit.common.share.login.result;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+
+public class QQToken extends BaseToken {
+
+ public static QQToken parse(JSONObject jsonObject) throws JSONException {
+ QQToken token = new QQToken();
+ token.setAccessToken(jsonObject.getString("access_token"));
+ token.setOpenid(jsonObject.getString("openid"));
+ return token;
+ }
+
+}
diff --git a/share/src/main/java/vip/devkit/common/share/login/result/QQUser.java b/share/src/main/java/vip/devkit/common/share/login/result/QQUser.java
new file mode 100644
index 0000000..45e70b3
--- /dev/null
+++ b/share/src/main/java/vip/devkit/common/share/login/result/QQUser.java
@@ -0,0 +1,41 @@
+package vip.devkit.common.share.login.result;
+
+import android.text.TextUtils;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+public class QQUser extends BaseUser {
+
+ private String qZoneHeadImage;
+
+ private String qZoneHeadImageLarge;
+
+ public static QQUser parse(String openId, JSONObject jsonObject) throws JSONException {
+ QQUser user = new QQUser();
+ user.setNickname(jsonObject.getString("nickname"));
+ user.setOpenId(openId);
+ user.setSex(TextUtils.equals("男", jsonObject.getString("gender")) ? 1 : 2);
+ user.setHeadImageUrl(jsonObject.getString("figureurl_qq_1"));
+ user.setHeadImageUrlLarge(jsonObject.getString("figureurl_qq_2"));
+ user.setqZoneHeadImage(jsonObject.getString("figureurl_1"));
+ user.setqZoneHeadImageLarge(jsonObject.getString("figureurl_2"));
+
+ return user;
+ }
+
+ public String getqZoneHeadImage() {
+ return qZoneHeadImage;
+ }
+
+ public void setqZoneHeadImage(String qZoneHeadImage) {
+ this.qZoneHeadImage = qZoneHeadImage;
+ }
+
+ public String getqZoneHeadImageLarge() {
+ return qZoneHeadImageLarge;
+ }
+
+ public void setqZoneHeadImageLarge(String qZoneHeadImageLarge) {
+ this.qZoneHeadImageLarge = qZoneHeadImageLarge;
+ }
+}
diff --git a/share/src/main/java/vip/devkit/common/share/login/result/WeiboToken.java b/share/src/main/java/vip/devkit/common/share/login/result/WeiboToken.java
new file mode 100644
index 0000000..94361b1
--- /dev/null
+++ b/share/src/main/java/vip/devkit/common/share/login/result/WeiboToken.java
@@ -0,0 +1,39 @@
+package vip.devkit.common.share.login.result;
+
+import com.sina.weibo.sdk.auth.Oauth2AccessToken;
+
+/**
+ * Created by shaohui on 2016/12/3.
+ */
+
+public class WeiboToken extends BaseToken {
+
+ private String refreshToken;
+
+ private String phoneNum;
+
+ public static WeiboToken parse(Oauth2AccessToken token) {
+ WeiboToken target = new WeiboToken();
+ target.setOpenid(token.getUid());
+ target.setAccessToken(token.getToken());
+ target.setRefreshToken(token.getRefreshToken());
+ target.setPhoneNum(token.getPhoneNum());
+ return target;
+ }
+
+ public String getRefreshToken() {
+ return refreshToken;
+ }
+
+ public void setRefreshToken(String refreshToken) {
+ this.refreshToken = refreshToken;
+ }
+
+ public String getPhoneNum() {
+ return phoneNum;
+ }
+
+ public void setPhoneNum(String phoneNum) {
+ this.phoneNum = phoneNum;
+ }
+}
diff --git a/share/src/main/java/vip/devkit/common/share/login/result/WeiboUser.java b/share/src/main/java/vip/devkit/common/share/login/result/WeiboUser.java
new file mode 100644
index 0000000..ddce401
--- /dev/null
+++ b/share/src/main/java/vip/devkit/common/share/login/result/WeiboUser.java
@@ -0,0 +1,120 @@
+package vip.devkit.common.share.login.result;
+
+import android.text.TextUtils;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+
+public class WeiboUser extends BaseUser {
+
+ private String language;
+
+ private String city;
+
+ private String province;
+
+ private String headimgurl_hd;
+
+ /**
+ * 示例
+ * {
+ * "id": 1404376560,
+ * "screen_name": "zaku",
+ * "name": "zaku",
+ * "province": "11",
+ * "city": "5",
+ * "location": "北京 朝阳区",
+ * "description": "人生五十年,乃如梦如幻;有生斯有死,壮士复何憾。",
+ * "url": "http://blog.sina.com.cn/zaku",
+ * "profile_image_url": "http://tp1.sinaimg.cn/1404376560/50/0/1",
+ * "domain": "zaku",
+ * "gender": "m",
+ * "followers_count": 1204,
+ * "friends_count": 447,
+ * "statuses_count": 2908,
+ * "favourites_count": 0,
+ * "created_at": "Fri Aug 28 00:00:00 +0800 2009",
+ * "following": false,
+ * "allow_all_act_msg": false,
+ * "geo_enabled": true,
+ * "verified": false,
+ * "status": {
+ * "created_at": "Tue May 24 18:04:53 +0800 2011",
+ * "id": 11142488790,
+ * "text": "我的相机到了。",
+ * "favorited": false,
+ * "truncated": false,
+ * "in_reply_to_status_id": "",
+ * "in_reply_to_user_id": "",
+ * "in_reply_to_screen_name": "",
+ * "geo": null,
+ * "mid": "5610221544300749636",
+ * "annotations": [],
+ * "reposts_count": 5,
+ * "comments_count": 8
+ * },
+ * "allow_all_comment": true,
+ * "avatar_large": "http://tp1.sinaimg.cn/1404376560/180/0/1",
+ * "verified_reason": "",
+ * "follow_me": false,
+ * "online_status": 0,
+ * "bi_followers_count": 215
+ * }
+ */
+
+ public static WeiboUser parse(JSONObject jsonObject) throws JSONException {
+ WeiboUser user = new WeiboUser();
+ user.setOpenId(String.valueOf(jsonObject.getInt("id")));
+ user.setNickname(jsonObject.getString("screen_name"));
+
+ // 性别
+ String gender = jsonObject.getString("gender");
+ if (TextUtils.equals(gender, "m")) {
+ user.setSex(1);
+ } else if (TextUtils.equals(gender, "f")) {
+ user.setSex(2);
+ } else {
+ user.setSex(0);
+ }
+
+ user.setHeadImageUrl(jsonObject.getString("profile_image_url"));
+ user.setHeadImageUrlLarge(jsonObject.getString("avatar_large"));
+ user.setHeadimgurl_hd(jsonObject.getString("avatar_hd"));
+ user.setCity(jsonObject.getString("city"));
+ user.setProvince(jsonObject.getString("province"));
+
+ return user;
+ }
+
+ public String getLanguage() {
+ return language;
+ }
+
+ public void setLanguage(String language) {
+ this.language = language;
+ }
+
+ public String getCity() {
+ return city;
+ }
+
+ public void setCity(String city) {
+ this.city = city;
+ }
+
+ public String getProvince() {
+ return province;
+ }
+
+ public void setProvince(String province) {
+ this.province = province;
+ }
+
+ public String getHeadimgurl_hd() {
+ return headimgurl_hd;
+ }
+
+ public void setHeadimgurl_hd(String headimgurl_hd) {
+ this.headimgurl_hd = headimgurl_hd;
+ }
+}
diff --git a/share/src/main/java/vip/devkit/common/share/login/result/WxToken.java b/share/src/main/java/vip/devkit/common/share/login/result/WxToken.java
new file mode 100644
index 0000000..d26bfe8
--- /dev/null
+++ b/share/src/main/java/vip/devkit/common/share/login/result/WxToken.java
@@ -0,0 +1,26 @@
+package vip.devkit.common.share.login.result;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+
+public class WxToken extends BaseToken {
+
+ private String refresh_token;
+
+ public static WxToken parse(JSONObject jsonObject) throws JSONException {
+ WxToken wxToken = new WxToken();
+ wxToken.setOpenid(jsonObject.getString("openid"));
+ wxToken.setAccessToken(jsonObject.getString("access_token"));
+ wxToken.setRefreshToken(jsonObject.getString("refresh_token"));
+ return wxToken;
+ }
+
+ public String getRefreshToken() {
+ return refresh_token;
+ }
+
+ public void setRefreshToken(String refresh_token) {
+ this.refresh_token = refresh_token;
+ }
+}
diff --git a/share/src/main/java/vip/devkit/common/share/login/result/WxUser.java b/share/src/main/java/vip/devkit/common/share/login/result/WxUser.java
new file mode 100644
index 0000000..9eb0b10
--- /dev/null
+++ b/share/src/main/java/vip/devkit/common/share/login/result/WxUser.java
@@ -0,0 +1,63 @@
+package vip.devkit.common.share.login.result;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+
+public class WxUser extends BaseUser {
+
+ private String city;
+
+ private String country;
+
+ private String province;
+
+ private String unionid;
+
+ public static WxUser parse(JSONObject jsonObject) throws JSONException {
+ WxUser user = new WxUser();
+ user.setOpenId(jsonObject.getString("openid"));
+ user.setNickname(jsonObject.getString("nickname"));
+ user.setSex(jsonObject.getInt("sex"));
+ user.setHeadImageUrl(jsonObject.getString("headimgurl"));
+ user.setHeadImageUrlLarge(jsonObject.getString("headimgurl")); // 重复
+ user.setProvince(jsonObject.getString("province"));
+ user.setCity(jsonObject.getString("city"));
+ user.setCountry(jsonObject.getString("country"));
+ user.setUnionid(jsonObject.getString("unionid"));
+
+ return user;
+ }
+
+ public String getCity() {
+ return city;
+ }
+
+ public void setCity(String city) {
+ this.city = city;
+ }
+
+ public String getCountry() {
+ return country;
+ }
+
+ public void setCountry(String country) {
+ this.country = country;
+ }
+
+ public String getProvince() {
+ return province;
+ }
+
+ public void setProvince(String province) {
+ this.province = province;
+ }
+
+ public String getUnionid() {
+ return unionid;
+ }
+
+ public void setUnionid(String unionid) {
+ this.unionid = unionid;
+ }
+}
diff --git a/share/src/main/java/vip/devkit/common/share/share/ImageDecoder.java b/share/src/main/java/vip/devkit/common/share/share/ImageDecoder.java
new file mode 100644
index 0000000..8acdc09
--- /dev/null
+++ b/share/src/main/java/vip/devkit/common/share/share/ImageDecoder.java
@@ -0,0 +1,126 @@
+package vip.devkit.common.share.share;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.os.Environment;
+import android.text.TextUtils;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import okhttp3.HttpUrl;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+import okio.BufferedSink;
+import okio.Okio;
+import vip.devkit.common.share.ShareLogger;
+
+
+public class ImageDecoder {
+
+ private static final String FILE_NAME = "share_image.jpg";
+
+ public static String decode(Context context, ShareImageObject imageObject) throws Exception {
+ File resultFile = cacheFile(context);
+
+ if (!TextUtils.isEmpty(imageObject.getPathOrUrl())) {
+ return decode(context, imageObject.getPathOrUrl());
+ } else if (imageObject.getBitmap() != null) {
+ // save bitmap to file
+ FileOutputStream outputStream = new FileOutputStream(resultFile);
+ imageObject.getBitmap().compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
+ outputStream.close();
+ return resultFile.getAbsolutePath();
+ } else {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ private static String decode(Context context, String pathOrUrl) throws Exception {
+ File resultFile = cacheFile(context);
+
+ if (new File(pathOrUrl).exists()) {
+ // copy file
+ return decodeFile(new File(pathOrUrl), resultFile);
+ } else if (HttpUrl.parse(pathOrUrl) != null) {
+ // download image
+ return downloadImageToUri(pathOrUrl, resultFile);
+ } else {
+ throw new IllegalArgumentException("Please input a file path or http url");
+ }
+ }
+
+ private static String downloadImageToUri(String url, File resultFile) throws IOException {
+ OkHttpClient client = new OkHttpClient();
+ Request request = new Request.Builder().url(url).build();
+ Response response = client.newCall(request).execute();
+ BufferedSink sink = Okio.buffer(Okio.sink(resultFile));
+ sink.writeAll(response.body().source());
+
+ sink.close();
+ response.close();
+
+ return resultFile.getAbsolutePath();
+ }
+
+ private static File cacheFile(Context context) throws Exception {
+ String state = Environment.getExternalStorageState();
+ if (state != null && state.equals(Environment.MEDIA_MOUNTED)) {
+ return new File(context.getExternalFilesDir(""), FILE_NAME);
+ } else {
+ throw new Exception(ShareLogger.INFO.SD_CARD_NOT_AVAILABLE);
+ }
+ }
+ private static void copyFile(InputStream inputStream, OutputStream outputStream)
+ throws IOException {
+ byte[] buffer = new byte[4096];
+ while (-1 != inputStream.read(buffer)) {
+ outputStream.write(buffer);
+ }
+
+ outputStream.flush();
+ inputStream.close();
+ outputStream.close();
+ }
+
+ private static String decodeFile(File origin, File result) throws IOException {
+ copyFile(new FileInputStream(origin), new FileOutputStream(result, false));
+ return result.getAbsolutePath();
+ }
+
+ public static byte[] compress2Byte(String imagePath, int size, int length) {
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ options.inJustDecodeBounds = true;
+ BitmapFactory.decodeFile(imagePath, options);
+
+ int outH = options.outHeight;
+ int outW = options.outWidth;
+ int inSampleSize = 1;
+
+ while (outH / inSampleSize > size || outW / inSampleSize > size) {
+ inSampleSize *= 2;
+ }
+
+ options.inSampleSize = inSampleSize;
+ options.inJustDecodeBounds = false;
+
+ Bitmap bitmap = BitmapFactory.decodeFile(imagePath, options);
+
+ ByteArrayOutputStream result = new ByteArrayOutputStream();
+ int quality = 100;
+ bitmap.compress(Bitmap.CompressFormat.JPEG, quality, result);
+ if (result.size() > length) {
+ result.reset();
+ quality -= 10;
+ bitmap.compress(Bitmap.CompressFormat.JPEG, quality, result);
+ }
+
+ bitmap.recycle();
+ return result.toByteArray();
+ }
+}
diff --git a/share/src/main/java/vip/devkit/common/share/share/ShareImageObject.java b/share/src/main/java/vip/devkit/common/share/share/ShareImageObject.java
new file mode 100644
index 0000000..481af35
--- /dev/null
+++ b/share/src/main/java/vip/devkit/common/share/share/ShareImageObject.java
@@ -0,0 +1,38 @@
+package vip.devkit.common.share.share;
+
+import android.graphics.Bitmap;
+
+/**
+ * Created by shaohui on 2016/11/19.
+ */
+
+public class ShareImageObject {
+
+ private Bitmap mBitmap;
+
+ private String mPathOrUrl;
+
+ public ShareImageObject(Bitmap bitmap) {
+ mBitmap = bitmap;
+ }
+
+ public ShareImageObject(String pathOrUrl) {
+ mPathOrUrl = pathOrUrl;
+ }
+
+ public Bitmap getBitmap() {
+ return mBitmap;
+ }
+
+ public void setBitmap(Bitmap bitmap) {
+ mBitmap = bitmap;
+ }
+
+ public String getPathOrUrl() {
+ return mPathOrUrl;
+ }
+
+ public void setPathOrUrl(String pathOrUrl) {
+ mPathOrUrl = pathOrUrl;
+ }
+}
diff --git a/share/src/main/java/vip/devkit/common/share/share/ShareListener.java b/share/src/main/java/vip/devkit/common/share/share/ShareListener.java
new file mode 100644
index 0000000..2d635b4
--- /dev/null
+++ b/share/src/main/java/vip/devkit/common/share/share/ShareListener.java
@@ -0,0 +1,55 @@
+package vip.devkit.common.share.share;
+
+import com.sina.weibo.sdk.api.share.BaseResponse;
+import com.sina.weibo.sdk.api.share.IWeiboHandler;
+import com.sina.weibo.sdk.constant.WBConstants;
+import com.tencent.tauth.IUiListener;
+import com.tencent.tauth.UiError;
+
+import vip.devkit.common.share.ShareLogger.INFO;
+
+
+public abstract class ShareListener implements IUiListener, IWeiboHandler.Response {
+ @Override
+ public final void onComplete(Object o) {
+ shareSuccess();
+ }
+
+ @Override
+ public final void onError(UiError uiError) {
+ shareFailure(
+ new Exception(uiError == null ? INFO.DEFAULT_QQ_SHARE_ERROR : uiError.errorDetail));
+ }
+
+ @Override
+ public final void onCancel() {
+ shareCancel();
+ }
+
+ @Override
+ public final void onResponse(BaseResponse baseResponse) {
+ switch (baseResponse.errCode) {
+ case WBConstants.ErrorCode.ERR_OK:
+ shareSuccess();
+ break;
+ case WBConstants.ErrorCode.ERR_FAIL:
+ shareFailure(new Exception(baseResponse.errMsg));
+ break;
+ case WBConstants.ErrorCode.ERR_CANCEL:
+ shareCancel();
+ break;
+ default:
+ shareFailure(new Exception(baseResponse.errMsg));
+ }
+ }
+
+ public abstract void shareSuccess();
+
+ public abstract void shareFailure(Exception e);
+
+ public abstract void shareCancel();
+
+ // 用于缓解用户焦虑
+ public void shareRequest() {
+ }
+}
diff --git a/share/src/main/java/vip/devkit/common/share/share/SharePlatform.java b/share/src/main/java/vip/devkit/common/share/share/SharePlatform.java
new file mode 100644
index 0000000..c99abd0
--- /dev/null
+++ b/share/src/main/java/vip/devkit/common/share/share/SharePlatform.java
@@ -0,0 +1,25 @@
+package vip.devkit.common.share.share;
+
+import android.support.annotation.IntDef;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Created by shaohui on 2016/11/18.
+ */
+
+public class SharePlatform {
+
+ @IntDef({ DEFAULT, QQ, QZONE, WEIBO, WX, WX_TIMELINE })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Platform{}
+
+ public static final int DEFAULT = 0;
+ public static final int QQ = 1;
+ public static final int QZONE = 2;
+ public static final int WX = 3;
+ public static final int WX_TIMELINE = 4;
+ public static final int WEIBO = 5;
+
+
+}
diff --git a/share/src/main/java/vip/devkit/common/share/share/instance/DefaultShareInstance.java b/share/src/main/java/vip/devkit/common/share/share/instance/DefaultShareInstance.java
new file mode 100644
index 0000000..4a10dcd
--- /dev/null
+++ b/share/src/main/java/vip/devkit/common/share/share/instance/DefaultShareInstance.java
@@ -0,0 +1,102 @@
+package vip.devkit.common.share.share.instance;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.net.Uri;
+import java.io.File;
+import rx.Emitter;
+import rx.Observable;
+import rx.android.schedulers.AndroidSchedulers;
+import rx.functions.Action1;
+import rx.schedulers.Schedulers;
+import vip.devkit.common.share.R;
+import vip.devkit.common.share.share.ImageDecoder;
+import vip.devkit.common.share.share.ShareImageObject;
+import vip.devkit.common.share.share.ShareListener;
+
+
+public class DefaultShareInstance implements ShareInstance {
+
+ @Override
+ public void shareText(int platform, String text, Activity activity, ShareListener listener) {
+ Intent sendIntent = new Intent();
+ sendIntent.setAction(Intent.ACTION_SEND);
+ sendIntent.putExtra(Intent.EXTRA_TEXT, text);
+ sendIntent.setType("text/plain");
+ activity.startActivity(Intent.createChooser(sendIntent,
+ activity.getResources().getString(R.string.vista_share_title)));
+ }
+
+ @Override
+ public void shareMedia(int platform, String title, String targetUrl, String summary,
+ ShareImageObject shareImageObject, Activity activity, ShareListener listener) {
+ Intent sendIntent = new Intent();
+ sendIntent.setAction(Intent.ACTION_SEND);
+ sendIntent.putExtra(Intent.EXTRA_TEXT, String.format("%s %s", title, targetUrl));
+ sendIntent.setType("text/plain");
+ activity.startActivity(Intent.createChooser(sendIntent,
+ activity.getResources().getString(R.string.vista_share_title)));
+ }
+
+ @Override
+ public void shareImage(int platform, final ShareImageObject shareImageObject,
+ final Activity activity, final ShareListener listener) {
+ Observable.fromEmitter(new Action1>() {
+ @Override
+ public void call(Emitter emitter) {
+ try {
+ Uri uri =
+ Uri.fromFile(new File(ImageDecoder.decode(activity, shareImageObject)));
+ emitter.onNext(uri);
+ emitter.onCompleted();
+ } catch (Exception e) {
+ emitter.onError(e);
+ }
+ }
+ }, Emitter.BackpressureMode.BUFFER)
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .doOnRequest(new Action1() {
+ @Override
+ public void call(Long aLong) {
+ listener.shareRequest();
+ }
+ })
+ .subscribe(new Action1() {
+ @Override
+ public void call(Uri uri) {
+ Intent shareIntent = new Intent();
+ shareIntent.setAction(Intent.ACTION_SEND);
+ shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
+ shareIntent.setType("image/jpeg");
+ activity.startActivity(Intent.createChooser(shareIntent,
+ activity.getResources().getText(R.string.vista_share_title)));
+ }
+ }, new Action1() {
+ @Override
+ public void call(Throwable throwable) {
+ listener.shareFailure(new Exception(throwable));
+ }
+ });
+ }
+
+ @Override
+ public void handleResult(Intent data) {
+ // Default share, do nothing
+ }
+
+ @Override
+ public boolean isInstall(Context context) {
+ Intent shareIntent = new Intent();
+ shareIntent.setAction(Intent.ACTION_SEND);
+ return context.getPackageManager()
+ .resolveActivity(shareIntent, PackageManager.MATCH_DEFAULT_ONLY) != null;
+ }
+
+ @Override
+ public void recycle() {
+
+ }
+}
diff --git a/share/src/main/java/vip/devkit/common/share/share/instance/QQShareInstance.java b/share/src/main/java/vip/devkit/common/share/share/instance/QQShareInstance.java
new file mode 100644
index 0000000..613a5fb
--- /dev/null
+++ b/share/src/main/java/vip/devkit/common/share/share/instance/QQShareInstance.java
@@ -0,0 +1,218 @@
+package vip.devkit.common.share.share.instance;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.text.TextUtils;
+import com.tencent.connect.share.QQShare;
+import com.tencent.connect.share.QzonePublish;
+import com.tencent.connect.share.QzoneShare;
+import com.tencent.tauth.Tencent;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+import vip.devkit.common.share.ShareUtil;
+import vip.devkit.common.share.share.ImageDecoder;
+import vip.devkit.common.share.share.ShareImageObject;
+import vip.devkit.common.share.share.ShareListener;
+import vip.devkit.common.share.share.SharePlatform;
+import rx.Emitter;
+import rx.Observable;
+import rx.android.schedulers.AndroidSchedulers;
+import rx.functions.Action0;
+import rx.functions.Action1;
+import rx.schedulers.Schedulers;
+
+import static vip.devkit.common.share.ShareLogger.INFO;
+
+
+public class QQShareInstance implements ShareInstance {
+
+ private Tencent mTencent;
+
+ public QQShareInstance(Context context, String app_id) {
+ mTencent = Tencent.createInstance(app_id, context);
+
+ }
+
+ @Override
+ public void shareText(int platform, String text, Activity activity, ShareListener listener) {
+ if (platform == SharePlatform.QZONE) {
+ shareToQZoneForText(text, activity, listener);
+ } else {
+ activity.finish();
+ listener.shareFailure(new Exception(INFO.QQ_NOT_SUPPORT_SHARE_TXT));
+ }
+ }
+
+ @Override
+ public void shareMedia(final int platform, final String title, final String targetUrl,
+ final String summary, final ShareImageObject shareImageObject, final Activity activity,
+ final ShareListener listener) {
+ Observable.fromEmitter(new Action1>() {
+ @Override
+ public void call(Emitter emitter) {
+ try {
+ emitter.onNext(ImageDecoder.decode(activity, shareImageObject));
+ emitter.onCompleted();
+ } catch (Exception e) {
+ emitter.onError(e);
+ }
+ }
+ }, Emitter.BackpressureMode.DROP)
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .doOnRequest(new Action1() {
+ @Override
+ public void call(Long aLong) {
+ listener.shareRequest();
+ }
+ })
+ .subscribe(new Action1() {
+ @Override
+ public void call(String s) {
+ if (platform == SharePlatform.QZONE) {
+ shareToQZoneForMedia(title, targetUrl, summary, s, activity,
+ listener);
+ } else {
+ shareToQQForMedia(title, summary, targetUrl, s, activity, listener);
+ }
+ }
+ }, new Action1() {
+ @Override
+ public void call(Throwable throwable) {
+ activity.finish();
+ listener.shareFailure(new Exception(throwable));
+ }
+ });
+ }
+
+ @Override
+ public void shareImage(final int platform, final ShareImageObject shareImageObject,
+ final Activity activity, final ShareListener listener) {
+ Observable.fromEmitter(new Action1>() {
+ @Override
+ public void call(Emitter emitter) {
+ try {
+ emitter.onNext(ImageDecoder.decode(activity, shareImageObject));
+ emitter.onCompleted();
+ } catch (Exception e) {
+ emitter.onError(e);
+ }
+ }
+ }, Emitter.BackpressureMode.DROP)
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .doOnRequest(new Action1() {
+ @Override
+ public void call(Long aLong) {
+ listener.shareRequest();
+ }
+ })
+ .subscribe(new Action1() {
+ @Override
+ public void call(String localPath) {
+ if (platform == SharePlatform.QZONE) {
+ shareToQzoneForImage(localPath, activity, listener);
+ } else {
+ shareToQQForImage(localPath, activity, listener);
+ }
+ }
+ }, new Action1() {
+ @Override
+ public void call(Throwable throwable) {
+ activity.finish();
+ listener.shareFailure(new Exception(throwable));
+ }
+ });
+ }
+
+ @Override
+ public void handleResult(Intent data) {
+ Tencent.handleResultData(data, ShareUtil.mShareListener);
+ }
+
+ @Override
+ public boolean isInstall(Context context) {
+ PackageManager pm = context.getPackageManager();
+ if (pm == null) {
+ return false;
+ }
+
+ List packageInfos = pm.getInstalledPackages(0);
+ for (PackageInfo info : packageInfos) {
+ if (TextUtils.equals(info.packageName.toLowerCase(), "com.tencent.mobileqq")) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void recycle() {
+ if (mTencent != null) {
+ mTencent.releaseResource();
+ mTencent = null;
+ }
+ }
+
+ private void shareToQQForMedia(String title, String summary, String targetUrl, String thumbUrl,
+ Activity activity, ShareListener listener) {
+ final Bundle params = new Bundle();
+ params.putInt(QQShare.SHARE_TO_QQ_KEY_TYPE, QQShare.SHARE_TO_QQ_TYPE_DEFAULT);
+ params.putString(QQShare.SHARE_TO_QQ_TITLE, title);
+ params.putString(QQShare.SHARE_TO_QQ_SUMMARY, summary);
+ params.putString(QQShare.SHARE_TO_QQ_TARGET_URL, targetUrl);
+ params.putString(QQShare.SHARE_TO_QQ_IMAGE_URL, thumbUrl);
+ params.putInt(QQShare.SHARE_TO_QQ_KEY_TYPE, QQShare.SHARE_TO_QQ_TYPE_DEFAULT);
+ params.putString(QQShare.SHARE_TO_QQ_TITLE, title);
+ params.putString(QQShare.SHARE_TO_QQ_SUMMARY,summary);
+ params.putString(QQShare.SHARE_TO_QQ_TARGET_URL, targetUrl);
+ params.putString(QQShare.SHARE_TO_QQ_IMAGE_URL, thumbUrl);
+ params.putInt(QQShare.SHARE_TO_QQ_EXT_INT, 123);
+ params.putString(QQShare.SHARE_TO_QQ_APP_NAME,null);
+ mTencent.shareToQQ(activity, params, listener);
+ }
+
+ private void shareToQQForImage(String localUrl, Activity activity, ShareListener listener) {
+ Bundle params = new Bundle();
+ params.putInt(QQShare.SHARE_TO_QQ_KEY_TYPE, QQShare.SHARE_TO_QQ_TYPE_IMAGE);
+ params.putString(QQShare.SHARE_TO_QQ_IMAGE_LOCAL_URL, localUrl);
+ mTencent.shareToQQ(activity, params, listener);
+ }
+
+ private void shareToQZoneForText(String text, Activity activity, ShareListener listener) {
+ final Bundle params = new Bundle();
+ params.putInt(QzoneShare.SHARE_TO_QZONE_KEY_TYPE,
+ QzonePublish.PUBLISH_TO_QZONE_TYPE_PUBLISHMOOD);
+ params.putString(QzoneShare.SHARE_TO_QQ_SUMMARY, text);
+ mTencent.publishToQzone(activity, params, listener);
+ }
+
+ private void shareToQZoneForMedia(String title, String targetUrl, String summary,
+ String imageUrl, Activity activity, ShareListener listener) {
+ final Bundle params = new Bundle();
+ final ArrayList image = new ArrayList<>();
+ image.add(imageUrl);
+ 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, summary);
+ params.putString(QzoneShare.SHARE_TO_QQ_TARGET_URL, targetUrl);
+ params.putStringArrayList(QzoneShare.SHARE_TO_QQ_IMAGE_URL, image);
+ mTencent.shareToQzone(activity, params, listener);
+ }
+
+ private void shareToQzoneForImage(String imagePath, Activity activity, ShareListener listener) {
+ final Bundle params = new Bundle();
+ final ArrayList image = new ArrayList<>();
+ image.add(imagePath);
+ params.putInt(QzoneShare.SHARE_TO_QZONE_KEY_TYPE,
+ QzonePublish.PUBLISH_TO_QZONE_TYPE_PUBLISHMOOD);
+ params.putStringArrayList(QzoneShare.SHARE_TO_QQ_IMAGE_URL, image);
+ mTencent.publishToQzone(activity, params, listener);
+ }
+}
\ No newline at end of file
diff --git a/share/src/main/java/vip/devkit/common/share/share/instance/ShareInstance.java b/share/src/main/java/vip/devkit/common/share/share/instance/ShareInstance.java
new file mode 100644
index 0000000..575dd35
--- /dev/null
+++ b/share/src/main/java/vip/devkit/common/share/share/instance/ShareInstance.java
@@ -0,0 +1,26 @@
+package vip.devkit.common.share.share.instance;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+
+import vip.devkit.common.share.share.ShareImageObject;
+import vip.devkit.common.share.share.ShareListener;
+
+
+public interface ShareInstance {
+
+ void shareText(int platform, String text, Activity activity, ShareListener listener);
+
+ void shareMedia(int platform, String title, String targetUrl, String summary,
+ ShareImageObject shareImageObject, Activity activity, ShareListener listener);
+
+ void shareImage(int platform, ShareImageObject shareImageObject, Activity activity,
+ ShareListener listener);
+
+ void handleResult(Intent data);
+
+ boolean isInstall(Context context);
+
+ void recycle();
+}
diff --git a/share/src/main/java/vip/devkit/common/share/share/instance/WeiboShareInstance.java b/share/src/main/java/vip/devkit/common/share/share/instance/WeiboShareInstance.java
new file mode 100644
index 0000000..4c8b1ab
--- /dev/null
+++ b/share/src/main/java/vip/devkit/common/share/share/instance/WeiboShareInstance.java
@@ -0,0 +1,155 @@
+package vip.devkit.common.share.share.instance;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.media.Image;
+import android.text.TextUtils;
+import android.util.Pair;
+import com.sina.weibo.sdk.api.ImageObject;
+import com.sina.weibo.sdk.api.TextObject;
+import com.sina.weibo.sdk.api.WeiboMultiMessage;
+import com.sina.weibo.sdk.api.share.IWeiboShareAPI;
+import com.sina.weibo.sdk.api.share.SendMessageToWeiboResponse;
+import com.sina.weibo.sdk.api.share.SendMultiMessageToWeiboRequest;
+import com.sina.weibo.sdk.api.share.WeiboShareSDK;
+import com.sina.weibo.sdk.constant.WBConstants;
+import rx.Emitter;
+import rx.Observable;
+import rx.android.schedulers.AndroidSchedulers;
+import rx.functions.Action1;
+import rx.schedulers.Schedulers;
+import vip.devkit.common.share.ShareUtil;
+import vip.devkit.common.share.share.ImageDecoder;
+import vip.devkit.common.share.share.ShareImageObject;
+import vip.devkit.common.share.share.ShareListener;
+
+public class WeiboShareInstance implements ShareInstance {
+ /**
+ * 微博分享限制thumb image必须小于2097152,否则点击分享会没有反应
+ */
+
+ private IWeiboShareAPI mWeiboShareAPI;
+
+ private static final int TARGET_SIZE = 1024;
+
+ private static final int TARGET_LENGTH = 2097152;
+
+ public WeiboShareInstance(Context context, String appId) {
+ mWeiboShareAPI = WeiboShareSDK.createWeiboAPI(context, appId);
+ mWeiboShareAPI.registerApp();
+ }
+
+ @Override
+ public void shareText(int platform, String text, Activity activity, ShareListener listener) {
+ TextObject textObject = new TextObject();
+ textObject.text = text;
+ WeiboMultiMessage message = new WeiboMultiMessage();
+ message.textObject = textObject;
+
+ sendRequest(activity, message);
+ }
+
+ @Override
+ public void shareMedia(int platform, final String title, final String targetUrl, String summary,
+ ShareImageObject shareImageObject, final Activity activity,
+ final ShareListener listener) {
+ String content = String.format("%s %s", title, targetUrl);
+ shareTextOrImage(shareImageObject, content, activity, listener);
+ }
+
+ @Override
+ public void shareImage(int platform, ShareImageObject shareImageObject, Activity activity,
+ ShareListener listener) {
+ shareTextOrImage(shareImageObject, null, activity, listener);
+ }
+
+ @Override
+ public void handleResult(Intent intent) {
+ SendMessageToWeiboResponse baseResponse =
+ new SendMessageToWeiboResponse(intent.getExtras());
+
+ switch (baseResponse.errCode) {
+ case WBConstants.ErrorCode.ERR_OK:
+ ShareUtil.mShareListener.shareSuccess();
+ break;
+ case WBConstants.ErrorCode.ERR_FAIL:
+ ShareUtil.mShareListener.shareFailure(new Exception(baseResponse.errMsg));
+ break;
+ case WBConstants.ErrorCode.ERR_CANCEL:
+ ShareUtil.mShareListener.shareCancel();
+ break;
+ default:
+ ShareUtil.mShareListener.shareFailure(new Exception(baseResponse.errMsg));
+ }
+ }
+
+ @Override
+ public boolean isInstall(Context context) {
+ return mWeiboShareAPI.isWeiboAppInstalled();
+ }
+
+ @Override
+ public void recycle() {
+ mWeiboShareAPI = null;
+ }
+
+ private void shareTextOrImage(final ShareImageObject shareImageObject, final String text,
+ final Activity activity, final ShareListener listener) {
+
+ Observable.fromEmitter(new Action1>>() {
+ @Override
+ public void call(Emitter> emitter) {
+ try {
+ String path = ImageDecoder.decode(activity, shareImageObject);
+ emitter.onNext(Pair.create(path,
+ ImageDecoder.compress2Byte(path, TARGET_SIZE, TARGET_LENGTH)));
+ emitter.onCompleted();
+ } catch (Exception e) {
+ emitter.onError(e);
+ }
+ }
+ }, Emitter.BackpressureMode.DROP)
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .doOnRequest(new Action1() {
+ @Override
+ public void call(Long aLong) {
+ listener.shareRequest();
+ }
+ })
+ .subscribe(new Action1>() {
+ @Override
+ public void call(Pair pair) {
+ ImageObject imageObject = new ImageObject();
+ imageObject.imageData = pair.second;
+ imageObject.imagePath = pair.first;
+
+ WeiboMultiMessage message = new WeiboMultiMessage();
+ message.imageObject = imageObject;
+ if (!TextUtils.isEmpty(text)) {
+ TextObject textObject = new TextObject();
+ textObject.text = text;
+
+ message.textObject = textObject;
+ }
+
+ sendRequest(activity, message);
+ }
+ }, new Action1() {
+ @Override
+ public void call(Throwable throwable) {
+ activity.finish();
+ listener.shareFailure(new Exception(throwable));
+ }
+ });
+ }
+
+ private void sendRequest(Activity activity, WeiboMultiMessage message) {
+ SendMultiMessageToWeiboRequest request = new SendMultiMessageToWeiboRequest();
+ request.transaction = String.valueOf(System.currentTimeMillis());
+ request.multiMessage = message;
+ mWeiboShareAPI.sendRequest(activity, request);
+ }
+}
diff --git a/share/src/main/java/vip/devkit/common/share/share/instance/WxShareInstance.java b/share/src/main/java/vip/devkit/common/share/share/instance/WxShareInstance.java
new file mode 100644
index 0000000..6bde46d
--- /dev/null
+++ b/share/src/main/java/vip/devkit/common/share/share/instance/WxShareInstance.java
@@ -0,0 +1,200 @@
+package vip.devkit.common.share.share.instance;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.media.Image;
+import android.text.TextUtils;
+import android.util.Log;
+import android.util.Pair;
+
+import com.tencent.mm.opensdk.modelbase.BaseReq;
+import com.tencent.mm.opensdk.modelbase.BaseResp;
+import com.tencent.mm.opensdk.modelmsg.SendMessageToWX;
+import com.tencent.mm.opensdk.modelmsg.WXImageObject;
+import com.tencent.mm.opensdk.modelmsg.WXMediaMessage;
+import com.tencent.mm.opensdk.modelmsg.WXTextObject;
+import com.tencent.mm.opensdk.modelmsg.WXWebpageObject;
+import com.tencent.mm.opensdk.openapi.IWXAPI;
+import com.tencent.mm.opensdk.openapi.IWXAPIEventHandler;
+import com.tencent.mm.opensdk.openapi.WXAPIFactory;
+
+import rx.Emitter;
+import rx.Observable;
+import rx.android.schedulers.AndroidSchedulers;
+import rx.functions.Action1;
+import rx.schedulers.Schedulers;
+import vip.devkit.common.share.ShareUtil;
+import vip.devkit.common.share.share.ImageDecoder;
+import vip.devkit.common.share.share.ShareImageObject;
+import vip.devkit.common.share.share.ShareListener;
+import vip.devkit.common.share.share.SharePlatform;
+
+
+public class WxShareInstance implements ShareInstance {
+
+ /**
+ * 微信分享限制thumb image必须小于32Kb,否则点击分享会没有反应
+ */
+
+ private IWXAPI mIWXAPI;
+
+ private static final int THUMB_SIZE = 32 * 1024 * 8;
+
+ private static final int TARGET_SIZE = 200;
+
+ public WxShareInstance(Context context, String appId) {
+ mIWXAPI = WXAPIFactory.createWXAPI(context, appId, true);
+ mIWXAPI.registerApp(appId);
+ }
+
+ @Override
+ public void shareText(int platform, String text, Activity activity, ShareListener listener) {
+ WXTextObject textObject = new WXTextObject();
+ textObject.text = text;
+
+ WXMediaMessage message = new WXMediaMessage();
+ message.mediaObject = textObject;
+ message.description = text;
+
+ sendMessage(platform, message, buildTransaction("text"));
+ }
+
+ @Override
+ public void shareMedia(
+ final int platform, final String title, final String targetUrl, final String summary,
+ final ShareImageObject shareImageObject, final Activity activity, final ShareListener listener) {
+ Observable.fromEmitter(new Action1>() {
+
+ @Override
+ public void call(Emitter emitter) {
+ try {
+ String imagePath = ImageDecoder.decode(activity, shareImageObject);
+ emitter.onNext(ImageDecoder.compress2Byte(imagePath, TARGET_SIZE, THUMB_SIZE));
+ } catch (Exception e) {
+ emitter.onError(e);
+ }
+ }
+ }, Emitter.BackpressureMode.DROP)
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .doOnRequest(new Action1() {
+ @Override
+ public void call(Long aLong) {
+ listener.shareRequest();
+ }
+ })
+ .subscribe(new Action1() {
+ @Override
+ public void call(byte[] bytes) {
+ WXWebpageObject webpageObject = new WXWebpageObject();
+ webpageObject.webpageUrl = targetUrl;
+
+ WXMediaMessage message = new WXMediaMessage(webpageObject);
+ message.title = title;
+ message.description = summary;
+ message.thumbData = bytes;
+
+ sendMessage(platform, message, buildTransaction("webPage"));
+ }
+ }, new Action1() {
+ @Override
+ public void call(Throwable throwable) {
+ activity.finish();
+ listener.shareFailure(new Exception(throwable));
+ }
+ });
+ }
+
+ @Override
+ public void shareImage(final int platform, final ShareImageObject shareImageObject,
+ final Activity activity, final ShareListener listener) {
+ Observable.fromEmitter(new Action1>>() {
+ @Override
+ public void call(Emitter> emitter) {
+ try {
+ String imagePath = ImageDecoder.decode(activity, shareImageObject);
+ emitter.onNext(Pair.create(BitmapFactory.decodeFile(imagePath),
+ ImageDecoder.compress2Byte(imagePath, TARGET_SIZE, THUMB_SIZE)));
+ } catch (Exception e) {
+ emitter.onError(e);
+ }
+ }
+ }, Emitter.BackpressureMode.BUFFER)
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .doOnRequest(new Action1() {
+ @Override
+ public void call(Long aLong) {
+ listener.shareRequest();
+ }
+ })
+ .subscribe(new Action1>() {
+ @Override
+ public void call(Pair pair) {
+ WXImageObject imageObject = new WXImageObject(pair.first);
+
+ WXMediaMessage message = new WXMediaMessage();
+ message.mediaObject = imageObject;
+ message.thumbData = pair.second;
+
+ sendMessage(platform, message, buildTransaction("image"));
+ }
+ }, new Action1() {
+ @Override
+ public void call(Throwable throwable) {
+ activity.finish();
+ listener.shareFailure(new Exception(throwable));
+ }
+ });
+ }
+
+ @Override
+ public void handleResult(Intent data) {
+ mIWXAPI.handleIntent(data, new IWXAPIEventHandler() {
+ @Override
+ public void onReq(BaseReq baseReq) {
+ }
+
+ @Override
+ public void onResp(BaseResp baseResp) {
+ switch (baseResp.errCode) {
+ case BaseResp.ErrCode.ERR_OK:
+ ShareUtil.mShareListener.shareSuccess();
+ break;
+ case BaseResp.ErrCode.ERR_USER_CANCEL:
+ ShareUtil.mShareListener.shareCancel();
+ break;
+ default:
+ ShareUtil.mShareListener.shareFailure(new Exception(baseResp.errStr));
+ }
+ }
+ });
+ }
+
+ @Override
+ public boolean isInstall(Context context) {
+ return mIWXAPI.isWXAppInstalled();
+ }
+
+ @Override
+ public void recycle() {
+ mIWXAPI.detach();
+ }
+
+ private void sendMessage(int platform, WXMediaMessage message, String transaction) {
+ SendMessageToWX.Req req = new SendMessageToWX.Req();
+ req.transaction = transaction;
+ req.message = message;
+ req.scene = platform == SharePlatform.WX_TIMELINE ? SendMessageToWX.Req.WXSceneTimeline
+ : SendMessageToWX.Req.WXSceneSession;
+ mIWXAPI.sendReq(req);
+ }
+
+ private String buildTransaction(String type) {
+ return System.currentTimeMillis() + type;
+ }
+
+}
diff --git a/share/src/main/jniLibs/arm64-v8a/libweibosdkcore.so b/share/src/main/jniLibs/arm64-v8a/libweibosdkcore.so
new file mode 100644
index 0000000..94a4567
Binary files /dev/null and b/share/src/main/jniLibs/arm64-v8a/libweibosdkcore.so differ
diff --git a/share/src/main/jniLibs/armeabi-v7a/libweibosdkcore.so b/share/src/main/jniLibs/armeabi-v7a/libweibosdkcore.so
new file mode 100644
index 0000000..a9495b6
Binary files /dev/null and b/share/src/main/jniLibs/armeabi-v7a/libweibosdkcore.so differ
diff --git a/share/src/main/jniLibs/armeabi/libweibosdkcore.so b/share/src/main/jniLibs/armeabi/libweibosdkcore.so
new file mode 100644
index 0000000..2d8fdf9
Binary files /dev/null and b/share/src/main/jniLibs/armeabi/libweibosdkcore.so differ
diff --git a/share/src/main/jniLibs/mips/libweibosdkcore.so b/share/src/main/jniLibs/mips/libweibosdkcore.so
new file mode 100644
index 0000000..8e22226
Binary files /dev/null and b/share/src/main/jniLibs/mips/libweibosdkcore.so differ
diff --git a/share/src/main/jniLibs/mips64/libweibosdkcore.so b/share/src/main/jniLibs/mips64/libweibosdkcore.so
new file mode 100644
index 0000000..d495237
Binary files /dev/null and b/share/src/main/jniLibs/mips64/libweibosdkcore.so differ
diff --git a/share/src/main/jniLibs/x86/libweibosdkcore.so b/share/src/main/jniLibs/x86/libweibosdkcore.so
new file mode 100644
index 0000000..44f794d
Binary files /dev/null and b/share/src/main/jniLibs/x86/libweibosdkcore.so differ
diff --git a/share/src/main/jniLibs/x86_64/libweibosdkcore.so b/share/src/main/jniLibs/x86_64/libweibosdkcore.so
new file mode 100644
index 0000000..a8776bb
Binary files /dev/null and b/share/src/main/jniLibs/x86_64/libweibosdkcore.so differ
diff --git a/share/src/main/res/drawable/ic_launcher_background.xml b/share/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..01f0af0
--- /dev/null
+++ b/share/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/share/src/main/res/drawable/ic_launcher_foreground.xml b/share/src/main/res/drawable/ic_launcher_foreground.xml
new file mode 100644
index 0000000..c7bd21d
--- /dev/null
+++ b/share/src/main/res/drawable/ic_launcher_foreground.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/share/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/share/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 0000000..bbd3e02
--- /dev/null
+++ b/share/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/share/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/share/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000..bbd3e02
--- /dev/null
+++ b/share/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/share/src/main/res/mipmap-hdpi/ic_launcher.png b/share/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..7df4e4c
Binary files /dev/null and b/share/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/share/src/main/res/mipmap-hdpi/ic_launcher_round.png b/share/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000..ebae12c
Binary files /dev/null and b/share/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/share/src/main/res/mipmap-mdpi/ic_launcher.png b/share/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..e29f86d
Binary files /dev/null and b/share/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/share/src/main/res/mipmap-mdpi/ic_launcher_round.png b/share/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000..f1f8b4b
Binary files /dev/null and b/share/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/share/src/main/res/mipmap-xhdpi/ic_launcher.png b/share/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..40387b7
Binary files /dev/null and b/share/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/share/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/share/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..9ace2ee
Binary files /dev/null and b/share/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/share/src/main/res/mipmap-xxhdpi/ic_launcher.png b/share/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..53613ff
Binary files /dev/null and b/share/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/share/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/share/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..2ed8ddb
Binary files /dev/null and b/share/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/share/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/share/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..be04bb8
Binary files /dev/null and b/share/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/share/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/share/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..57521ba
Binary files /dev/null and b/share/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/share/src/main/res/values/strings.xml b/share/src/main/res/values/strings.xml
new file mode 100644
index 0000000..3a9b9f9
--- /dev/null
+++ b/share/src/main/res/values/strings.xml
@@ -0,0 +1,4 @@
+
+ ShareLib
+ 分享
+