fluty 5 vuotta sitten
commit
164a70ac0a
100 muutettua tiedostoa jossa 4040 lisäystä ja 0 poistoa
  1. 10 0
      .gitignore
  2. 1 0
      app/.gitignore
  3. 46 0
      app/build.gradle
  4. BIN
      app/fqgamesdkkeystore.jks
  5. 21 0
      app/proguard-rules.pro
  6. 29 0
      app/src/main/AndroidManifest.xml
  7. 324 0
      app/src/main/java/com/funcheer/channel/sdk/MainActivity.java
  8. 19 0
      app/src/main/java/com/funcheer/channel/sdk/MainApp.java
  9. 34 0
      app/src/main/res/drawable-v24/ic_launcher_foreground.xml
  10. 170 0
      app/src/main/res/drawable/ic_launcher_background.xml
  11. 177 0
      app/src/main/res/layout/fq_activity_main.xml
  12. 5 0
      app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
  13. 5 0
      app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
  14. BIN
      app/src/main/res/mipmap-hdpi/ic_launcher.png
  15. BIN
      app/src/main/res/mipmap-hdpi/ic_launcher_round.png
  16. BIN
      app/src/main/res/mipmap-mdpi/ic_launcher.png
  17. BIN
      app/src/main/res/mipmap-mdpi/ic_launcher_round.png
  18. BIN
      app/src/main/res/mipmap-xhdpi/ic_launcher.png
  19. BIN
      app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
  20. BIN
      app/src/main/res/mipmap-xxhdpi/ic_launcher.png
  21. BIN
      app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
  22. BIN
      app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
  23. BIN
      app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
  24. 11 0
      app/src/main/res/values/colors.xml
  25. 9 0
      app/src/main/res/values/lingdo_styles.xml
  26. 25 0
      app/src/main/res/values/strings.xml
  27. 8 0
      app/src/main/res/values/styles.xml
  28. 28 0
      build.gradle
  29. 1 0
      fq_channel_huawei/.gitignore
  30. 33 0
      fq_channel_huawei/build.gradle
  31. 0 0
      fq_channel_huawei/consumer-rules.pro
  32. 21 0
      fq_channel_huawei/proguard-rules.pro
  33. 2 0
      fq_channel_huawei/src/main/AndroidManifest.xml
  34. 3 0
      fq_channel_huawei/src/main/res/values/strings.xml
  35. 1 0
      fq_channel_mubao/.gitignore
  36. 30 0
      fq_channel_mubao/build.gradle
  37. 0 0
      fq_channel_mubao/consumer-rules.pro
  38. 21 0
      fq_channel_mubao/proguard-rules.pro
  39. 2 0
      fq_channel_mubao/src/main/AndroidManifest.xml
  40. 4 0
      fq_channel_mubao/src/main/assets/fq_config/joint_cfg
  41. 17 0
      fq_channel_mubao/src/main/java/com/fq/channel/sdk/FQApplication.java
  42. 224 0
      fq_channel_mubao/src/main/java/com/fq/channel/sdk/MyDialog.java
  43. 385 0
      fq_channel_mubao/src/main/java/com/fq/channel/sdk/SdkPluginDemo.java
  44. 3 0
      fq_channel_mubao/src/main/res/values/strings.xml
  45. 1 0
      fq_channel_oppo/.gitignore
  46. 30 0
      fq_channel_oppo/build.gradle
  47. 0 0
      fq_channel_oppo/consumer-rules.pro
  48. 21 0
      fq_channel_oppo/proguard-rules.pro
  49. 2 0
      fq_channel_oppo/src/main/AndroidManifest.xml
  50. 4 0
      fq_channel_oppo/src/main/assets/fq_config/joint_cfg
  51. 17 0
      fq_channel_oppo/src/main/java/com/fq/channel/sdk/FQApplication.java
  52. 409 0
      fq_channel_oppo/src/main/java/com/fq/channel/sdk/SdkPluginOppo.java
  53. 3 0
      fq_channel_oppo/src/main/res/values/strings.xml
  54. 1 0
      fq_channel_ysdk/.gitignore
  55. 33 0
      fq_channel_ysdk/build.gradle
  56. 0 0
      fq_channel_ysdk/consumer-rules.pro
  57. 21 0
      fq_channel_ysdk/proguard-rules.pro
  58. 2 0
      fq_channel_ysdk/src/main/AndroidManifest.xml
  59. 3 0
      fq_channel_ysdk/src/main/res/values/strings.xml
  60. 1 0
      fq_plugin_api/.gitignore
  61. 32 0
      fq_plugin_api/build.gradle
  62. 0 0
      fq_plugin_api/consumer-rules.pro
  63. 21 0
      fq_plugin_api/proguard-rules.pro
  64. 2 0
      fq_plugin_api/src/main/AndroidManifest.xml
  65. 131 0
      fq_plugin_api/src/main/java/com/fq/channel/sdk/api/FqGame.java
  66. 42 0
      fq_plugin_api/src/main/java/com/fq/channel/sdk/api/bean/LoginInfo.java
  67. 42 0
      fq_plugin_api/src/main/java/com/fq/channel/sdk/api/bean/PayInfo.java
  68. 219 0
      fq_plugin_api/src/main/java/com/fq/channel/sdk/api/bean/PaymentInfo.java
  69. 50 0
      fq_plugin_api/src/main/java/com/fq/channel/sdk/api/bean/RoleInfo.java
  70. 3 0
      fq_plugin_api/src/main/res/values/strings.xml
  71. 1 0
      fq_plugin_base/.gitignore
  72. 28 0
      fq_plugin_base/build.gradle
  73. 0 0
      fq_plugin_base/consumer-rules.pro
  74. BIN
      fq_plugin_base/libs/android-support-v4.jar
  75. 21 0
      fq_plugin_base/proguard-rules.pro
  76. 2 0
      fq_plugin_base/src/main/AndroidManifest.xml
  77. 16 0
      fq_plugin_base/src/main/java/com/fq/channel/sdk/base/Exception/NoSuchFunctionException.java
  78. 9 0
      fq_plugin_base/src/main/java/com/fq/channel/sdk/base/Test.java
  79. 83 0
      fq_plugin_base/src/main/java/com/fq/channel/sdk/base/interfaces/FQPluginApi.java
  80. 124 0
      fq_plugin_base/src/main/java/com/fq/channel/sdk/base/interfaces/PluginResult.java
  81. 20 0
      fq_plugin_base/src/main/java/com/fq/channel/sdk/base/interfaces/PluginResultHandler.java
  82. 50 0
      fq_plugin_base/src/main/java/com/fq/channel/sdk/base/utils/ResourceCfg.java
  83. 340 0
      fq_plugin_base/src/main/java/com/fq/channel/sdk/base/utils/Utils.java
  84. 3 0
      fq_plugin_base/src/main/res/values/strings.xml
  85. 1 0
      fq_plugin_core/.gitignore
  86. 30 0
      fq_plugin_core/build.gradle
  87. 0 0
      fq_plugin_core/consumer-rules.pro
  88. 21 0
      fq_plugin_core/proguard-rules.pro
  89. 2 0
      fq_plugin_core/src/main/AndroidManifest.xml
  90. 64 0
      fq_plugin_core/src/main/java/com/fq/channel/sdk/core/JointManager.java
  91. 9 0
      fq_plugin_core/src/main/java/com/fq/channel/sdk/core/TestCore.java
  92. 93 0
      fq_plugin_core/src/main/java/com/fq/channel/sdk/core/invoke/ApiPlugin.java
  93. 76 0
      fq_plugin_core/src/main/java/com/fq/channel/sdk/core/invoke/ApiReflectManager.java
  94. 3 0
      fq_plugin_core/src/main/res/values/strings.xml
  95. 23 0
      gradle.properties
  96. BIN
      gradle/wrapper/gradle-wrapper.jar
  97. 6 0
      gradle/wrapper/gradle-wrapper.properties
  98. 172 0
      gradlew
  99. 84 0
      gradlew.bat
  100. 0 0
      settings.gradle

+ 10 - 0
.gitignore

@@ -0,0 +1,10 @@
+*.iml
+.gradle
+/local.properties
+.idea
+.DS_Store
+/build
+/captures
+.externalNativeBuild
+.cxx
+

+ 1 - 0
app/.gitignore

@@ -0,0 +1 @@
+/build

+ 46 - 0
app/build.gradle

@@ -0,0 +1,46 @@
+apply plugin: 'com.android.application'
+
+apply plugin: 'kotlin-android'
+
+apply plugin: 'kotlin-android-extensions'
+
+android {
+    compileSdkVersion 29
+    defaultConfig {
+        applicationId "com.funcheer.channel.sdk"
+        minSdkVersion 15
+        targetSdkVersion 29
+        versionCode 1
+        versionName "1.0"
+        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+    }
+
+    signingConfigs {
+//        release {
+//            storeFile file("./fqgamesdkkeystore.jks")
+//            storePassword '201868'
+//            keyPassword '201868'
+//            keyAlias 'fqgamesdkkeystore.jks'
+//            v2SigningEnabled false
+//        }
+//        debug{
+//            storeFile file("./fqgamesdkkeystore.jks")
+//            storePassword '201868'
+//            keyPassword '201868'
+//            keyAlias 'fqgamesdkkeystore.jks'
+//            v2SigningEnabled false
+//        }
+    }
+
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+        }
+    }
+}
+
+dependencies {
+    implementation fileTree(dir: 'libs', include: ['*.jar'])
+    api project(':fq_plugin_api')
+}

BIN
app/fqgamesdkkeystore.jks


+ 21 - 0
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

+ 29 - 0
app/src/main/AndroidManifest.xml

@@ -0,0 +1,29 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.fqchannelsdk">
+
+    <application
+        android:allowBackup="true"
+        android:icon="@mipmap/ic_launcher"
+        android:label="@string/app_name"
+        android:roundIcon="@mipmap/ic_launcher_round"
+        android:supportsRtl="true"
+        android:name="com.funcheer.channel.sdk.MainApp"
+        android:theme="@style/fq_AppTheme" >
+
+
+    <activity android:name="com.funcheer.channel.sdk.MainActivity"
+        android:configChanges="orientation|keyboardHidden|screenSize"
+        android:launchMode="singleTask"
+        android:screenOrientation="portrait"
+        android:theme="@style/fq_AppTheme"
+        >
+        <intent-filter>
+            <action android:name="android.intent.action.MAIN" />
+            <category android:name="android.intent.category.LAUNCHER" />
+        </intent-filter>
+    </activity>
+
+
+
+    </application>
+</manifest>

+ 324 - 0
app/src/main/java/com/funcheer/channel/sdk/MainActivity.java

@@ -0,0 +1,324 @@
+package com.funcheer.channel.sdk;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.View;
+import android.widget.EditText;
+import android.widget.Toast;
+
+import com.example.fqchannelsdk.R;
+import com.fq.channel.sdk.api.FqGame;
+import com.fq.channel.sdk.api.bean.LoginInfo;
+import com.fq.channel.sdk.api.bean.PaymentInfo;
+
+/**
+ * @Description: 描述
+ * @Author: FLuty
+ * @CreateDate: 2020/3/24 09:49
+ */
+public class MainActivity extends Activity implements View.OnClickListener {
+    private static final String TAG = "FQSDK_LOG"+MainActivity.class.getSimpleName();
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.fq_activity_main);
+        initUI();
+
+        initSDK();
+    }
+
+    //跟游戏的主Activity走
+    @Override
+    protected void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+        //保存状态
+    }
+
+    @Override
+    protected void onNewIntent(Intent intent) {
+        super.onNewIntent(intent);
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        super.onActivityResult(requestCode, resultCode, data);
+    }
+
+    @Override
+    protected void onRestart() {
+        super.onRestart();
+    }
+
+    @Override
+    protected void onStart() {
+        super.onStart();
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+
+    }
+
+    @Override
+    protected void onStop() {
+        super.onStop();
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+    }
+
+    private void initUI(){
+        findViewById(getResourceId("fq_login", "id")).setOnClickListener(this);
+        findViewById(getResourceId("fq_switch_account", "id")).setOnClickListener(this);
+        findViewById(getResourceId("fq_logout", "id")).setOnClickListener(this);
+        findViewById(getResourceId("fq_charge", "id")).setOnClickListener(this);
+        findViewById(getResourceId("fq_report_data", "id")).setOnClickListener(this);
+        findViewById(getResourceId("fq_exit", "id")).setOnClickListener(this);
+    }
+
+    @Override
+    public void onClick(View v) {
+        int id = v.getId();
+        switch (id){
+            case R.id.fq_login:
+                login();
+                break;
+
+            case R.id.fq_switch_account:
+                switch_account();
+                break;
+
+            case R.id.fq_logout:
+                logout();
+                break;
+
+            case R.id.fq_report_data:
+                dataReport();
+                break;
+
+            case R.id.fq_charge:
+                charge();
+                break;
+
+            case R.id.fq_exit:
+                exit();
+                break;
+
+            default:
+                break;
+        }
+    }
+
+    private int getResourceId(String name, String defType){
+        return this.getResources().getIdentifier(name, defType, this.getPackageName());
+    }
+
+    private void initSDK(){
+        FqGame.init(MainActivity.this, new FqGame.IResult<String>() {
+            @Override
+            public void onSuccess(String s) {
+                Log.i(TAG,"init success: "+s);
+            }
+
+            @Override
+            public void onFail(String failMsg) {
+                Log.i(TAG,"init fail:"+failMsg);
+            }
+        });
+    }
+
+
+    private void login(){
+        FqGame.login(MainActivity.this, new FqGame.IResult<LoginInfo>() {
+            @Override
+            public void onSuccess(LoginInfo s) {
+                Log.i(TAG,"login success: "+s.getUid());
+            }
+
+            @Override
+            public void onFail(String failMsg) {
+                Log.i(TAG,"login fail:"+failMsg);
+            }
+        });
+    }
+
+    public void charge(){
+        //get price
+        String priceString = ((EditText)findViewById(getResourceId("fq_charge_price",
+                "id"))).getText().toString();
+        if (TextUtils.isEmpty(priceString)){
+            showResult("请先填入价格");
+            return;
+        }
+
+        float price = Float.parseFloat(priceString);
+        Log.d(TAG,"price : "+price);
+        PaymentInfo paymentInfo = new PaymentInfo();
+        paymentInfo.setOrderAmount("1");            //订单金额           必须字段
+        paymentInfo.setSubject("1元宝");              //商品名             必须字段
+        paymentInfo.setRoleName("Hello");           //角色名             必须字段
+        paymentInfo.setCpBillNo("cp_order001");    //CP订单号           必须字段
+//        paymentInfo.setUid(uid);                    //登录时成功拿到的UID  必须字段
+        paymentInfo.setServerId("1");               //区服ID             必须字段
+        paymentInfo.setExtraInfo("FqGameSdk");      //拓展信息            必须字段
+        paymentInfo.setRemark("remark");            //订单备注            非必须字段
+        paymentInfo.setRoleLevel("5");              //角色等级            非必须字段
+        paymentInfo.setRoleId("Role_001");          //订单备注            非必须字段
+        paymentInfo.setPartyName("帮派");            //帮派               非必须字段
+        paymentInfo.setServerName("区服名");         //区服名              非必须字段
+
+
+        FqGame.pay(MainActivity.this,paymentInfo, new FqGame.IResult<String>() {
+            @Override
+            public void onSuccess(String s) {
+                Log.i(TAG,"pay success: "+s);
+            }
+
+            @Override
+            public void onFail(String failMsg) {
+                Log.i(TAG,"pay fail:"+failMsg);
+            }
+        });
+    }
+
+    private void getChannelId() {
+    }
+
+
+
+    private void exit() {// 退出接口
+    }
+
+    private void showGameExitView(){
+        AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
+        builder.setTitle("游戏自带退出界面");
+        builder.setCancelable(false);
+        builder.setPositiveButton("退出",
+                new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog,
+                                        int which) {
+
+
+                        exitAppProcess(MainActivity.this);
+                    }
+                });
+        builder.show();
+    }
+
+    private void dismissFloatView() {
+    }
+
+    private void showFloatView() {
+    }
+
+    private void dataReport() {
+        //get report data type
+        String dataReportTypeString = ((EditText)findViewById(getResourceId("fq_report_type",
+                "id"))).getText().toString();
+        if (TextUtils.isEmpty(dataReportTypeString)){
+            showResult("请先填入上报类型");
+            return;
+        }
+
+        int dataReportType = Integer.parseInt(dataReportTypeString);
+
+        /**设置统计参数的方法,游戏在参数发出变化时都需要调用接口设置参数*/
+        /**====================================================
+         * ConstSet.DATA_KEY_ROLE_ID 当前登录的玩家角色ID
+         * ConstSet.DATA_KEY_ROLE_NAME 当前登录的玩家角色名
+         * ConstSet.DATA_KEY_ROLE_LEVEL 当前登录的玩家角色等级
+         * ConstSet.DATA_KEY_SERVER_ID 当前登录的游戏区服ID
+         * ConstSet.DATA_KEY_SERVER_NAME 当前登录的游戏区服名称
+         * ConstSet.DATA_KEY_BALANCE 当前用户游戏币余额
+         * ConstSet.DATA_KEY_VIP_LEVEL 当前用户VIP等级
+         * ConstSet.DATA_KEY_PARTY_NAME 当前用户所属帮派
+         * ConstSet.DATA_KEY_PARTY_NAME 角色创建时间(单位:秒),该时间请务必传入服务端真实角色创建时间。
+         * ConstSet.DATA_KEY_ROLE_LEVEL_TIME 角色等级变化时间(单位:秒),该时间请务必传入服务端真实角色升级时间。
+         *
+         * ConstSet.DATA_KEY_DATA_TYPE 数据统计类型,以下所有统计点必接):
+         * 1、创建角色,data type为0;
+         * 2、角色升级,data type为1;
+         * 3、上传区服信息,data type为2;
+         * 4、登录,data type为3;
+         * 5、进入游戏,data type为4;
+         * 6、支付,data type为5;
+         * 7、选择服务器,data type为6;
+         * 8、退出游戏,data type为7;
+         =======================================================*/
+        Bundle staticsData = new Bundle();
+//        staticsData.putString(ConstSet.DATA_KEY_ROLE_ID, "111");
+//        staticsData.putString(ConstSet.DATA_KEY_ROLE_NAME, "战士");
+//        staticsData.putString(ConstSet.DATA_KEY_ROLE_LEVEL, "65");
+//        staticsData.putString(ConstSet.DATA_KEY_SERVER_ID, "11");
+//        staticsData.putString(ConstSet.DATA_KEY_SERVER_NAME, "服务器");
+//        staticsData.putString(ConstSet.DATA_KEY_BALANCE, "102");
+//        staticsData.putString(ConstSet.DATA_KEY_VIP_LEVEL, "2");
+//        staticsData.putString(ConstSet.DATA_KEY_PARTY_NAME, "水果派");
+//        staticsData.putLong(ConstSet.DATA_KEY_ROLE_CREATE_TIME, System.currentTimeMillis() / 1000);
+//        staticsData.putLong(ConstSet.DATA_KEY_ROLE_LEVEL_TIME, System.currentTimeMillis() / 1000);
+//        staticsData.putString(ConstSet.DATA_KEY_ZONE_ID, "1");
+//        staticsData.putString(ConstSet.DATA_KEY_ZONE_NAME, "阿狸一区");
+//        staticsData.putInt(ConstSet.DATA_KEY_DATA_TYPE, dataReportType);
+
+//        Idsfq.setExtraBundle(staticsData);
+    }
+
+    private void logout() {
+    }
+
+    private void switch_account() {
+    }
+
+    private void showResult(String message){
+        Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
+    }
+
+    private void exitAppProcess(Activity activity){
+        if (!activity.isFinishing()){
+            activity.finish();
+        }
+        android.os.Process.killProcess(android.os.Process.myPid());
+        System.exit(0);
+    }
+
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        boolean isConsume = super.onKeyDown(keyCode, event);
+        switch (keyCode) {
+            case KeyEvent.KEYCODE_BACK:
+                isConsume = true;
+                exit();
+                break;
+        }
+
+        return isConsume;
+    }
+
+    @Override
+    public void onBackPressed() {
+        exit();
+    }
+
+    @Override
+    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[]
+            grantResults) {
+        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+    }
+}

+ 19 - 0
app/src/main/java/com/funcheer/channel/sdk/MainApp.java

@@ -0,0 +1,19 @@
+package com.funcheer.channel.sdk;
+
+import android.app.Application;
+import android.content.Context;
+
+import com.fq.channel.sdk.FQApplication;
+
+public class MainApp extends FQApplication {
+
+    @Override
+    public void attachBaseContext(Context base) {
+        super.attachBaseContext(base);
+    }
+
+    @Override
+    public void onCreate(){
+        super.onCreate();
+    }
+}

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 34 - 0
app/src/main/res/drawable-v24/ic_launcher_foreground.xml


+ 170 - 0
app/src/main/res/drawable/ic_launcher_background.xml

@@ -0,0 +1,170 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="108dp"
+    android:height="108dp"
+    android:viewportWidth="108"
+    android:viewportHeight="108">
+    <path
+        android:fillColor="#008577"
+        android:pathData="M0,0h108v108h-108z" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M9,0L9,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,0L19,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M29,0L29,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M39,0L39,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M49,0L49,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M59,0L59,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M69,0L69,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M79,0L79,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M89,0L89,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M99,0L99,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,9L108,9"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,19L108,19"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,29L108,29"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,39L108,39"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,49L108,49"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,59L108,59"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,69L108,69"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,79L108,79"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,89L108,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,99L108,99"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,29L89,29"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,39L89,39"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,49L89,49"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,59L89,59"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,69L89,69"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,79L89,79"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M29,19L29,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M39,19L39,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M49,19L49,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M59,19L59,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M69,19L69,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M79,19L79,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+</vector>

+ 177 - 0
app/src/main/res/layout/fq_activity_main.xml

@@ -0,0 +1,177 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:padding="20dp"
+    android:background="@color/fq_gray"
+    tools:context="com.funcheer.channel.sdk.MainActivity"    >
+
+    <ScrollView
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:orientation="vertical">
+
+            <LinearLayout
+                android:id="@+id/fq_user_module"
+                android:layout_alignParentTop="true"
+                android:layout_centerInParent="true"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:background="@color/fq_white"
+                android:orientation="vertical">
+
+                <TextView
+                    android:id="@+id/fq_user_tv"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:background="@color/fq_white"
+                    android:gravity="center"
+                    android:text="@string/fq_user" />
+
+                <Button
+                    android:id="@+id/fq_login"
+                    android:layout_marginTop="5dp"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:text="@string/fq_login" />
+
+                <Button
+                    android:id="@+id/fq_switch_account"
+                    android:layout_marginTop="5dp"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:text="@string/fq_switch_account" />
+
+                <Button
+                    android:id="@+id/fq_logout"
+                    android:layout_marginTop="5dp"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:text="@string/fq_logout" />
+
+            </LinearLayout>
+
+            <LinearLayout
+                android:id="@+id/fq_charge_module"
+                android:layout_width="match_parent"
+                android:layout_marginTop="20dp"
+                android:layout_centerInParent="true"
+                android:background="@color/fq_white"
+                android:layout_below="@+id/fq_user_module"
+                android:layout_height="wrap_content"
+                android:orientation="vertical">
+
+                <TextView
+                    android:id="@+id/fq_charge_module_tv"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:background="@color/fq_white"
+                    android:gravity="center"
+                    android:text="@string/fq_charge_module" />
+
+                <LinearLayout
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:orientation="horizontal">
+
+                    <TextView
+                        android:id="@+id/fq_input_price"
+                        android:layout_marginTop="10dp"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:background="@color/fq_white"
+                        android:gravity="center"
+                        android:text="@string/fq_input_price" />
+
+                    <EditText
+                        android:id="@+id/fq_charge_price"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:text="1"
+                        />
+
+                </LinearLayout>
+
+                <Button
+                    android:id="@+id/fq_charge"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_marginTop="5dp"
+                    android:layout_below="@+id/fq_charge_module"
+                    android:layout_centerInParent="true"
+                    android:text="@string/fq_charge" />
+
+            </LinearLayout>
+
+
+            <LinearLayout
+                android:id="@+id/fq_data_report_module"
+                android:layout_width="match_parent"
+                android:layout_marginTop="20dp"
+                android:layout_centerInParent="true"
+                android:background="@color/fq_white"
+                android:layout_below="@+id/fq_user_module"
+                android:layout_height="wrap_content"
+                android:orientation="vertical">
+
+                <TextView
+                    android:id="@+id/fq_data_report_module_tv"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:background="@color/fq_white"
+                    android:gravity="center"
+                    android:text="@string/fq_data_report_module_tv" />
+
+                <LinearLayout
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:orientation="horizontal">
+
+                    <TextView
+                        android:id="@+id/fq_input_report_type"
+                        android:layout_marginTop="10dp"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:background="@color/fq_white"
+                        android:gravity="center"
+                        android:text="@string/fq_input_report_type" />
+
+                    <EditText
+                        android:id="@+id/fq_report_type"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:text="4"
+                        />
+
+                </LinearLayout>
+
+                <Button
+                    android:id="@+id/fq_report_data"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_marginTop="5dp"
+                    android:layout_below="@+id/fq_charge_module"
+                    android:layout_centerInParent="true"
+                    android:text="@string/fq_report_data" />
+
+            </LinearLayout>
+
+
+            <Button
+                android:id="@+id/fq_exit"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="5dp"
+                android:layout_centerInParent="true"
+                android:text="@string/fq_exit" />
+
+        </LinearLayout>
+
+    </ScrollView>
+
+</RelativeLayout>

+ 5 - 0
app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+    <background android:drawable="@drawable/ic_launcher_background" />
+    <foreground android:drawable="@drawable/ic_launcher_foreground" />
+</adaptive-icon>

+ 5 - 0
app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+    <background android:drawable="@drawable/ic_launcher_background" />
+    <foreground android:drawable="@drawable/ic_launcher_foreground" />
+</adaptive-icon>

BIN
app/src/main/res/mipmap-hdpi/ic_launcher.png


BIN
app/src/main/res/mipmap-hdpi/ic_launcher_round.png


BIN
app/src/main/res/mipmap-mdpi/ic_launcher.png


BIN
app/src/main/res/mipmap-mdpi/ic_launcher_round.png


BIN
app/src/main/res/mipmap-xhdpi/ic_launcher.png


BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_round.png


BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher.png


BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png


BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher.png


BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png


+ 11 - 0
app/src/main/res/values/colors.xml

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <color name="colorPrimary">#008577</color>
+    <color name="colorPrimaryDark">#00574B</color>
+    <color name="colorAccent">#D81B60</color>
+    <color name="fq_colorPrimary">#3F51B5</color>
+    <color name="fq_colorPrimaryDark">#303F9F</color>
+    <color name="fq_colorAccent">#FF4081</color>
+    <color name="fq_white">#FFFFFF</color>
+    <color name="fq_gray">#F1F1F1</color>
+</resources>

+ 9 - 0
app/src/main/res/values/lingdo_styles.xml

@@ -0,0 +1,9 @@
+<resources>
+
+    <!-- Base application theme. -->
+    <style name="lingdo_AppTheme" parent="@android:style/Theme.NoTitleBar">
+        <item name="android:windowIsTranslucent">false</item>
+        <item name="android:windowDisablePreview">true</item>
+    </style>
+
+</resources>

+ 25 - 0
app/src/main/res/values/strings.xml

@@ -0,0 +1,25 @@
+<resources>
+    <string name="app_name">FQChannelSDK</string>
+    <string name="fq_result">result...</string>
+
+    <string name="fq_user">用户</string>
+    <string name="fq_login">登录</string>
+    <string name="fq_logout">注销</string>
+    <string name="fq_switch_account">切换账号</string>
+
+    <string name="fq_charge_module">支付</string>
+    <string name="fq_input_price">输入价格:</string>
+    <string name="fq_charge">支付</string>
+
+    <string name="fq_data_report_module_tv">数据上报</string>
+    <string name="fq_input_report_type">输入数据上报类型:</string>
+    <string name="fq_report_data">上报数据</string>
+
+    <string name="fq_show_float_view">显示浮层</string>
+    <string name="fq_hide_float_view">隐藏浮层</string>
+
+    <string name="fq_get_channel_id">获取渠道号</string>
+    <string name="fq_share">分享</string>
+
+    <string name="fq_exit">退出</string>
+</resources>

+ 8 - 0
app/src/main/res/values/styles.xml

@@ -0,0 +1,8 @@
+<resources>
+
+    <!-- Base application theme. -->
+    <style name="fq_AppTheme" parent="@android:style/Theme.NoTitleBar">
+        <item name="android:windowIsTranslucent">false</item>
+        <item name="android:windowDisablePreview">true</item>
+    </style>
+</resources>

+ 28 - 0
build.gradle

@@ -0,0 +1,28 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+    ext.kotlin_version = '1.3.41'
+    repositories {
+        google()
+        jcenter()
+        
+    }
+    dependencies {
+        classpath 'com.android.tools.build:gradle:3.5.0'
+        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+        // NOTE: Do not place your application dependencies here; they belong
+        // in the individual module build.gradle files
+    }
+}
+
+allprojects {
+    repositories {
+        google()
+        jcenter()
+        
+    }
+}
+
+task clean(type: Delete) {
+    delete rootProject.buildDir
+}

+ 1 - 0
fq_channel_huawei/.gitignore

@@ -0,0 +1 @@
+/build

+ 33 - 0
fq_channel_huawei/build.gradle

@@ -0,0 +1,33 @@
+apply plugin: 'com.android.library'
+
+android {
+    compileSdkVersion 29
+
+
+    defaultConfig {
+        minSdkVersion 15
+        targetSdkVersion 29
+        versionCode 1
+        versionName "1.0"
+
+        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+        consumerProguardFiles 'consumer-rules.pro'
+    }
+
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+        }
+    }
+
+}
+
+dependencies {
+    implementation fileTree(dir: 'libs', include: ['*.jar'])
+
+    implementation 'androidx.appcompat:appcompat:1.0.2'
+    testImplementation 'junit:junit:4.12'
+    androidTestImplementation 'androidx.test:runner:1.1.1'
+    androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
+}

+ 0 - 0
fq_channel_huawei/consumer-rules.pro


+ 21 - 0
fq_channel_huawei/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

+ 2 - 0
fq_channel_huawei/src/main/AndroidManifest.xml

@@ -0,0 +1,2 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.fq.channel.sdk" />

+ 3 - 0
fq_channel_huawei/src/main/res/values/strings.xml

@@ -0,0 +1,3 @@
+<resources>
+    <string name="app_name">fq_channel_huawei</string>
+</resources>

+ 1 - 0
fq_channel_mubao/.gitignore

@@ -0,0 +1 @@
+/build

+ 30 - 0
fq_channel_mubao/build.gradle

@@ -0,0 +1,30 @@
+apply plugin: 'com.android.library'
+
+android {
+    compileSdkVersion 29
+
+
+    defaultConfig {
+        minSdkVersion 15
+        targetSdkVersion 29
+        versionCode 1
+        versionName "1.0"
+
+        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+        consumerProguardFiles 'consumer-rules.pro'
+    }
+
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+        }
+    }
+
+}
+
+dependencies {
+    implementation fileTree(dir: 'libs', include: ['*.jar'])
+
+    api project(':fq_plugin_base')
+}

+ 0 - 0
fq_channel_mubao/consumer-rules.pro


+ 21 - 0
fq_channel_mubao/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

+ 2 - 0
fq_channel_mubao/src/main/AndroidManifest.xml

@@ -0,0 +1,2 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.fq.channel.sdk" />

+ 4 - 0
fq_channel_mubao/src/main/assets/fq_config/joint_cfg

@@ -0,0 +1,4 @@
+{
+"plugin_name": "testchannel",
+"plugin_sdk_class_name":"com.fq.channel.sdk.SdkPluginDemo"
+}

+ 17 - 0
fq_channel_mubao/src/main/java/com/fq/channel/sdk/FQApplication.java

@@ -0,0 +1,17 @@
+package com.fq.channel.sdk;
+
+import android.app.Application;
+import android.util.Log;
+
+public class FQApplication extends Application{
+
+	private String TAG = getClass().getSimpleName() ;
+	
+	@Override
+	public void onCreate() {
+		super.onCreate();
+		Log.d(TAG, "FQApplication->onCreate") ;
+	}
+	
+		
+}

+ 224 - 0
fq_channel_mubao/src/main/java/com/fq/channel/sdk/MyDialog.java

@@ -0,0 +1,224 @@
+package com.fq.channel.sdk;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.os.Bundle;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.Button;
+import android.widget.TextView;
+
+public class MyDialog extends Dialog{
+
+	public MyDialog(Context context) {
+		super(context);
+	}
+
+	private Button yes;//确定按钮
+    private Button no;//否定按钮
+    private Button cancel; //取消按钮
+
+    private TextView titleTv;//消息标题文本
+    private TextView messageTv;//消息提示文本
+    private String titleStr;//从外界设置的title文本
+    private String messageStr;//从外界设置的消息文本
+
+    //确定文本和取消文本的显示内容
+    private String yesStr, noStr,cancelStr;
+
+    private YesOnclickListener yesOnclickListener;//确定按钮被点击了的监听器
+    private NoOnclickListener noOnclickListener;//否定按钮被点击了的监听器
+    private CancelOnclickListener cancelOnclickListener; //取消按钮被点击了的监听器
+
+    /**
+     * 设置确定按钮的显示内容和监听
+     *
+     * @param str
+     * @param onYesOnclickListener
+     */
+    public void setYesOnclickListener(String str, YesOnclickListener yesOnclickListener2) {
+        if (str != null) {
+            yesStr = str;
+        }
+        this.yesOnclickListener = yesOnclickListener2;
+    }
+
+    /**
+     * 设置否定按钮的显示内容和监听
+     *
+     * @param str
+     * @param onNoOnclickListener
+     */
+    public void setNoOnclickListener(String str, NoOnclickListener noOnclickListener) {
+        if (str != null) {
+            noStr = str;
+        }
+        this.noOnclickListener = noOnclickListener;
+    }
+
+    /**
+     * 设置取消按钮的显示内容和监听
+     *
+     * @param str
+     * @param onNoOnclickListener
+     */
+    public void setCancelOnclickListener(String str, CancelOnclickListener cancelOnclickListener) {
+        if (str != null) {
+        	cancelStr = str;
+        }
+        this.cancelOnclickListener = cancelOnclickListener;
+    }
+
+    /**
+     * 为Dialog设置标题
+     * @param title
+     */
+    public void setTitle(String title) {
+        titleStr = title;
+    }
+
+    /**
+     * 为Dialog设置dialog的message
+     * @param message
+     */
+    public void setMessage(String message) {
+        messageStr = message;
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+//        setContentView(R.layout.mydialog);
+
+        //为适应打包系统,打出母包jar  不能通过R文件来调用
+        LayoutInflater inflater = LayoutInflater.from(getContext());
+        View view = inflater.inflate(getContext().getResources().getIdentifier("mydialog", "layout", getContext().getPackageName()), null);
+        setContentView(view);
+
+        yes = (Button) findViewById(getContext().getResources().getIdentifier("yes", "id", getContext().getPackageName()));
+        no = (Button) findViewById(getContext().getResources().getIdentifier("no", "id", getContext().getPackageName()));
+        cancel = (Button) findViewById(getContext().getResources().getIdentifier("cancel", "id", getContext().getPackageName()));
+
+        titleTv = (TextView) findViewById(getContext().getResources().getIdentifier("title", "id", getContext().getPackageName()));
+        messageTv = (TextView) findViewById(getContext().getResources().getIdentifier("message", "id", getContext().getPackageName()));
+
+        //按空白处不能取消动画
+        setCanceledOnTouchOutside(false);
+
+
+//        //初始化界面控件
+//        initView();
+        //初始化界面数据
+        initData();
+        //初始化界面控件的事件
+        initEvent();
+
+    }
+
+//    /**
+//     * 初始化界面控件
+//     */
+//    private void initView() {
+//        yes = (Button) findViewById(R.id.yes);
+//        no = (Button) findViewById(R.id.no);
+//        cancel = (Button) findViewById(R.id.cancel);
+//
+//        titleTv = (TextView) findViewById(R.id.title);
+//        messageTv = (TextView) findViewById(R.id.message);
+//    }
+
+
+    /**
+     * 初始化界面控件的显示数据
+     */
+    private void initData() {
+        //如果用户自定了title和message
+        if (titleStr != null) {
+            titleTv.setText(titleStr);
+        }
+        if (messageStr != null) {
+            messageTv.setText(messageStr);
+        }
+        //如果设置按钮的文字
+        if (yesStr != null) {
+            yes.setText(yesStr);
+        }
+        if (noStr != null) {
+            no.setText(noStr);
+        }
+        if (cancelStr != null) {
+            cancel.setText(cancelStr);
+        }
+    }
+
+    /**
+     * 初始化界面的确定和取消监听器
+     */
+    private void initEvent() {
+
+        //设置确定按钮被点击后,向外界提供监听
+        yes.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                if (yesOnclickListener != null) {
+                	yesOnclickListener.YesOnClick();
+                }
+            }
+        });
+
+        //设置否定按钮被点击后,向外界提供监听
+        no.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                if (noOnclickListener != null) {
+                    noOnclickListener.NoOnClick();
+                }
+            }
+        });
+
+        //设置取消按钮被点击后,向外界提供监听
+        cancel.setOnClickListener(new View.OnClickListener() {
+			@Override
+			public void onClick(View v) {
+				if (cancelOnclickListener != null) {
+					cancelOnclickListener.CancelOnClick();
+				}
+			}
+		});
+
+    }
+
+
+    /**
+     * 设置确定按钮、否定和取消被点击的接口
+     */
+    public interface YesOnclickListener {
+        public void YesOnClick();
+    }
+
+    public interface NoOnclickListener {
+        public void NoOnClick();
+    }
+
+    public interface CancelOnclickListener{
+    	public void CancelOnClick();
+    }
+
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        if (keyCode == KeyEvent.KEYCODE_BACK) {
+        	if (cancelOnclickListener != null) {
+				cancelOnclickListener.CancelOnClick();
+			}
+        	return true;
+        }
+
+        return false;
+    }
+}
+
+
+
+

+ 385 - 0
fq_channel_mubao/src/main/java/com/fq/channel/sdk/SdkPluginDemo.java

@@ -0,0 +1,385 @@
+package com.fq.channel.sdk;
+
+import android.app.Activity;
+import android.app.AlertDialog.Builder;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnKeyListener;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.widget.Toast;
+
+import com.fq.channel.sdk.base.interfaces.FQPluginApi;
+import com.fq.channel.sdk.base.interfaces.PluginResult;
+import com.fq.channel.sdk.base.interfaces.PluginResultHandler;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.Map;
+
+public class SdkPluginDemo extends FQPluginApi {
+
+    private static final String TAG = "FQSDK_LOGSdkPluginDemo";
+
+    /**
+     * 数据统计
+     */
+    private int dataType;
+    private String roleId, roleName, roleLevel, zoneId, zoneName, serverId, serverName, balance, vipLevel, partyName;
+
+    /**
+     * 初始化
+     */
+    @Override
+    public void init(Context activity,final PluginResultHandler handler) {
+        Log.i(TAG, "init");
+        handler.onHandlePluginResult(new PluginResult(
+                PluginResult.Status.OK));
+    }
+
+    /**
+     * 登录
+     */
+    @Override
+    public void login(final Context activity, final PluginResultHandler handler) {
+        Log.i(TAG, "login");
+
+        Builder builder = new Builder(activity);
+        builder.setTitle("登录");
+        builder.setMessage("请选择登录操作");
+        builder.setCancelable(false);
+        builder.setPositiveButton("确认", new DialogInterface.OnClickListener() {
+            public void onClick(DialogInterface dialog, int which) {
+                JSONObject jo = new JSONObject();
+                try {
+                    jo.put("uid", "uid");
+                    jo.put("token", "token");
+                    handler.onHandlePluginResult(new PluginResult(
+                            PluginResult.Status.OK, jo));
+                } catch (JSONException e) {
+                    e.printStackTrace();
+                }
+
+                dialog.dismiss();
+            }
+        });
+        builder.setNeutralButton("失败", new DialogInterface.OnClickListener() {
+            public void onClick(DialogInterface dialog, int which) {
+                handler.onHandlePluginResult(new PluginResult(
+                        PluginResult.Status.ERROR, "登录失败"));
+                dialog.dismiss();
+            }
+        });
+        builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
+            public void onClick(DialogInterface dialog, int which) {
+                handler.onHandlePluginResult(new PluginResult(
+                        PluginResult.Status.CANCEL));
+                dialog.dismiss();
+            }
+        });
+        builder.setOnKeyListener(new OnKeyListener() {
+
+            @Override
+            public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
+                if (keyCode == KeyEvent.KEYCODE_BACK) {
+                    handler.onHandlePluginResult(new PluginResult(
+                            PluginResult.Status.CANCEL));
+                    dialog.dismiss();
+                    return true;
+                }
+                return false;
+            }
+        });
+        builder.create().show();
+    }
+
+    @Override
+    public void pay(final Context activity, final Map<String, Object> map,
+                    final PluginResultHandler handler) {
+        Log.i(TAG, "pay map:" + (map != null ? map.toString() : ""));
+
+        Builder builder = new Builder(activity);
+        builder.setTitle("支付");
+        builder.setMessage("请选择支付操作");
+        builder.setCancelable(false);
+        builder.setPositiveButton("确认", new DialogInterface.OnClickListener() {
+            public void onClick(DialogInterface dialog, int which) {
+                handler.onHandlePluginResult(new PluginResult(
+                        PluginResult.Status.OK));
+                dialog.dismiss();
+            }
+        });
+        builder.setNeutralButton("失败", new DialogInterface.OnClickListener() {
+            public void onClick(DialogInterface dialog, int which) {
+                handler.onHandlePluginResult(new PluginResult(
+                        PluginResult.Status.ERROR));
+                dialog.dismiss();
+            }
+        });
+        builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
+            public void onClick(DialogInterface dialog, int which) {
+                handler.onHandlePluginResult(new PluginResult(
+                        PluginResult.Status.CANCEL));
+                dialog.dismiss();
+            }
+        });
+        builder.setOnKeyListener(new OnKeyListener() {
+
+            @Override
+            public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
+                if (keyCode == KeyEvent.KEYCODE_BACK) {
+                    handler.onHandlePluginResult(new PluginResult(
+                            PluginResult.Status.CANCEL));
+                    dialog.dismiss();
+                    return true;
+                }
+                return false;
+            }
+        });
+        builder.create().show();
+    }
+
+    /**
+     * 退出
+     *
+     * @param context
+     * @param prh
+     */
+    public void exit(Context context, PluginResultHandler prh) {
+        Log.d(TAG, "exit");
+
+        prh.onHandlePluginResult(new PluginResult(
+                PluginResult.Status.CANCEL));
+    }
+
+    /**
+     * 注销
+     */
+    public void logout(final Context context, final PluginResultHandler cb) {
+        Log.d(TAG, "logout");
+
+        Builder builder = new Builder(context);
+        builder.setTitle("注销");
+        builder.setMessage("是否注销?");
+        builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
+
+            @Override
+            public void onClick(DialogInterface dialog, int which) {
+                Log.d(TAG, "注销成功");
+                cb.onHandlePluginResult(new PluginResult(
+                        PluginResult.Status.OK));
+            }
+        });
+        builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
+
+            @Override
+            public void onClick(DialogInterface dialog, int which) {
+                Log.d(TAG, "注销失败");
+                cb.onHandlePluginResult(new PluginResult(
+                        PluginResult.Status.ERROR));
+            }
+        });
+        builder.show();
+    }
+
+    @Override
+    public void changeAccount(Activity activity, final PluginResultHandler prh) {
+        Log.d(TAG, " changeAccount ");
+
+        Builder builder = new Builder(activity);
+        builder.setTitle("切换账号");
+        builder.setMessage("请选择切换账号操作");
+        builder.setCancelable(false);
+        builder.setPositiveButton("确认", new DialogInterface.OnClickListener() {
+            public void onClick(DialogInterface dialog, int which) {
+
+                dialog.dismiss();
+            }
+        });
+        builder.setNeutralButton("失败", new DialogInterface.OnClickListener() {
+            public void onClick(DialogInterface dialog, int which) {
+                dialog.dismiss();
+            }
+        });
+        builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
+            public void onClick(DialogInterface dialog, int which) {
+                dialog.dismiss();
+            }
+        });
+        builder.setOnKeyListener(new OnKeyListener() {
+
+            @Override
+            public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
+                if (keyCode == KeyEvent.KEYCODE_BACK) {
+                    dialog.dismiss();
+                    return true;
+                }
+                return false;
+            }
+        });
+
+
+        builder.create().show();
+    }
+
+
+    private void showTips(final String message) {
+        Handler handler = new Handler(Looper.getMainLooper());
+        handler.post(new Runnable() {
+
+            @Override
+            public void run() {
+//				Activity activity = IdsLingdoCache.get().getCurrentActivity();
+//				if (null != activity){
+//					Toast.makeText(activity, message, Toast.LENGTH_SHORT).show();
+//				}
+            }
+        });
+    }
+
+    /**
+     * 游戏角色信息
+     *
+     * @param data
+     */
+    public void setExtraBundle(Bundle data) {
+        if (null == data) {
+            data = new Bundle();
+        }
+        Log.i(TAG, "setExtraBundle data:" + data.toString());
+
+        roleName = data.getString("roleName");// 角色名称
+        roleLevel = data.getString("roleLevel");//当前登录的玩家角色等级
+        roleId = data.getString("roleId");// 角色名称
+        serverId = data.getString("serverId"); //当前登录的游戏区服ID
+        serverName = data.getString("serverName");//当前登录的游戏区服名称
+        balance = data.getString("balance");//当前用户游戏币余额
+        vipLevel = data.getString("vipLevel");//当前用户VIP等级
+        partyName = data.getString("partyName");//当前用户所属帮派
+        zoneId = data.getString("zoneId");//角色所在区域唯一标示
+        zoneName = data.getString("zoneName");//角色所在区域名称
+        dataType = data.getInt("dataType");//统计判断类型
+
+        StringBuffer reportData = new StringBuffer();
+        reportData.append("[");
+        reportData.append(" roleName:" + roleName);
+        reportData.append(" roleLevel:" + roleLevel);
+        reportData.append(" roleId:" + roleId);
+        reportData.append(" serverId:" + serverId);
+        reportData.append(" serverName:" + serverName);
+        reportData.append(" balance:" + balance);
+        reportData.append(" vipLevel:" + vipLevel);
+        reportData.append(" partyName:" + zoneId);
+        reportData.append(" zoneName:" + zoneName);
+        reportData.append(" dataType:" + dataType);
+        reportData.append("]");
+
+        switch (dataType) {
+            case 0://创建角色
+                showTips("数据上报:创建角色 ");
+                Log.i(TAG, "reportData" + reportData);
+                break;
+
+            case 1://角色升级
+                showTips("数据上报:角色升级");
+                Log.i(TAG, "reportData" + reportData);
+                break;
+
+            case 2:// 上传区服信息
+                showTips("数据上报:上传区服信息");
+                Log.i(TAG, "reportData" + reportData);
+                break;
+
+            case 3://登录
+                showTips("数据上报:登录");
+                Log.i(TAG, "reportData" + reportData);
+                break;
+
+            case 4://支付
+                showTips("数据上报:进入游戏");
+                Log.i(TAG, "reportData" + reportData);
+                break;
+
+            case 5:// 选择服务器
+                showTips("数据上报:支付");
+                Log.i(TAG, "reportData" + reportData);
+                break;
+
+            case 6://退出游戏
+                showTips("数据上报:退出游戏");
+                Log.i(TAG, "reportData" + reportData);
+                break;
+
+            case 7:// 备注(预留参数)
+                showTips("数据上报:退出游戏");
+                Log.i(TAG, "reportData" + reportData);
+                break;
+
+            default:
+                break;
+        }
+    }
+
+    @Override
+    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
+
+    }
+
+    /**
+     * 复写生命周期方法,里面调用
+     */
+    public void onStart(Context context) {
+        Log.i(TAG, "onStart");
+    }
+
+    public void onCreate(Context context, Bundle handler) {
+        Log.i(TAG, "onCreate");
+    }
+
+    public void onRestart(Context context) {
+        Log.i(TAG, "onRestart");
+    }
+
+    public void onResume(Context context) {
+        Log.i(TAG, "onResume");
+    }
+
+    public void onPause(Context context) {
+        Log.i(TAG, "onPause");
+    }
+
+    public void onStop(Context context) {
+        Log.i(TAG, "onStop");
+    }
+
+    public void onDestroy(Context context) {
+        Log.i(TAG, "onDestroy");
+    }
+
+    public void onActivityResult(int requestCode, int resultCode, Intent data) {
+        Log.i(TAG, "onActivityResult requestCode:" + requestCode + " resultCode:" + resultCode + " data:" + data);
+    }
+
+    public void onNewIntent(Intent intent) {
+        Log.i(TAG, "onNewIntent");
+    }
+
+    @Override
+    public void attachBaseContext(Context context) {
+
+    }
+
+    @Override
+    public void onApplicationCreate(Context context) {
+
+    }
+
+    public void onSaveInstanceState(Context context, Bundle outState) {
+        Log.i(TAG, "onSaveInstanceState");
+    }
+}

+ 3 - 0
fq_channel_mubao/src/main/res/values/strings.xml

@@ -0,0 +1,3 @@
+<resources>
+    <string name="app_name">fq_channel_mubao</string>
+</resources>

+ 1 - 0
fq_channel_oppo/.gitignore

@@ -0,0 +1 @@
+/build

+ 30 - 0
fq_channel_oppo/build.gradle

@@ -0,0 +1,30 @@
+apply plugin: 'com.android.library'
+
+android {
+    compileSdkVersion 29
+
+
+    defaultConfig {
+        minSdkVersion 15
+        targetSdkVersion 29
+        versionCode 1
+        versionName "1.0"
+
+        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+        consumerProguardFiles 'consumer-rules.pro'
+    }
+
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+        }
+    }
+
+}
+
+dependencies {
+    implementation fileTree(dir: 'libs', include: ['*.jar'])
+
+    api project(':fq_plugin_base')
+}

+ 0 - 0
fq_channel_oppo/consumer-rules.pro


+ 21 - 0
fq_channel_oppo/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

+ 2 - 0
fq_channel_oppo/src/main/AndroidManifest.xml

@@ -0,0 +1,2 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.fq.channel.sdk" />

+ 4 - 0
fq_channel_oppo/src/main/assets/fq_config/joint_cfg

@@ -0,0 +1,4 @@
+{
+"plugin_name": "testchannel",
+"plugin_sdk_class_name":"com.fq.channel.sdk.SdkPluginOppo"
+}

+ 17 - 0
fq_channel_oppo/src/main/java/com/fq/channel/sdk/FQApplication.java

@@ -0,0 +1,17 @@
+package com.fq.channel.sdk;
+
+import android.app.Application;
+import android.util.Log;
+
+public class FQApplication extends Application{
+
+	private String TAG = getClass().getSimpleName() ;
+	
+	@Override
+	public void onCreate() {
+		super.onCreate();
+		Log.d(TAG, "FQApplication->onCreate") ;
+	}
+	
+		
+}

+ 409 - 0
fq_channel_oppo/src/main/java/com/fq/channel/sdk/SdkPluginOppo.java

@@ -0,0 +1,409 @@
+package com.fq.channel.sdk;
+
+import android.app.Activity;
+import android.app.AlertDialog.Builder;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnKeyListener;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.widget.Toast;
+
+import com.fq.channel.sdk.base.interfaces.FQPluginApi;
+import com.fq.channel.sdk.base.interfaces.PluginResult;
+import com.fq.channel.sdk.base.interfaces.PluginResultHandler;
+
+import java.util.Map;
+
+public class SdkPluginOppo extends FQPluginApi {
+
+	private static final String TAG = "FQSDK_LOGSdkPluginOppo";
+ 
+	/**
+	 * 数据统计
+	 */
+	private int dataType;
+	private String roleId,roleName,roleLevel,zoneId,zoneName,serverId,serverName,balance,vipLevel,partyName; 
+
+	/**
+	 * 初始化
+	 */
+	@Override
+	public void init(Context activity, Map<String, Object> map,
+			final PluginResultHandler handler) {
+		Log.i(TAG, "init");
+		handler.onHandlePluginResult(new PluginResult(
+				PluginResult.Status.OK));
+	}
+
+	/**
+	 * 登录
+	 */
+	@Override
+	public void login(final Context activity, final PluginResultHandler handler) {
+		Log.i(TAG, "login ");
+		
+		Builder builder = new Builder(activity);
+        builder.setTitle("登录");  
+        builder.setMessage("请选择登录操作");  
+        builder.setCancelable(false);
+        builder.setPositiveButton("确认", new DialogInterface.OnClickListener() {  
+            public void onClick(DialogInterface dialog, int which) {
+            	
+//            	//登陆乐逗服务器:
+//        		String path = "sns/ChannelLogin?channel_id=" + IdsLingdoCache.get().getChannelId()  //渠道ID
+//        				+ "&channel_en_name="+ "test"   //测试参数【必须】
+//        				+ "&channel_version="+ "1.0"   //测试参数【必须】
+//        				+ "&sign="+ "6d5c4bdc86f7d8cf"   //测试参数【必须】
+//        				+ "&imei="+ "862845022982883"   // 移动设备的电子串号
+//        				+ "&udid=" + "00000000-3dc7-ef39-331c-0c2b0033c587"  //设备标识
+//        				+ "&uid=" + "34536434645645"
+//        				+ "&token=" + "7f34536434645645";
+//
+//        		HashMap<String, String> loginAuthData = new HashMap<String, String>(1);
+//        		loginAuthData.put(ApiPluginConstants.PARAMS_LOGIN_OAUTH_URL, path);
+				handler.onHandlePluginResult(new PluginResult(
+						PluginResult.Status.OK,"登录成功"));
+        		dialog.dismiss();
+            }  
+        });  
+        builder.setNeutralButton("失败", new DialogInterface.OnClickListener() {  
+            public void onClick(DialogInterface dialog, int which) {
+				handler.onHandlePluginResult(new PluginResult(
+						PluginResult.Status.ERROR,"登录失败"));
+            	dialog.dismiss();
+            }  
+        });  
+        builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {  
+            public void onClick(DialogInterface dialog, int which) {  
+				handler.onHandlePluginResult(new PluginResult(
+						PluginResult.Status.CANCEL));
+            	dialog.dismiss();
+            }  
+        });  
+        builder.setOnKeyListener(new OnKeyListener() {
+			
+			@Override
+			public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
+				if (keyCode == KeyEvent.KEYCODE_BACK) {
+					handler.onHandlePluginResult(new PluginResult(
+							PluginResult.Status.CANCEL));
+	            	dialog.dismiss();
+	            	return true;
+		        } 
+            	return false;
+			}
+		});
+        builder.create().show();
+	}
+
+	@Override
+	public void pay(final Context activity, final Map<String, Object> map,
+			final PluginResultHandler handler) {
+		Log.i(TAG, "pay map:"+ (map != null?map.toString():"")); 
+
+		Builder builder = new Builder(activity);
+        builder.setTitle("支付");  
+        builder.setMessage("请选择支付操作");  
+        builder.setCancelable(false);
+        builder.setPositiveButton("确认", new DialogInterface.OnClickListener() {  
+            public void onClick(DialogInterface dialog, int which) { 
+				handler.onHandlePluginResult(new PluginResult(
+						PluginResult.Status.OK));
+        		dialog.dismiss();
+            }  
+        });  
+        builder.setNeutralButton("失败", new DialogInterface.OnClickListener() {  
+            public void onClick(DialogInterface dialog, int which) {   
+				handler.onHandlePluginResult(new PluginResult(
+						PluginResult.Status.ERROR));
+            	dialog.dismiss();
+            }  
+        });  
+        builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {  
+            public void onClick(DialogInterface dialog, int which) {  
+				handler.onHandlePluginResult(new PluginResult(
+						PluginResult.Status.CANCEL));
+            	dialog.dismiss();
+            }  
+        });  
+        builder.setOnKeyListener(new OnKeyListener() {
+			
+			@Override
+			public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
+				if (keyCode == KeyEvent.KEYCODE_BACK) {
+					handler.onHandlePluginResult(new PluginResult(
+							PluginResult.Status.CANCEL));
+	            	dialog.dismiss();
+	            	return true;
+		        } 
+            	return false;
+			}
+		});
+        builder.create().show();
+	}
+
+	/**
+	 * 退出
+	 * @param context
+	 * @param prh
+	 */
+	public void exit(Context context,PluginResultHandler prh){
+		Log.d(TAG, "exit");
+
+		prh.onHandlePluginResult(new PluginResult(
+				PluginResult.Status.CANCEL));
+	}
+
+	/**
+	 * 注销
+	 */
+	public void logout(final Context context,final PluginResultHandler cb){
+		Log.d(TAG, "logout");
+ 
+		Builder builder = new Builder(context);
+		builder.setTitle("注销");
+		builder.setMessage("是否注销?");
+		builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
+
+			@Override
+			public void onClick(DialogInterface dialog, int which) {
+				Log.d(TAG, "注销成功");
+				cb.onHandlePluginResult(new PluginResult(
+						PluginResult.Status.OK));
+			}
+		}); 
+		builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
+
+			@Override
+			public void onClick(DialogInterface dialog, int which) {
+				Log.d(TAG, "注销失败");
+				cb.onHandlePluginResult(new PluginResult(
+						PluginResult.Status.ERROR));
+			}
+		});
+		builder.show(); 
+	}
+
+	@Override
+	public void changeAccount(Activity activity, final PluginResultHandler prh) {
+		Log.d(TAG, " changeAccount ");
+
+		Builder builder = new Builder(activity);
+		builder.setTitle("切换账号");
+		builder.setMessage("请选择切换账号操作");
+		builder.setCancelable(false);
+		builder.setPositiveButton("确认", new DialogInterface.OnClickListener() {
+			public void onClick(DialogInterface dialog, int which) {
+
+				dialog.dismiss();
+			}
+		});
+		builder.setNeutralButton("失败", new DialogInterface.OnClickListener() {
+			public void onClick(DialogInterface dialog, int which) {
+				dialog.dismiss();
+			}
+		});
+		builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
+			public void onClick(DialogInterface dialog, int which) {
+				dialog.dismiss();
+			}
+		});
+		builder.setOnKeyListener(new OnKeyListener() {
+
+			@Override
+			public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
+				if (keyCode == KeyEvent.KEYCODE_BACK) {
+					dialog.dismiss();
+					return true;
+				}
+				return false;
+			}
+		});
+
+
+		builder.create().show();
+	}
+
+
+	private void showTips(final String message){ 
+		Handler handler = new Handler(Looper.getMainLooper());
+		handler.post(new Runnable() {
+			
+			@Override
+			public void run() { 
+//				Activity activity = IdsLingdoCache.get().getCurrentActivity();
+//				if (null != activity){
+//					Toast.makeText(activity, message, Toast.LENGTH_SHORT).show();
+//				}
+			}
+		});
+	}
+
+	/**
+	 * 游戏角色信息
+	 * @param data
+	 */
+	public void setExtraBundle(Bundle data){ 
+		if(null == data){
+			data = new Bundle();
+		}
+		Log.i(TAG, "setExtraBundle data:"+data.toString());
+
+		roleName =  data.getString("roleName") ;// 角色名称
+		roleLevel =  data.getString("roleLevel") ;//当前登录的玩家角色等级
+		roleId =  data.getString("roleId") ;// 角色名称
+		serverId = data.getString("serverId"); //当前登录的游戏区服ID
+		serverName =  data.getString("serverName") ;//当前登录的游戏区服名称
+		balance =  data.getString("balance") ;//当前用户游戏币余额
+		vipLevel =  data.getString("vipLevel") ;//当前用户VIP等级
+		partyName =  data.getString("partyName") ;//当前用户所属帮派
+		zoneId  = data.getString("zoneId") ;//角色所在区域唯一标示
+		zoneName  = data.getString("zoneName") ;//角色所在区域名称
+		dataType  = data.getInt("dataType") ;//统计判断类型
+
+		StringBuffer reportData = new StringBuffer();
+		reportData.append("[");
+		reportData.append(" roleName:"+roleName);
+		reportData.append(" roleLevel:"+roleLevel);
+		reportData.append(" roleId:"+roleId);
+		reportData.append(" serverId:"+serverId);
+		reportData.append(" serverName:"+serverName);
+		reportData.append(" balance:"+balance);
+		reportData.append(" vipLevel:"+vipLevel);
+		reportData.append(" partyName:"+zoneId);
+		reportData.append(" zoneName:"+zoneName);
+		reportData.append(" dataType:"+dataType); 
+		reportData.append("]");
+		
+		switch(dataType){
+			case 0 ://创建角色 
+				showTips("数据上报:创建角色 ");
+				Log.i(TAG, "reportData"+reportData);
+				break;
+
+			case 1 ://角色升级
+				showTips("数据上报:角色升级");
+				Log.i(TAG, "reportData"+reportData);
+				break;
+
+			case 2 :// 上传区服信息
+				showTips("数据上报:上传区服信息");
+				Log.i(TAG, "reportData"+reportData);
+				break;
+
+			case 3 ://登录 
+				showTips("数据上报:登录");
+				Log.i(TAG, "reportData"+reportData);
+				break;
+
+			case 4 ://支付
+				showTips("数据上报:进入游戏");
+				Log.i(TAG, "reportData"+reportData);
+				break; 
+				
+			case 5 :// 选择服务器
+				showTips("数据上报:支付");
+				Log.i(TAG, "reportData"+reportData);
+				break;
+
+			case 6 ://退出游戏
+				showTips("数据上报:退出游戏");
+				Log.i(TAG, "reportData"+reportData);
+				break;
+
+			case 7 :// 备注(预留参数)
+				showTips("数据上报:退出游戏");
+				Log.i(TAG, "reportData"+reportData);
+				break;
+
+			default:
+				break;
+		}
+	}
+
+	@Override
+	public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
+
+	}
+
+
+	/**
+	 * 释放资源时调用,当用户退出界面或者游戏的时候,
+	 * 调用此接口,释放资源才允许退出!
+	 * @param context
+	 */
+	public void releaseSdkResource(Context context){
+		Log.i(TAG, "releaseSdkResource");
+		
+		Toast.makeText(context, "释放SDK资源", Toast.LENGTH_SHORT).show();  
+		
+		try {
+			/**渠道存在退出界面,此处游戏必须调用,begin*/
+		    Intent startMain = new Intent(Intent.ACTION_MAIN);
+		    startMain.addCategory(Intent.CATEGORY_HOME);
+		    startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+		    context.startActivity(startMain);
+		    /**渠道存在退出界面,此处游戏必须调用,end*/
+		} catch (Exception e) {
+			Log.e(TAG, "releaseSdkResource 抛出异常!") ;
+		}
+	} 
+
+	/**
+	 * 复写生命周期方法,里面调用
+	 */ 
+	public void onStart(Context context){
+		Log.i(TAG, "onStart");
+	}
+
+	public void onCreate(Context context, Bundle handler){
+		Log.i(TAG, "onCreate");
+	}
+
+	public void onRestart(Context context){
+		Log.i(TAG, "onRestart");
+	}
+
+	public void onResume(Context context){
+		Log.i(TAG, "onResume");
+	}
+
+	public void onPause(Context context){
+		Log.i(TAG, "onPause");
+	}
+
+	public void onStop(Context context){
+		Log.i(TAG, "onStop");
+	}
+
+	public void onDestroy(Context context){
+		Log.i(TAG, "onDestroy");
+	}
+
+	public void onActivityResult(int requestCode, int resultCode, Intent data){
+		Log.i(TAG, "onActivityResult requestCode:"+requestCode+" resultCode:"+resultCode+" data:"+data);
+	}
+
+	public void onNewIntent(Intent intent){
+		Log.i(TAG, "onNewIntent");
+	}
+
+	@Override
+	public void attachBaseContext(Context context) {
+
+	}
+
+	@Override
+	public void onApplicationCreate(Context context) {
+
+	}
+
+	public void onSaveInstanceState(Context context, Bundle outState){
+		Log.i(TAG, "onSaveInstanceState");
+	}
+}

+ 3 - 0
fq_channel_oppo/src/main/res/values/strings.xml

@@ -0,0 +1,3 @@
+<resources>
+    <string name="app_name">fq_channel_oppo</string>
+</resources>

+ 1 - 0
fq_channel_ysdk/.gitignore

@@ -0,0 +1 @@
+/build

+ 33 - 0
fq_channel_ysdk/build.gradle

@@ -0,0 +1,33 @@
+apply plugin: 'com.android.library'
+
+android {
+    compileSdkVersion 29
+
+
+    defaultConfig {
+        minSdkVersion 15
+        targetSdkVersion 29
+        versionCode 1
+        versionName "1.0"
+
+        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+        consumerProguardFiles 'consumer-rules.pro'
+    }
+
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+        }
+    }
+
+}
+
+dependencies {
+    implementation fileTree(dir: 'libs', include: ['*.jar'])
+
+    implementation 'androidx.appcompat:appcompat:1.0.2'
+    testImplementation 'junit:junit:4.12'
+    androidTestImplementation 'androidx.test:runner:1.1.1'
+    androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
+}

+ 0 - 0
fq_channel_ysdk/consumer-rules.pro


+ 21 - 0
fq_channel_ysdk/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

+ 2 - 0
fq_channel_ysdk/src/main/AndroidManifest.xml

@@ -0,0 +1,2 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.fq.channel.sdk" />

+ 3 - 0
fq_channel_ysdk/src/main/res/values/strings.xml

@@ -0,0 +1,3 @@
+<resources>
+    <string name="app_name">fq_channel_ysdk</string>
+</resources>

+ 1 - 0
fq_plugin_api/.gitignore

@@ -0,0 +1 @@
+/build

+ 32 - 0
fq_plugin_api/build.gradle

@@ -0,0 +1,32 @@
+apply plugin: 'com.android.library'
+
+android {
+    compileSdkVersion 29
+
+
+    defaultConfig {
+        minSdkVersion 15
+        targetSdkVersion 29
+        versionCode 1
+        versionName "1.0"
+
+        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+        consumerProguardFiles 'consumer-rules.pro'
+    }
+
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+        }
+    }
+
+}
+
+dependencies {
+    implementation fileTree(dir: 'libs', include: ['*.jar'])
+
+    api project(':fq_plugin_core')
+    api project(':fq_plugin_base')
+    api project(':fq_channel_mubao')
+}

+ 0 - 0
fq_plugin_api/consumer-rules.pro


+ 21 - 0
fq_plugin_api/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

+ 2 - 0
fq_plugin_api/src/main/AndroidManifest.xml

@@ -0,0 +1,2 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.fq.channel.sdk.api" />

+ 131 - 0
fq_plugin_api/src/main/java/com/fq/channel/sdk/api/FqGame.java

@@ -0,0 +1,131 @@
+package com.fq.channel.sdk.api;
+
+import android.app.Activity;
+import android.support.annotation.NonNull;
+import android.util.Log;
+
+import com.fq.channel.sdk.api.bean.LoginInfo;
+import com.fq.channel.sdk.api.bean.PaymentInfo;
+import com.fq.channel.sdk.base.interfaces.PluginResult.Status;
+import com.fq.channel.sdk.base.interfaces.PluginResult;
+import com.fq.channel.sdk.base.interfaces.PluginResultHandler;
+import com.fq.channel.sdk.base.utils.Utils;
+import com.fq.channel.sdk.core.JointManager;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.Map;
+
+/**
+ * @Description: 提供给CP访问的接口类
+ * @Author: FLuty
+ * @CreateDate: 2020/3/24 11:21
+ */
+public class FqGame {
+
+    private static final String TAG = "FQSDK_LOGFqGame";
+
+    /**
+     * 提过给CP调用的初始化接口
+     *
+     * @param activity
+     * @param resultInit
+     */
+    public static void init(@NonNull Activity activity, final IResult<String> resultInit) {
+        Log.i(TAG, "init");
+        JointManager.getInstance().init(activity, new PluginResultHandler() {
+            @Override
+            public void onHandlePluginResult(PluginResult result) {
+                Status mStatus = result.getStatus();
+                Log.i(TAG, "init mStatus :" + mStatus);
+                if (Status.OK == mStatus) {
+                    resultInit.onSuccess(result.getMessage());
+                } else if (Status.CANCEL == mStatus) {
+                    resultInit.onFail(result.getMessage());
+                } else if (Status.ERROR == mStatus) {
+                    resultInit.onFail(result.getMessage());
+                }
+            }
+        });
+    }
+
+    /**
+     * 提供给CP调用登录的接口
+     *
+     * @param activity
+     */
+    public static void login(@NonNull Activity activity, final IResult<LoginInfo> resultLoginInfo) {
+        Log.i(TAG, "login");
+        JointManager.getInstance().login(activity, new PluginResultHandler() {
+            @Override
+            public void onHandlePluginResult(PluginResult result) {
+                Status mStatus = result.getStatus();
+                Log.i(TAG, "login mStatus :" + mStatus);
+
+                if (Status.OK == mStatus) {
+                    Object res_msg = result.getRawMessage();
+                    JSONObject jo = (JSONObject) res_msg;
+                    try {
+                        resultLoginInfo.onSuccess(new LoginInfo(jo.get("uid").toString(), jo.get("token").toString()));
+                    } catch (JSONException e) {
+                        resultLoginInfo.onFail("JSONException");
+                        e.printStackTrace();
+                    }
+                } else if (Status.CANCEL == mStatus) {
+                    resultLoginInfo.onFail(result.getMessage());
+                } else if (Status.ERROR == mStatus) {
+                    resultLoginInfo.onFail(result.getMessage());
+                }
+            }
+        });
+    }
+
+    /**
+     * 提供给CP调用的支付接口
+     *
+     * @param activity
+     * @param paymentInfo CP传入的订单信息
+     * @param resultPay
+     */
+    public static void pay(@NonNull Activity activity, @NonNull final PaymentInfo paymentInfo, final IResult<String> resultPay) {
+        Log.i(TAG, "pay");
+        try {
+            Map map = Utils.getObjectToMap(paymentInfo);
+            if (map == null){
+                resultPay.onFail("params is null");
+                return;
+            }
+            JointManager.getInstance().pay(activity, map, new PluginResultHandler() {
+                @Override
+                public void onHandlePluginResult(PluginResult result) {
+                    Status mStatus = result.getStatus();
+                    Log.i(TAG, "pay mStatus :" + mStatus);
+                    if (Status.OK == mStatus) {
+                        resultPay.onSuccess(result.getMessage());
+                    } else if (Status.CANCEL == mStatus) {
+                        resultPay.onFail(result.getMessage());
+                    } else if (Status.ERROR == mStatus) {
+                        resultPay.onFail(result.getMessage());
+                    }
+                }
+            });
+        } catch (IllegalAccessException e) {
+            resultPay.onFail("params is null");
+            e.printStackTrace();
+        }
+    }
+
+
+    /**
+     * 提供给CP接收回调的接口
+     */
+
+    public interface IResult<T> {
+
+        void onSuccess(T t);
+
+        void onFail(String failMsg);
+    }
+
+}

+ 42 - 0
fq_plugin_api/src/main/java/com/fq/channel/sdk/api/bean/LoginInfo.java

@@ -0,0 +1,42 @@
+package com.fq.channel.sdk.api.bean;
+
+/**
+ * Created by Ethan on 2017/7/11.
+ * <p>
+ * 返回用户唯一标识uid和token给CP
+ */
+
+public class LoginInfo {
+
+    private String uid;
+    private String token;
+
+    public LoginInfo(String uid, String token) {
+        this.uid = uid;
+        this.token = token;
+    }
+
+    public String getUid() {
+        return uid;
+    }
+
+    public void setUid(String uid) {
+        this.uid = uid;
+    }
+
+    public String getToken() {
+        return token;
+    }
+
+    public void setToken(String token) {
+        this.token = token;
+    }
+
+    @Override
+    public String toString() {
+        return "LoginInfo{" +
+                "uid='" + uid + '\'' +
+                ", sCurrentToken='" + token + '\'' +
+                '}';
+    }
+}

+ 42 - 0
fq_plugin_api/src/main/java/com/fq/channel/sdk/api/bean/PayInfo.java

@@ -0,0 +1,42 @@
+package com.fq.channel.sdk.api.bean;
+
+/**
+ * Created by Ethan on 2017/7/11.
+ * <p>
+ * 返回用户唯一标识uid和token给CP
+ */
+
+public class PayInfo {
+
+    private String orderId;
+    private String notifyUrl;
+
+    public PayInfo(String orderId, String notifyUrl) {
+        this.orderId = orderId;
+        this.notifyUrl = notifyUrl;
+    }
+
+    public String getOrderId() {
+        return orderId;
+    }
+
+    public void setOrderId(String orderId) {
+        this.orderId = orderId;
+    }
+
+    public String getNotifyUrl() {
+        return notifyUrl;
+    }
+
+    public void setNotifyUrl(String notifyUrl) {
+        this.notifyUrl = notifyUrl;
+    }
+
+    @Override
+    public String toString() {
+        return "PayInfo{" +
+                "orderId='" + orderId + '\'' +
+                ", notifyUrl='" + notifyUrl + '\'' +
+                '}';
+    }
+}

+ 219 - 0
fq_plugin_api/src/main/java/com/fq/channel/sdk/api/bean/PaymentInfo.java

@@ -0,0 +1,219 @@
+package com.fq.channel.sdk.api.bean;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.fq.channel.sdk.base.utils.Utils;
+
+/**
+ * Created by Ethan on 2017/8/17.
+ * 提供个CP传入支付信息
+ */
+
+public class PaymentInfo implements Parcelable {
+
+    /**
+     * 必须字段
+     */
+    //订单金额
+    private String orderAmount;
+
+    //商品名称
+    private String subject;
+//    private String subject = Utils.getString(Utils.getIdentifier("default_subject","string"));
+
+    //角色名
+    private String roleName;
+
+    //cp订单号
+    private String cpBillNo;
+
+    //用户在凤起平台的唯一标识
+    private String uid;
+
+    //区服id
+    private String serverId;
+
+    //拓展信息
+    private String extraInfo;
+
+
+    /**
+     * 非必须字段
+     */
+    //订单备注
+    private String remark;
+
+    //角色等级
+    private String roleLevel;
+
+    //角色id
+    private String roleId;
+
+    //帮派、工会名
+    private String partyName;
+
+    //区服名
+    private String serverName;
+
+    //Td_AppId
+    private String tdAppId;
+
+    public String getTdAppId() {
+        return tdAppId;
+    }
+
+    public void setTdAppId(String tdAppId) {
+        this.tdAppId = tdAppId;
+    }
+
+    public String getOrderAmount() {
+        return orderAmount;
+    }
+
+    public void setOrderAmount(String orderAmount) {
+        this.orderAmount = orderAmount;
+    }
+
+    public String getSubject() {
+        return subject;
+    }
+
+    public void setSubject(String subject) {
+        this.subject = subject;
+    }
+
+    public String getRoleName() {
+        return roleName;
+    }
+
+    public void setRoleName(String roleName) {
+        this.roleName = roleName;
+    }
+
+    public String getCpBillNo() {
+        return cpBillNo;
+    }
+
+    public void setCpBillNo(String cpBillNo) {
+        this.cpBillNo = cpBillNo;
+    }
+
+    public String getUid() {
+        return uid;
+    }
+
+    public void setUid(String uid) {
+        this.uid = uid;
+    }
+
+    public String getServerId() {
+        return serverId;
+    }
+
+    public void setServerId(String serverId) {
+        this.serverId = serverId;
+    }
+
+    public String getExtraInfo() {
+        return extraInfo;
+    }
+
+    public void setExtraInfo(String extraInfo) {
+        this.extraInfo = extraInfo;
+    }
+
+    public String getRemark() {
+        return remark;
+    }
+
+    public void setRemark(String remark) {
+        this.remark = remark;
+    }
+
+    public String getRoleLevel() {
+        return roleLevel;
+    }
+
+    public void setRoleLevel(String roleLevel) {
+        this.roleLevel = roleLevel;
+    }
+
+    public String getRoleId() {
+        return roleId;
+    }
+
+    public void setRoleId(String roleId) {
+        this.roleId = roleId;
+    }
+
+    public String getPartyName() {
+        return partyName;
+    }
+
+    public void setPartyName(String partyName) {
+        this.partyName = partyName;
+    }
+
+    public String getServerName() {
+        return serverName;
+    }
+
+    public void setServerName(String serverName) {
+        this.serverName = serverName;
+    }
+
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(this.orderAmount);
+        dest.writeString(this.subject);
+        dest.writeString(this.roleName);
+        dest.writeString(this.cpBillNo);
+        dest.writeString(this.uid);
+        dest.writeString(this.serverId);
+        dest.writeString(this.extraInfo);
+        dest.writeString(this.remark);
+        dest.writeString(this.roleLevel);
+        dest.writeString(this.roleId);
+        dest.writeString(this.partyName);
+        dest.writeString(this.serverName);
+        dest.writeString(this.tdAppId);
+    }
+
+    public PaymentInfo() {
+    }
+
+    protected PaymentInfo(Parcel in) {
+        this.orderAmount = in.readString();
+        this.subject = in.readString();
+        this.roleName = in.readString();
+        this.cpBillNo = in.readString();
+        this.uid = in.readString();
+        this.serverId = in.readString();
+        this.extraInfo = in.readString();
+        this.remark = in.readString();
+        this.roleLevel = in.readString();
+        this.roleId = in.readString();
+        this.partyName = in.readString();
+        this.serverName = in.readString();
+        this.tdAppId = in.readString();
+    }
+
+    public static final Creator<PaymentInfo> CREATOR = new Creator<PaymentInfo>() {
+        @Override
+        public PaymentInfo createFromParcel(Parcel source) {
+            return new PaymentInfo(source);
+        }
+
+        @Override
+        public PaymentInfo[] newArray(int size) {
+            return new PaymentInfo[size];
+        }
+    };
+}

+ 50 - 0
fq_plugin_api/src/main/java/com/fq/channel/sdk/api/bean/RoleInfo.java

@@ -0,0 +1,50 @@
+package com.fq.channel.sdk.api.bean;
+
+/**
+ * Created by Ethan on 2017/8/19.
+ * 提供给CP给角色信息
+ */
+
+public class RoleInfo {
+
+    //游戏服务器编号
+    private String gameServerId;
+    //用户游戏角色等级
+    private String roleLev;
+    //用户角色名
+    private String roleName;
+    //用户在凤起平台的唯一标识
+    private String uid;
+
+    public String getGameServerId() {
+        return gameServerId;
+    }
+
+    public void setGameServerId(String gameServerId) {
+        this.gameServerId = gameServerId;
+    }
+
+    public String getRoleLev() {
+        return roleLev;
+    }
+
+    public void setRoleLev(String roleLev) {
+        this.roleLev = roleLev;
+    }
+
+    public String getRoleName() {
+        return roleName;
+    }
+
+    public void setRoleName(String roleName) {
+        this.roleName = roleName;
+    }
+
+    public String getUid() {
+        return uid;
+    }
+
+    public void setUid(String uid) {
+        this.uid = uid;
+    }
+}

+ 3 - 0
fq_plugin_api/src/main/res/values/strings.xml

@@ -0,0 +1,3 @@
+<resources>
+    <string name="app_name">fq_plugin_api</string>
+</resources>

+ 1 - 0
fq_plugin_base/.gitignore

@@ -0,0 +1 @@
+/build

+ 28 - 0
fq_plugin_base/build.gradle

@@ -0,0 +1,28 @@
+apply plugin: 'com.android.library'
+
+android {
+    compileSdkVersion 29
+
+
+    defaultConfig {
+        minSdkVersion 15
+        targetSdkVersion 29
+        versionCode 1
+        versionName "1.0"
+
+        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+        consumerProguardFiles 'consumer-rules.pro'
+    }
+
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+        }
+    }
+
+}
+
+dependencies {
+    api fileTree(dir: 'libs', include: ['*.jar'])
+}

+ 0 - 0
fq_plugin_base/consumer-rules.pro


BIN
fq_plugin_base/libs/android-support-v4.jar


+ 21 - 0
fq_plugin_base/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

+ 2 - 0
fq_plugin_base/src/main/AndroidManifest.xml

@@ -0,0 +1,2 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.fq.channel.sdk.base" />

+ 16 - 0
fq_plugin_base/src/main/java/com/fq/channel/sdk/base/Exception/NoSuchFunctionException.java

@@ -0,0 +1,16 @@
+package com.fq.channel.sdk.base.Exception;
+
+/**
+ * @Description:  异常类
+ * @Author: FLuty
+ * @CreateDate: 2020/3/24 15:18
+ */
+public class NoSuchFunctionException extends Exception{
+
+	private static final long serialVersionUID = 1L;
+
+		public NoSuchFunctionException(String message) {
+			super(message);
+		}
+	
+}

+ 9 - 0
fq_plugin_base/src/main/java/com/fq/channel/sdk/base/Test.java

@@ -0,0 +1,9 @@
+package com.fq.channel.sdk.base;
+
+/**
+ * @Description: 描述
+ * @Author: FLuty
+ * @CreateDate: 2020/3/24 15:18
+ */
+public class Test {
+}

+ 83 - 0
fq_plugin_base/src/main/java/com/fq/channel/sdk/base/interfaces/FQPluginApi.java

@@ -0,0 +1,83 @@
+package com.fq.channel.sdk.base.interfaces;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+
+import java.util.Map;
+
+/**
+ * @Description: 渠道封装基类
+ * @Author: FLuty
+ * @CreateDate: 2020/3/24 15:19
+ */
+public abstract class FQPluginApi {
+    /**
+     * 初始化
+     * @param activity
+     * @param handler
+     */
+    public abstract void init(Context activity, PluginResultHandler handler);
+
+    /**
+     * 登录
+     * @param activity
+     * @param handler
+     */
+    public abstract void login(final Context activity, final PluginResultHandler handler);
+    /**
+     * 支付
+     * @param activity
+     * @param map
+     * @param handler
+     */
+    public abstract void pay(Context activity, Map<String, Object> map, final PluginResultHandler handler);
+    /**
+     * 登出
+     * @param context
+     * @param prh
+     */
+    public abstract void logout(Context context, PluginResultHandler prh);
+    /**
+     * 切换用户
+     * @param activity
+     * @param prh
+     */
+    public abstract void changeAccount(final Activity activity, final PluginResultHandler prh);
+    /**
+     * 退出
+     * @param context
+     * @param cb
+     */
+    public abstract void exit(Context context, final PluginResultHandler cb);
+    /**
+     * 数据上报
+     * @param data
+     */
+    public abstract void setExtraBundle(Bundle data);
+
+    /**
+     * 获取权限结果
+     * @param requestCode
+     * @param permissions
+     * @param grantResults
+     */
+    public void onRequestPermissionsResult(int requestCode,
+                                           String[] permissions, int[] grantResults){}
+
+
+    /** 生命周期相关方法(非业务)*/
+    public abstract void onCreate(Context context, Bundle savedInstanceState);
+    public abstract void onSaveInstanceState(Context context, Bundle outState);
+    public abstract void onRestart(Context context);
+    public abstract void onStart(Context context);
+    public abstract void onResume(Context context);
+    public abstract void onPause(Context context);
+    public abstract void onStop(Context context);
+    public abstract void onNewIntent(Intent intent);
+    public abstract void attachBaseContext(Context context);
+    public abstract void onApplicationCreate(Context context);
+    public abstract void onActivityResult(int requestCode, int resultCode, Intent data);
+    public abstract void onDestroy(Context context);
+}

+ 124 - 0
fq_plugin_base/src/main/java/com/fq/channel/sdk/base/interfaces/PluginResult.java

@@ -0,0 +1,124 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+ */
+package com.fq.channel.sdk.base.interfaces;
+
+import java.util.Map;
+
+public class PluginResult {
+
+	private final Status mStatus;
+	private final int mMessageType;
+	private String mMessage;
+	private Object mRawMessage;
+
+	public PluginResult(Status status) {
+		this(status, StatusMessages[status.ordinal()]);
+	}
+
+	public PluginResult(Status status, String message) {
+		mStatus = status;
+		mMessageType = message == null ? MESSAGE_TYPE_NULL
+				: MESSAGE_TYPE_STRING;
+
+		mMessage = message;
+		mRawMessage = message;
+	}
+
+
+	public PluginResult(Status status, Object message) {
+		mStatus = status;
+		mMessageType = message == null ? MESSAGE_TYPE_NULL
+				: MESSAGE_TYPE_OBJECT;
+
+		mMessage = message != null ? message.toString() : null;
+		mRawMessage = message;
+	}
+
+	public PluginResult(Status status, Map<String, Object> message) {
+		mStatus = status;
+		mMessageType = message == null ? MESSAGE_TYPE_NULL
+				: MESSAGE_TYPE_MAP;
+
+		mMessage = message != null ? message.toString() : null;
+		mRawMessage = message;
+	}
+	
+	
+	public PluginResult(Status status, int i) {
+		mStatus = status;
+		mMessageType = MESSAGE_TYPE_NUMBER;
+
+		mMessage = String.valueOf(i);
+		mRawMessage = i;
+	}
+
+	public PluginResult(Status status, float f) {
+		mStatus = status;
+		mMessageType = MESSAGE_TYPE_NUMBER;
+
+		mMessage = String.valueOf(f);
+		mRawMessage = f;
+	}
+
+	public PluginResult(Status status, boolean b) {
+		mStatus = status;
+		mMessageType = MESSAGE_TYPE_BOOLEAN;
+
+		mMessage = String.valueOf(b);
+		mRawMessage = b;
+	}
+
+	public Status getStatus() {
+		return mStatus;
+	}
+
+	public int getMessageType() {
+		return mMessageType;
+	}
+
+	public String getMessage() {
+		return mMessage;
+	}
+
+	public Object getRawMessage() {
+		return mRawMessage;
+	}
+
+
+	public static final int MESSAGE_TYPE_STRING = 1;
+	public static final int MESSAGE_TYPE_JSON_OBJECT = 2;
+	public static final int MESSAGE_TYPE_JSON_ARRAY = 3;
+	public static final int MESSAGE_TYPE_NUMBER = 4;
+	public static final int MESSAGE_TYPE_BOOLEAN = 5;
+	public static final int MESSAGE_TYPE_NULL = 6;
+	public static final int MESSAGE_TYPE_MAP = 7;
+	public static final int MESSAGE_TYPE_OBJECT = 8;
+
+	private static String[] StatusMessages = new String[] { "OK", "Error",
+			"Cancel", "Wait", "Shift" };
+
+	public static enum Status {
+
+		OK(0), ERROR(1), CANCEL(2), WAIT(3), SHIFT(4), TOKEN_EXIPRED(5);
+
+		Status(int state) {
+		}
+
+	}
+}

+ 20 - 0
fq_plugin_base/src/main/java/com/fq/channel/sdk/base/interfaces/PluginResultHandler.java

@@ -0,0 +1,20 @@
+package com.fq.channel.sdk.base.interfaces;
+
+
+/**
+ * A callback interface to handle callbacks between plugins.
+ * 
+ * @author David
+ */
+public interface PluginResultHandler {
+
+	/**
+	 * Called when the specified plugin has finished doing something and has the
+	 * {@link PluginResult} sent to the receiver.
+	 * 
+	 * @param result
+	 *            The {@link PluginResult} object.
+	 */
+	public void onHandlePluginResult(PluginResult result);
+
+}

+ 50 - 0
fq_plugin_base/src/main/java/com/fq/channel/sdk/base/utils/ResourceCfg.java

@@ -0,0 +1,50 @@
+package com.fq.channel.sdk.base.utils;
+
+import android.content.Context;
+
+
+import org.json.JSONObject;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * @Description:  读取渠道插件配置文件
+ * @Author: FLuty
+ * @CreateDate: 2020/3/24 15:18
+ */
+public class ResourceCfg {
+
+	private String mFilePath = "fq_config/joint_cfg";
+
+	private Map<String, Object> mData;
+
+	public ResourceCfg(Context context) {
+		mData = new HashMap<String, Object>();
+		initCfg(context);
+	}
+
+	private void initCfg(Context context) {
+		try {
+			String st = Utils.readSimplelyFile(context.getAssets().open(mFilePath));
+			JSONObject json = new JSONObject(st);
+			Iterator<String> it = json.keys();
+			while (it.hasNext()) {
+				String key = it.next();
+				mData.put(key, json.get(key));
+			}
+		} catch (Exception e) {
+			e.printStackTrace();
+			throw new RuntimeException();
+		}
+	}
+
+	public Object get(String key) {
+		return mData.get(key);
+	}
+
+	public String getString(String key) {
+		return String.valueOf(mData.get(key));
+	}
+}

+ 340 - 0
fq_plugin_base/src/main/java/com/fq/channel/sdk/base/utils/Utils.java

@@ -0,0 +1,340 @@
+package com.fq.channel.sdk.base.utils;
+
+import android.annotation.SuppressLint;
+import android.app.ActivityManager;
+import android.app.Application;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.support.annotation.ColorRes;
+import android.support.annotation.DimenRes;
+import android.support.annotation.IntegerRes;
+import android.support.annotation.NonNull;
+import android.support.annotation.StringRes;
+import android.support.v4.content.ContextCompat;
+import android.text.TextUtils;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * 获取上下文的工具类
+ * Created by Ethan on 2017/6/14.
+ */
+
+public class Utils {
+    @SuppressLint("StaticFieldLeak")
+    private static Context sContext;
+
+    //SDK版本号
+    public static String FQSDK_VERSION = "1.0.8";
+
+    /**
+     * 初始化 Utils
+     *
+     * @param context 上下文
+     */
+    public static void init(@NonNull Context context) {
+        sContext = context.getApplicationContext();
+    }
+
+
+    /**
+     * 获取 ApplicationContext
+     *
+     * @return ApplicationContext
+     */
+    public static Context getContext() {
+        if (sContext != null) return sContext;
+        throw new NullPointerException("please invoke the init method first");
+    }
+
+    /**
+     * 判断传入的对象是否为空
+     *
+     * @param reference
+     * @param <T>
+     * @return 返回传入的非空对象
+     */
+    public static <T> T checkNotNull(T reference) {
+        if (reference == null) {
+            throw new NullPointerException();
+        } else {
+            return reference;
+        }
+    }
+
+    /**
+     * 获取values/strings中的string值
+     *
+     * @param resId 资源标识符
+     * @return
+     */
+    public static String getString(@StringRes int resId) {
+        return getContext().getString(resId);
+    }
+
+    /**
+     * 获取values/strings中的可格式化的string值
+     *
+     * @param resId
+     * @param formatArgs
+     * @return
+     */
+    public static String getString(@StringRes int resId, Object... formatArgs) {
+        return getContext().getString(resId, formatArgs);
+    }
+
+    /**
+     * 获取values/integers中的int值
+     *
+     * @param resId 资源标识符
+     * @return
+     */
+    public static int getInt(@IntegerRes int resId) {
+        return getContext().getResources().getInteger(resId);
+    }
+
+    /**
+     * 获取values/dimens中的dimen值
+     *
+     * @param resId 资源标识符
+     * @return
+     */
+    public static float getDimen(@DimenRes int resId) {
+        return getContext().getResources().getDimension(resId);
+    }
+
+    /**
+     * 获取values/colors中的color值
+     *
+     * @param resId 资源标识符
+     * @return
+     */
+    public static int getColor(@ColorRes int resId) {
+        return ContextCompat.getColor(getContext(), resId);
+    }
+
+
+    /**
+     * Return a resource identifier for the given resource name
+     *
+     * @param name
+     * @param defType
+     * @return
+     */
+    public static int getIdentifier(String name, String defType) {
+        return sContext.getResources().getIdentifier(name, defType, sContext.getPackageName());
+    }
+
+    /**
+     * 判断是否是手机号码
+     * <p>
+     * 1开头,总共11位数字
+     */
+    public static boolean isMobile(@NonNull String number) {
+
+        String num = "^(1)\\d{10}$";
+        if (TextUtils.isEmpty(number)) {
+            return false;
+        } else {
+            //matches():字符串是否在给定的正则表达式匹配
+            return number.matches(num);
+        }
+    }
+
+    /**
+     * 调用系统的拨号界面
+     *
+     * @param phoneNumber 拨号界面显示的号码
+     */
+    public static void callPhone(String phoneNumber) {
+        Intent intent = new Intent(Intent.ACTION_DIAL);
+        intent.setData(Uri.parse("tel:" + phoneNumber));
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        Utils.getContext().startActivity(intent);
+    }
+
+
+    /**
+     * 进行URLDecoder
+     *
+     * @param text 要Decoder的text
+     * @return
+     */
+    public static String decodeText(String text) {
+
+        try {
+            return URLDecoder.decode(text, "UTF-8");
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        }
+        return "";
+    }
+
+
+    /**
+     * 进行URLEncoder
+     *
+     * @param text 要Encode的text
+     * @return
+     */
+    private String encoderText(String text) {
+        try {
+            return URLEncoder.encode(text, "UTF-8");
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        }
+        return "";
+    }
+
+
+
+    /**
+     * 判断使用是否位于前台
+     *
+     * @return
+     */
+    public static boolean isAppForeground() {
+
+        //获取Android设备中所有正在运行的App
+        ActivityManager am = (ActivityManager) Utils.getContext()
+                .getSystemService(Application.ACTIVITY_SERVICE);
+        List<ActivityManager.RunningAppProcessInfo> appProcesses = am.getRunningAppProcesses();
+
+        //应用包名
+        String packgameName = Utils.getContext().getPackageName();
+
+        if (appProcesses == null
+                || appProcesses.isEmpty()) {
+            return false;
+        }
+
+        for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
+            if (appProcess.processName.equals(packgameName)
+                    && ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND == appProcess.importance) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 判断是否匹配对应的正则表达式
+     *
+     * @return
+     */
+    public static boolean isMatcher(String txt) {
+
+        //编译正则表达式
+        Pattern pattern = Pattern.compile(getString(getIdentifier("regex", "string")));
+        Matcher matcher = pattern.matcher(txt);
+        return matcher.matches();
+    }
+
+    /**
+     * 读简单的文件
+     *
+     * @param is
+     *            文件流
+     * @return 字符
+     */
+    public static String readSimplelyFile(InputStream is) {
+        if (is == null) {
+            return null;
+        }
+        ByteArrayOutputStream baos = null;
+        try {
+            baos = new ByteArrayOutputStream(4096);
+            byte[] b = new byte[1024];
+            int a = -1;
+            while ((a = is.read(b)) != -1) {
+                baos.write(b, 0, a);
+            }
+            return baos.toString();
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        } finally {
+            if (null != is) {
+                try {
+                    is.close();
+
+                } catch (IOException e) {
+                }
+            }
+            if (baos != null) {
+                try {
+                    baos.close();
+                } catch (IOException e) {
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * 将Object对象里面的属性和值转化成Map对象
+     *
+     * @param obj
+     * @return
+     * @throws IllegalAccessException
+     */
+
+    public static Map<String, Object> getObjectToMap(Object obj) throws IllegalAccessException {
+        Map<String, Object> map = new LinkedHashMap<String, Object>();
+        Class<?> clazz = obj.getClass();
+        System.out.println(clazz);
+        for (Field field : clazz.getDeclaredFields()) {
+            field.setAccessible(true);
+            String fieldName = field.getName();
+            Object value = field.get(obj);
+            if (value == null) {
+                value = "";
+            }
+            map.put(fieldName, value);
+        }
+        return map;
+
+    }
+
+    /**
+     * 将Map转Object对象
+     *
+     * @param map
+     * @return obj
+     * @throws IllegalAccessException
+     */
+    public static Object mapToObject(Map<Object, Object> map, Class<?> beanClass) throws Exception {
+        if (map == null)
+            return null;
+        Object obj = beanClass.newInstance();
+        Field[] fields = obj.getClass().getDeclaredFields();
+        for (Field field : fields) {
+            int mod = field.getModifiers();
+            if (Modifier.isStatic(mod) || Modifier.isFinal(mod)) {
+                continue;
+            }
+            field.setAccessible(true);
+            if (map.containsKey(field.getName())) {
+                field.set(obj, map.get(field.getName()));
+            }
+        }
+        return obj;
+    }
+
+}

+ 3 - 0
fq_plugin_base/src/main/res/values/strings.xml

@@ -0,0 +1,3 @@
+<resources>
+    <string name="app_name">fq_plugin_base</string>
+</resources>

+ 1 - 0
fq_plugin_core/.gitignore

@@ -0,0 +1 @@
+/build

+ 30 - 0
fq_plugin_core/build.gradle

@@ -0,0 +1,30 @@
+apply plugin: 'com.android.library'
+
+android {
+    compileSdkVersion 29
+
+
+    defaultConfig {
+        minSdkVersion 15
+        targetSdkVersion 29
+        versionCode 1
+        versionName "1.0"
+
+        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+        consumerProguardFiles 'consumer-rules.pro'
+    }
+
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+        }
+    }
+
+}
+
+dependencies {
+    implementation fileTree(dir: 'libs', include: ['*.jar'])
+
+    api project(':fq_plugin_base')
+}

+ 0 - 0
fq_plugin_core/consumer-rules.pro


+ 21 - 0
fq_plugin_core/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

+ 2 - 0
fq_plugin_core/src/main/AndroidManifest.xml

@@ -0,0 +1,2 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.fq.channel.sdk.core" />

+ 64 - 0
fq_plugin_core/src/main/java/com/fq/channel/sdk/core/JointManager.java

@@ -0,0 +1,64 @@
+package com.fq.channel.sdk.core;
+
+import android.content.Context;
+
+import com.fq.channel.sdk.base.interfaces.PluginResultHandler;
+import com.fq.channel.sdk.base.utils.ResourceCfg;
+import com.fq.channel.sdk.core.invoke.ApiPlugin;
+
+import java.util.Map;
+
+/**
+ * @Description: 核心层对外API
+ *
+ * @Author: FLuty
+ * @CreateDate: 2020/3/24 17:59
+ */
+public class JointManager {
+    private static final String TAG = "JointManager";
+
+    private volatile static JointManager uniqueInstance;
+
+    private ResourceCfg mCfg;
+
+    private JointManager() {}
+
+    public static JointManager getInstance() {
+        if (uniqueInstance == null) {
+            synchronized (JointManager.class) {
+                if (uniqueInstance == null) {
+                    uniqueInstance = new JointManager();
+                }
+            }
+        }
+        return uniqueInstance;
+    }
+
+    public void initCfgConfigFile(Context mContext) {
+        if (null == mCfg) {
+            mCfg = new ResourceCfg(mContext);
+        }
+    }
+
+    public void init(Context context,PluginResultHandler cb){
+        initCfgConfigFile(context);//加载assets/cfg文件
+        // 获取对应的ApiPlugin子类实例,并反射初始化SDK操作
+        ApiPlugin.getInstace().init(context, cb);
+    }
+
+    public void login(Context context,PluginResultHandler cb){
+        ApiPlugin.getInstace().login(context, cb);
+    }
+
+    public void pay(Context context, Map paymentInfo, PluginResultHandler cb){
+        ApiPlugin.getInstace().pay(context, paymentInfo, cb);
+    }
+
+    public String getPluginSdkClassName() {
+        return mCfg.getString("plugin_sdk_class_name");
+    }
+
+    public String getPluginName() {
+        return mCfg.getString("plugin_name");
+    }
+}

+ 9 - 0
fq_plugin_core/src/main/java/com/fq/channel/sdk/core/TestCore.java

@@ -0,0 +1,9 @@
+package com.fq.channel.sdk.core;
+
+/**
+ * @Description: 描述
+ * @Author: FLuty
+ * @CreateDate: 2020/3/24 16:48
+ */
+public class TestCore {
+}

+ 93 - 0
fq_plugin_core/src/main/java/com/fq/channel/sdk/core/invoke/ApiPlugin.java

@@ -0,0 +1,93 @@
+package com.fq.channel.sdk.core.invoke;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.Looper;
+import android.util.Log;
+
+import com.fq.channel.sdk.base.Exception.NoSuchFunctionException;
+import com.fq.channel.sdk.base.interfaces.PluginResult;
+import com.fq.channel.sdk.base.interfaces.PluginResultHandler;
+
+import java.util.Map;
+
+public class ApiPlugin extends ApiReflectManager {
+
+	protected String TAG = getClass().getSimpleName() ;
+
+
+	private static byte[] sync = new byte[0];
+	private static ApiPlugin instance = null;
+
+	public static ApiPlugin getInstace() {
+		if (instance == null) {
+			synchronized (sync) {
+				instance = new ApiPlugin();
+			}
+		}
+		return instance;
+	}
+
+	private ApiPlugin() {
+
+	}
+
+	Handler mainHandler = new Handler(Looper.getMainLooper());
+
+	public void post(Runnable r) {
+		mainHandler.post(r);
+	}
+
+
+	public void init(Context context, PluginResultHandler cb) {
+		if(cb == null) {
+			Log.e(TAG, "====initialize====的回调函数为null,请初始化");
+			return;
+		}
+
+		try {
+			invoke(getDeclaredMethod("init", Context.class, PluginResultHandler.class),
+					context, cb);
+		} catch (NoSuchFunctionException e) {
+			Log.e(TAG, "initialize NoSuchFunctionException");
+			e.printStackTrace();
+			cb.onHandlePluginResult(new PluginResult(PluginResult.Status.ERROR));
+		}
+	}
+
+
+	public void login(Context context, PluginResultHandler cb) {
+
+		if(cb == null) {
+			Log.e(TAG, "====login====的回调函数为null,请初始化");
+			return;
+		}
+		try {
+			invoke(getDeclaredMethod("login", Context.class, PluginResultHandler.class),
+					context, cb);
+		} catch (NoSuchFunctionException e) {
+			Log.e(TAG, "login NoSuchFunctionException");
+			e.printStackTrace();
+			cb.onHandlePluginResult(new PluginResult(PluginResult.Status.ERROR));
+		}
+
+	}
+
+	public void pay(Context context,Map map, PluginResultHandler cb) {
+
+		if(cb == null) {
+			Log.e(TAG, "====pay====的回调函数为null,请初始化");
+			return;
+		}
+		try {
+			invoke(getDeclaredMethod("pay", Context.class,Map.class, PluginResultHandler.class),
+					context,map, cb);
+		} catch (NoSuchFunctionException e) {
+			Log.e(TAG, "login NoSuchFunctionException");
+			e.printStackTrace();
+			cb.onHandlePluginResult(new PluginResult(PluginResult.Status.ERROR));
+		}
+
+	}
+
+}

+ 76 - 0
fq_plugin_core/src/main/java/com/fq/channel/sdk/core/invoke/ApiReflectManager.java

@@ -0,0 +1,76 @@
+package com.fq.channel.sdk.core.invoke;
+
+import android.content.Context;
+import android.util.Log;
+
+import com.fq.channel.sdk.base.Exception.NoSuchFunctionException;
+import com.fq.channel.sdk.core.JointManager;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.List;
+
+public class ApiReflectManager {
+	private String TAG = getClass().getSimpleName();
+	private Class<?> mClazz;
+	private Object mObject;
+	
+	public List<String> getMethodNames() {
+		List<String> list = new ArrayList<String>();
+		try {
+			Method[] methods = (ApiPlugin.getInstace().getClass()).getDeclaredMethods();
+			for (Method m : methods) {
+				if (Modifier.PUBLIC == m.getModifiers()) {
+					list.add(m.getName());
+				}
+			}
+		} catch (Exception e) {
+		}
+		return list;
+	}
+
+	public String getClassName() {
+		return JointManager.getInstance().getPluginSdkClassName();
+	}
+	
+	Object invoke(Method method, Object... args)  throws NoSuchFunctionException {
+		
+		if(null == method) {
+			throw new NoSuchFunctionException("该渠道还未实现此方法!");
+		}
+		
+		try {
+			return method.invoke(mObject, args);
+		} catch (Exception e) {
+			e.printStackTrace();
+			throw new NoSuchFunctionException("该渠道还未实现此方法!");
+		}
+	}
+
+	Method getDeclaredMethod(String name, Class<?>... parameterTypes) {
+		try {
+			
+			if(null == mClazz) {
+				init();
+			}
+			
+			return mClazz.getDeclaredMethod(name, parameterTypes);
+		} catch (Exception e) {
+			e.printStackTrace();
+			Log.d(TAG, name + " is not found.");
+		}
+		return null;
+	}
+	
+	public void init() {
+		try {
+			mClazz = Class.forName(getClassName());
+			mObject = mClazz.newInstance();
+		} catch (Exception e) {
+			e.printStackTrace();
+			throw new RuntimeException("className:" + getClassName()
+					+ " happen exception");
+		}
+	}
+}

+ 3 - 0
fq_plugin_core/src/main/res/values/strings.xml

@@ -0,0 +1,3 @@
+<resources>
+    <string name="app_name">fq_plugin_core</string>
+</resources>

+ 23 - 0
gradle.properties

@@ -0,0 +1,23 @@
+# 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
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app's APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=false
+# Automatically convert third-party libraries to use AndroidX
+android.enableJetifier=false
+# Kotlin code style for this project: "official" or "obsolete":
+kotlin.code.style=official
+
+

BIN
gradle/wrapper/gradle-wrapper.jar


+ 6 - 0
gradle/wrapper/gradle-wrapper.properties

@@ -0,0 +1,6 @@
+#Mon Mar 23 18:46:44 CST 2020
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip

+ 172 - 0
gradlew

@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# 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
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# 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
+nonstop=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+  NONSTOP* )
+    nonstop=true
+    ;;
+esac
+
+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" -a "$nonstop" = "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
+
+# Escape application args
+save () {
+    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+    echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+  cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"

+ 84 - 0
gradlew.bat

@@ -0,0 +1,84 @@
+@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
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@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=
+
+@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 Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_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=%*
+
+: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

+ 0 - 0
settings.gradle


Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä