Procházet zdrojové kódy

1.修改层次
2.增加多渠道分applicationId打包
3.根据applicationId做区分加载umeng

FailedToRead před 4 roky
rodič
revize
3e49e7b8ad
31 změnil soubory, kde provedl 1333 přidání a 238 odebrání
  1. 5 0
      .idea/jarRepositories.xml
  2. 61 6
      app/build.gradle
  3. 1 1
      app/src/androidTest/java/com/edufound/ott/zijie/yuwen/ExampleInstrumentedTest.kt
  4. 9 8
      app/src/main/AndroidManifest.xml
  5. 40 4
      app/src/main/java/com/edufound/ott/zijie/yuwen/activity/DialogNetworkActivity.java
  6. 39 24
      app/src/main/java/com/edufound/ott/zijie/yuwen/activity/MainActivity.java
  7. 206 0
      app/src/main/java/com/edufound/bytedance/application/MyApplication.java
  8. 14 7
      app/src/main/java/com/edufound/ott/zijie/yuwen/base/BaseActivity.java
  9. 3 3
      app/src/main/java/com/edufound/ott/zijie/yuwen/base/BaseMVP.java
  10. 4 4
      app/src/main/java/com/edufound/ott/zijie/yuwen/base/BasePresenter.java
  11. 4 0
      app/src/main/java/com/edufound/bytedance/mvp/IModel.java
  12. 1 3
      app/src/main/java/com/edufound/ott/zijie/yuwen/mvp/IPresenter.java
  13. 1 1
      app/src/main/java/com/edufound/ott/zijie/yuwen/mvp/IView.java
  14. 12 11
      app/src/main/java/com/edufound/ott/zijie/yuwen/mvp/model/MainModel.java
  15. 86 36
      app/src/main/java/com/edufound/ott/zijie/yuwen/mvp/presenter/MainPersenter.java
  16. 2 2
      app/src/main/java/com/edufound/ott/zijie/yuwen/mvp/view/MainView.java
  17. 49 0
      app/src/main/java/com/edufound/bytedance/receiver/HomeKeyEventReceiver.java
  18. 8 7
      app/src/main/java/com/edufound/ott/zijie/yuwen/receiver/NetworkChangeReceiver.java
  19. 7 3
      app/src/main/java/com/edufound/ott/zijie/yuwen/util/ContextUtil.java
  20. 51 5
      app/src/main/java/com/edufound/ott/zijie/yuwen/util/DeviceUtil.java
  21. 1 1
      app/src/main/java/com/edufound/ott/zijie/yuwen/util/DeviceUuidFactory.java
  22. 1 1
      app/src/main/java/com/edufound/ott/zijie/yuwen/util/Logger.java
  23. 700 0
      app/src/main/java/com/edufound/bytedance/util/OkHttpUtil.java
  24. 1 1
      app/src/main/java/com/edufound/ott/zijie/yuwen/util/SharedPerfenceUtil.java
  25. 16 0
      app/src/main/java/com/edufound/bytedance/util/ToastUtil.java
  26. 0 74
      app/src/main/java/com/edufound/ott/zijie/yuwen/application/MyApplication.java
  27. 0 4
      app/src/main/java/com/edufound/ott/zijie/yuwen/mvp/IModel.java
  28. 0 31
      app/src/main/java/com/edufound/ott/zijie/yuwen/receiver/HomeKeyEventReceiver.java
  29. 8 0
      app/src/main/res/xml/network_security_config.xml
  30. 1 1
      app/src/test/java/com/edufound/ott/zijie/yuwen/ExampleUnitTest.kt
  31. 2 0
      build.gradle

+ 5 - 0
.idea/jarRepositories.xml

@@ -21,5 +21,10 @@
       <option name="name" value="Google" />
       <option name="url" value="https://dl.google.com/dl/android/maven2/" />
     </remote-repository>
+    <remote-repository>
+      <option name="id" value="maven" />
+      <option name="name" value="maven" />
+      <option name="url" value="https://dl.bintray.com/umsdk/release" />
+    </remote-repository>
   </component>
 </project>

+ 61 - 6
app/build.gradle

@@ -1,29 +1,76 @@
 apply plugin: 'com.android.application'
-apply plugin: 'kotlin-android'
-apply plugin: 'kotlin-android-extensions'
 
 android {
     compileSdkVersion 30
     buildToolsVersion "30.0.1"
 
     defaultConfig {
-        applicationId "com.edufound.ott.zijie.yuwen"
-        minSdkVersion 23
+        applicationId "com.edufound.bytedance"
+        minSdkVersion 14
         targetSdkVersion 30
         versionCode 1
         versionName "1.0"
-
+        flavorDimensions "versionCode"
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
     }
+    signingConfigs {
+        efunbox {
+            keyAlias "edufound_key"
+            keyPassword "edufound321"
+            storeFile file("C:/Users/Candy/Desktop/edufound.keystore")
+            storePassword "edufound123"
+        }
+    }
 
     buildTypes {
         release {
             minifyEnabled false
             proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+            signingConfig signingConfigs.efunbox
+            zipAlignEnabled true
+        }
+    }
+    sourceSets {
+        main {
+            jniLibs.srcDirs = ["libs"]
         }
     }
+    productFlavors {
+        // 语文预习
+        yuwen_prepare {
+            applicationId 'com.edufound.bytedance.yuwen.prepare'
+//            manifestPlaceholders = [app_name: "app", app_icon: "@mipmap/ic_launcher"]
+        }
+
+        // 语文复习
+        yuwen_review {
+            applicationId 'com.edufound.bytedance.yuwen.review'
+//            manifestPlaceholders = [app_name: "app1", app_icon: "@mipmap/ic_launcher"]
+        }
+        // 数学预习
+        mathematics_prepare {
+            applicationId 'com.edufound.bytedance.mathematics.prepare'
+//            manifestPlaceholders = [app_name: "app", app_icon: "@mipmap/ic_launcher"]
+        }
+
+        // 数学复习
+        mathematics_review {
+            applicationId 'com.edufound.bytedance.mathematics.review'
+//            manifestPlaceholders = [app_name: "app1", app_icon: "@mipmap/ic_launcher"]
+        }
+    }
+//    productFlavors.all {
+//        flavor -> flavor.manifestPlaceholders = []
+//    }
+}
+
+repositories {
+    flatDir {
+        dirs 'libs'
+    }
 }
 
+
 dependencies {
     implementation fileTree(dir: "libs", include: ["*.jar"])
     implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
@@ -32,5 +79,13 @@ dependencies {
     testImplementation 'junit:junit:4.12'
     androidTestImplementation 'androidx.test.ext:junit:1.1.2'
     androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
-
+    //okhttp3
+    implementation 'com.squareup.okhttp3:okhttp:4.8.0'
+    implementation 'com.squareup.okio:okio:2.7.0'
+    //gson
+    implementation 'com.google.code.gson:gson:2.8.6'
+    //umeng
+    implementation 'com.umeng.umsdk:common:9.3.0' // (必选)版本号
+    implementation 'com.umeng.umsdk:asms:1.1.3' // asms包依赖(必选)
+    implementation 'com.umeng.umsdk:crash:0.0.5' // native crash包依赖(必选)
 }

+ 1 - 1
app/src/androidTest/java/com/edufound/ott/zijie/yuwen/ExampleInstrumentedTest.kt

@@ -1,4 +1,4 @@
-package com.edufound.ott.zijie.yuwen
+package com.edufound.bytedance.yuwen
 
 import androidx.test.platform.app.InstrumentationRegistry
 import androidx.test.ext.junit.runners.AndroidJUnit4

+ 9 - 8
app/src/main/AndroidManifest.xml

@@ -1,6 +1,6 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:tools="http://schemas.android.com/tools"
-    package="com.edufound.ott.zijie.yuwen">
+    package="com.edufound.bytedance">
 
     <uses-permission
         android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"
@@ -14,21 +14,22 @@
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
     <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
-    <uses-permission android:name="com.xiaomi.permission.AUTH_THIRDPAY" />
-    <uses-permission android:name="com.xiaomi.permission.CHANGE_NETWORK_STATE" />
-    <uses-permission android:name="com.xiaomi.permission.CHANGE_WIFI_STATE" />
-    <uses-permission android:name="com.xiaomi.permission.WRITE_SETTINGS" />
 
     <application
-        android:name=".application.MyApplication"
+        android:name="com.edufound.bytedance.application.MyApplication"
         android:allowBackup="true"
         android:icon="@mipmap/ic_launcher"
         android:label="@string/app_name"
+        android:networkSecurityConfig="@xml/network_security_config"
         android:roundIcon="@mipmap/ic_launcher_round"
         android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
         android:usesCleartextTraffic="true">
+        <uses-library
+            android:name="org.apache.http.legacy"
+            android:required="false" />
+
         <activity
-            android:name=".activity.MainActivity"
+            android:name="com.edufound.bytedance.activity.MainActivity"
             android:screenOrientation="landscape"
             android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
             <intent-filter>
@@ -50,7 +51,7 @@
 
         </activity>
         <activity
-            android:name=".activity.DialogNetworkActivity"
+            android:name="com.edufound.bytedance.activity.DialogNetworkActivity"
             android:screenOrientation="landscape"
             android:theme="@style/dialog"></activity>
     </application>

+ 40 - 4
app/src/main/java/com/edufound/ott/zijie/yuwen/activity/DialogNetworkActivity.java

@@ -1,4 +1,4 @@
-package com.edufound.ott.zijie.yuwen.activity;
+package com.edufound.bytedance.activity;
 
 import android.app.Activity;
 import android.content.BroadcastReceiver;
@@ -6,6 +6,7 @@ import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.graphics.Color;
+import android.os.Build;
 import android.os.Bundle;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
@@ -14,10 +15,13 @@ import android.widget.FrameLayout;
 import android.widget.TextView;
 
 import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
 
-import com.edufound.ott.zijie.yuwen.R;
-import com.edufound.ott.zijie.yuwen.application.MyApplication;
-import com.edufound.ott.zijie.yuwen.util.ContextUtil;
+import com.edufound.bytedance.R;
+import com.edufound.bytedance.application.MyApplication;
+import com.edufound.bytedance.util.ContextUtil;
+import com.edufound.bytedance.util.DeviceUtil;
+import com.edufound.bytedance.util.Logger;
 
 public class DialogNetworkActivity extends Activity {
 
@@ -28,6 +32,11 @@ public class DialogNetworkActivity extends Activity {
     protected void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         ContextUtil.setDialogNetWorkonShow(true);
+        int widht = DeviceUtil.getWidth(this);
+        int height = DeviceUtil.getHeight(this);
+        Logger.e("widht:" + widht);
+        Logger.e("height:" + height);
+        DeviceUtil.initDesignSize(this, widht, height);
         View bv = this.findViewById(android.R.id.title);
         bv.setVisibility(View.GONE);
         setFinishOnTouchOutside(false);
@@ -37,13 +46,40 @@ public class DialogNetworkActivity extends Activity {
     }
 
     void init() {
+        ContextUtil.setDialogNetWorkonShow(true);
 //        btnCancel = findViewById(R.id.dialog_cancel_button);
         btnConfirm = findViewById(R.id.dialog_confirm_button);
 //        btnCancel.setOnTouchListener(buttonTouch);
         btnConfirm.setOnTouchListener(buttonTouch);
     }
 
+
+    @Override
+    public void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        //获取屏幕宽高,以1920*1200字节音响为基准
+//        int width = mDeviceUtil.getWidth(this);
+//        int height = mDeviceUtil.getHeight(this);
+//        float width_scale = width / 1920f;
+//        float height_scale = height / 1200f;
+//        Logger.e("width_scale:" + width_scale);
+//        Logger.e("height_scale:" + height_scale);
+//        View view = getWindow().getDecorView();
+//        WindowManager.LayoutParams lp = (WindowManager.LayoutParams) view.getLayoutParams();
+//        lp.gravity = Gravity.CENTER | Gravity.LEFT;
+//        lp.x = (int) (960 * width_scale) - (mDeviceUtil.dip2px(this, 480) / 2) - 104;
+////        lp.y = 100;
+////        lp.width = 300;
+////        lp.height = 300;
+//
+//        Logger.e("lp.x=" + lp.x);
+//        Logger.e("lp.x=" + lp.y);
+//
+//        getWindowManager().updateViewLayout(view, lp);
+    }
+
     View.OnTouchListener buttonTouch = new View.OnTouchListener() {
+        @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
         @Override
         public boolean onTouch(View view, MotionEvent motionEvent) {
             switch (motionEvent.getAction()) {

+ 39 - 24
app/src/main/java/com/edufound/ott/zijie/yuwen/activity/MainActivity.java

@@ -1,28 +1,26 @@
-package com.edufound.ott.zijie.yuwen.activity;
+package com.edufound.bytedance.activity;
 
 import android.animation.ObjectAnimator;
 import android.app.Activity;
-import android.content.Context;
 import android.content.Intent;
 import android.graphics.Color;
+import android.os.Build;
 import android.os.Bundle;
+import android.view.KeyEvent;
 import android.view.View;
-import android.view.ViewGroup;
-import android.view.animation.Interpolator;
 import android.view.animation.LinearInterpolator;
 import android.webkit.WebView;
-import android.widget.Button;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
 
 import androidx.annotation.Nullable;
 
-import com.edufound.ott.zijie.yuwen.R;
-import com.edufound.ott.zijie.yuwen.base.BaseActivity;
-import com.edufound.ott.zijie.yuwen.mvp.model.MainModel;
-import com.edufound.ott.zijie.yuwen.mvp.presenter.MainPersenter;
-import com.edufound.ott.zijie.yuwen.mvp.view.MainView;
-import com.edufound.ott.zijie.yuwen.util.ContextUtil;
+import com.edufound.bytedance.R;
+import com.edufound.bytedance.base.BaseActivity;
+import com.edufound.bytedance.mvp.model.MainModel;
+import com.edufound.bytedance.mvp.presenter.MainPersenter;
+import com.edufound.bytedance.mvp.view.MainView;
+import com.edufound.bytedance.util.ContextUtil;
 
 public class MainActivity extends BaseActivity<MainModel, MainView, MainPersenter> implements MainView {
 
@@ -56,20 +54,35 @@ public class MainActivity extends BaseActivity<MainModel, MainView, MainPersente
         mPresenter.initWeb();
         mPresenter.openWeb(getIntent());
         mMainFrame.addView(getWebView());
-        ///test
-        Button ben = new Button(mActivity);
-        ben.setLayoutParams(new FrameLayout.LayoutParams(100, 100));
-        ben.setText("click show dialog error page");
-        ben.setOnClickListener(new View.OnClickListener() {
-            @Override
-            public void onClick(View view) {
-                Intent intent = new Intent(MainActivity.this, DialogNetworkActivity.class);
-                startActivity(intent);
-            }
-        });
-        mMainFrame.addView(ben);
+//        /test show network dialog
+//        Button ben = new Button(mActivity);
+//        ben.setLayoutParams(new FrameLayout.LayoutParams(100, 100));
+//        ben.setText("click show dialog error page");
+//        ben.setOnClickListener(new View.OnClickListener() {
+//            @Override
+//            public void onClick(View view) {
+//                Intent intent = new Intent(MainActivity.this, DialogNetworkActivity.class);
+//                startActivity(intent);
+//            }
+//        });
+//        mMainFrame.addView(ben);
+    }
+
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
     }
 
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        return mPresenter.onKeyDown(keyCode, event);
+    }
 
     @Override
     public MainView createView() {
@@ -102,7 +115,9 @@ public class MainActivity extends BaseActivity<MainModel, MainView, MainPersente
     @Override
     public void dismissProgressDialog() {
         mLoading.setVisibility(View.INVISIBLE);
-        mLoadingAnim.pause();
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+            mLoadingAnim.pause();
+        }
     }
 
     @Override

+ 206 - 0
app/src/main/java/com/edufound/bytedance/application/MyApplication.java

@@ -0,0 +1,206 @@
+package com.edufound.bytedance.application;
+
+import android.app.Activity;
+import android.app.Application;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
+import android.os.Process;
+
+import com.edufound.bytedance.receiver.HomeKeyEventReceiver;
+import com.edufound.bytedance.receiver.NetworkChangeReceiver;
+import com.edufound.bytedance.util.ContextUtil;
+import com.edufound.bytedance.util.Logger;
+import com.edufound.bytedance.util.OkHttpUtil;
+import com.umeng.analytics.MobclickAgent;
+import com.umeng.commonsdk.UMConfigure;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import okhttp3.Request;
+
+public class MyApplication extends Application {
+    //网络异常监听
+    NetworkChangeReceiver mNetworkReceiver;
+    //按home键的receiver
+    HomeKeyEventReceiver mHomeReceiver;
+
+    private int activityAount = 0;
+    public boolean isForeground = false;
+    //语文预习
+    private static String UMENG_KEY_YUWEN_PREVIEW = "5fbcd71b1e29ca3d7be369a9";
+    private static String APP_CODE_YUWEN_PREVIEW = "4001";
+    //语文复习
+    private static String UMENG_KEY_YUWEN_REVIEW = "5fbcd7731e29ca3d7be369be";
+    private static String APP_CODE_YUWEN_REVIEW = "4002";
+
+    //数学预习
+    private static String UMENG_KEY_MATHEMATICS_PREVIEW = "";
+    private static String APP_CODE_MATHEMATICS_PREVIEW = "4003";
+    //数学复习
+    private static String UMENG_KEY_MATHEMATICS_REVIEW = "";
+    private static String APP_CODE_MATHEMATICS_REVIEW = "4004";
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        ContextUtil.setAppStartTime(System.currentTimeMillis());
+        ContextUtil.setmApplicationContext(this);
+        initUMeng();
+        initBoardCastReceiver();
+    }
+
+
+    void initBoardCastReceiver() {
+        mHomeReceiver = new HomeKeyEventReceiver();
+        registerReceiver(mHomeReceiver, new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
+        mNetworkReceiver = new NetworkChangeReceiver();
+        IntentFilter netFilter = new IntentFilter();
+        netFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
+        registerReceiver(mNetworkReceiver, netFilter);
+        registerActivityLifecycleCallbacks(activityLifecycleCallbacks);
+    }
+
+
+    public static String getAppCode() {
+        if (ContextUtil.getmApplicationContext().getPackageName().contains("yuwen.prepare")) {
+            //语文预习
+            return APP_CODE_YUWEN_PREVIEW;
+        } else if (ContextUtil.getmApplicationContext().getPackageName().contains("yuwen.review")) {
+            //语文复习
+            return APP_CODE_YUWEN_REVIEW;
+        } else if (ContextUtil.getmApplicationContext().getPackageName().contains("mathematics.prepare")) {
+            //数学复习
+            return APP_CODE_MATHEMATICS_PREVIEW;
+        } else if (ContextUtil.getmApplicationContext().getPackageName().contains("mathematics.review")) {
+            //数学复习
+            return APP_CODE_MATHEMATICS_REVIEW;
+        }
+        return "default";
+    }
+
+    void initUMeng() {
+        try {
+            String umeng_key = "";
+            int app_code = Integer.valueOf(getAppCode());
+            switch (app_code) {
+                case 4001:
+                    umeng_key = UMENG_KEY_YUWEN_PREVIEW;
+                    break;
+                case 4002:
+                    umeng_key = UMENG_KEY_YUWEN_REVIEW;
+                    break;
+                case 4003:
+                    umeng_key = UMENG_KEY_MATHEMATICS_PREVIEW;
+                    break;
+                case 4004:
+                    umeng_key = UMENG_KEY_MATHEMATICS_REVIEW;
+                    break;
+            }
+            // 初始化SDK
+            UMConfigure.init(ContextUtil.getmApplicationContext(), umeng_key, String.valueOf(app_code), UMConfigure.DEVICE_TYPE_PHONE, null);
+            // 选用AUTO页面采集模式
+            MobclickAgent.setPageCollectionMode(MobclickAgent.PageMode.AUTO);
+        } catch (Exception e) {
+            Logger.e("友盟初始化失败:" + e.getMessage());
+            e.printStackTrace();
+        }
+    }
+
+    private static List<Activity> getAllActivitys() {
+        List<Activity> list = new ArrayList<>();
+        try {
+            Class<?> activityThread = Class.forName("android.app.ActivityThread");
+            Method currentActivityThread = activityThread.getDeclaredMethod("currentActivityThread");
+            currentActivityThread.setAccessible(true);
+            //获取主线程对象
+            Object activityThreadObject = currentActivityThread.invoke(null);
+            Field mActivitiesField = activityThread.getDeclaredField("mActivities");
+            mActivitiesField.setAccessible(true);
+            Map<Object, Object> mActivities = (Map<Object, Object>) mActivitiesField.get(activityThreadObject);
+            for (Map.Entry<Object, Object> entry : mActivities.entrySet()) {
+                Object value = entry.getValue();
+                Class<?> activityClientRecordClass = value.getClass();
+                Field activityField = activityClientRecordClass.getDeclaredField("activity");
+                activityField.setAccessible(true);
+                Object o = activityField.get(value);
+                list.add((Activity) o);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return list;
+    }
+
+    public static void exitApp() {
+        List<Activity> myAclist = getAllActivitys();
+        for (int i = 0; i < myAclist.size(); i++) {
+            myAclist.get(i).finish();
+        }
+        android.os.Process.killProcess(Process.myPid());
+    }
+
+    /**
+     * Activity 生命周期监听,用于监控app前后台状态切换
+     */
+    ActivityLifecycleCallbacks activityLifecycleCallbacks = new ActivityLifecycleCallbacks() {
+        @Override
+        public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
+        }
+
+        @Override
+        public void onActivityStarted(Activity activity) {
+            if (activityAount == 0) {
+                //app回到前台
+                isForeground = true;
+//                ToastUtil.showToast("app回到前台了");
+            }
+            activityAount++;
+        }
+
+        @Override
+        public void onActivityResumed(Activity activity) {
+        }
+
+        @Override
+        public void onActivityPaused(Activity activity) {
+        }
+
+        @Override
+        public void onActivityStopped(Activity activity) {
+            activityAount--;
+            if (activityAount == 0) {
+                isForeground = false;
+//                ToastUtil.showToast("app后台了");
+                OkHttpUtil.postUserTime(new OkHttpUtil.ResultCallback() {
+                    @Override
+                    public void onError(Request request, Exception e) {
+                        Logger.e("上传使用时间:onError:" + request.toString());
+                        exitApp();
+                        android.os.Process.killProcess(android.os.Process.myPid());
+                    }
+
+                    @Override
+                    public void onResponse(Object response) {
+                        Logger.e("上传使用时间:" + response.toString());
+                        exitApp();
+                        android.os.Process.killProcess(android.os.Process.myPid());
+                    }
+                });
+
+            }
+        }
+
+        @Override
+        public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
+        }
+
+        @Override
+        public void onActivityDestroyed(Activity activity) {
+        }
+    };
+}

+ 14 - 7
app/src/main/java/com/edufound/ott/zijie/yuwen/base/BaseActivity.java

@@ -1,14 +1,11 @@
-package com.edufound.ott.zijie.yuwen.base;
+package com.edufound.bytedance.base;
 
 import android.app.Activity;
-import android.content.IntentFilter;
 import android.os.Bundle;
 
-import androidx.annotation.Nullable;
-
-import com.edufound.ott.zijie.yuwen.mvp.IModel;
-import com.edufound.ott.zijie.yuwen.mvp.IView;
-import com.edufound.ott.zijie.yuwen.receiver.NetworkChangeReceiver;
+import com.edufound.bytedance.mvp.IModel;
+import com.edufound.bytedance.mvp.IView;
+import com.umeng.analytics.MobclickAgent;
 
 public class BaseActivity<M extends IModel, V extends IView, P extends BasePresenter> extends Activity implements BaseMVP<M, V, P> {
 
@@ -28,7 +25,17 @@ public class BaseActivity<M extends IModel, V extends IView, P extends BasePrese
         }
     }
 
+    @Override
+    protected void onResume() {
+        super.onResume();
+        MobclickAgent.onResume(this);
+    }
 
+    @Override
+    public void onPause() {
+        super.onPause();
+        MobclickAgent.onPause(this); // 不能遗漏
+    }
 
     @Override
     protected void onDestroy() {

+ 3 - 3
app/src/main/java/com/edufound/ott/zijie/yuwen/base/BaseMVP.java

@@ -1,7 +1,7 @@
-package com.edufound.ott.zijie.yuwen.base;
+package com.edufound.bytedance.base;
 
-import com.edufound.ott.zijie.yuwen.mvp.IModel;
-import com.edufound.ott.zijie.yuwen.mvp.IView;
+import com.edufound.bytedance.mvp.IModel;
+import com.edufound.bytedance.mvp.IView;
 
 public interface BaseMVP<M extends IModel, V extends IView, P extends BasePresenter> {
     M createModel();

+ 4 - 4
app/src/main/java/com/edufound/ott/zijie/yuwen/base/BasePresenter.java

@@ -1,8 +1,8 @@
-package com.edufound.ott.zijie.yuwen.base;
+package com.edufound.bytedance.base;
 
-import com.edufound.ott.zijie.yuwen.mvp.IModel;
-import com.edufound.ott.zijie.yuwen.mvp.IPresenter;
-import com.edufound.ott.zijie.yuwen.mvp.IView;
+import com.edufound.bytedance.mvp.IModel;
+import com.edufound.bytedance.mvp.IPresenter;
+import com.edufound.bytedance.mvp.IView;
 
 import java.lang.ref.WeakReference;
 

+ 4 - 0
app/src/main/java/com/edufound/bytedance/mvp/IModel.java

@@ -0,0 +1,4 @@
+package com.edufound.bytedance.mvp;
+
+public interface IModel {
+}

+ 1 - 3
app/src/main/java/com/edufound/ott/zijie/yuwen/mvp/IPresenter.java

@@ -1,6 +1,4 @@
-package com.edufound.ott.zijie.yuwen.mvp;
-
-import java.lang.ref.SoftReference;
+package com.edufound.bytedance.mvp;
 
 public interface IPresenter<M extends IModel, V extends IView> {
     void registerModel(M model);

+ 1 - 1
app/src/main/java/com/edufound/ott/zijie/yuwen/mvp/IView.java

@@ -1,4 +1,4 @@
-package com.edufound.ott.zijie.yuwen.mvp;
+package com.edufound.bytedance.mvp;
 
 import android.app.Activity;
 

+ 12 - 11
app/src/main/java/com/edufound/ott/zijie/yuwen/mvp/model/MainModel.java

@@ -1,17 +1,17 @@
-package com.edufound.ott.zijie.yuwen.mvp.model;
+package com.edufound.bytedance.mvp.model;
 
 import android.app.Activity;
-import android.os.Process;
-import android.webkit.JavascriptInterface;
 
-import com.edufound.ott.zijie.yuwen.mvp.IModel;
-import com.edufound.ott.zijie.yuwen.util.ContextUtil;
-import com.edufound.ott.zijie.yuwen.util.DeviceUtil;
-import com.edufound.ott.zijie.yuwen.util.DeviceUuidFactory;
-import com.edufound.ott.zijie.yuwen.util.SharedPerfenceUtil;
+import com.edufound.bytedance.application.MyApplication;
+import com.edufound.bytedance.mvp.IModel;
+import com.edufound.bytedance.util.ContextUtil;
+import com.edufound.bytedance.util.DeviceUtil;
+import com.edufound.bytedance.util.DeviceUuidFactory;
+import com.edufound.bytedance.util.SharedPerfenceUtil;
 
 public class MainModel implements MainModelInter {
-    private String LOAD_URL = "https://www.baidu.com/";
+    //    private String LOAD_URL = "http://reader-test.efunbox.cn/build/stage/index/index.html?wareId=1604565055981663";
+    private String LOAD_URL = "https://www.baidu.com";
     private DeviceUtil deviceUtil;
 
     public MainModel() {
@@ -20,7 +20,7 @@ public class MainModel implements MainModelInter {
 
     @Override
     public String getDefaultWebUrl() {
-        return LOAD_URL + "?";
+        return LOAD_URL;
     }
 
     @Override
@@ -31,7 +31,8 @@ public class MainModel implements MainModelInter {
         }
         ContextUtil.setUuid(preuuid);
         StringBuffer params = new StringBuffer();
-        params.append("&uuid=" + preuuid.toString());
+        params.append("uuid=" + preuuid);
+        params.append("&appCode=" + MyApplication.getAppCode());
         params.append("&width=" + deviceUtil.getWidth(activity));
         params.append("&height=" + deviceUtil.getHeight(activity));
         params.append("&model=" + deviceUtil.getSystemModel());

+ 86 - 36
app/src/main/java/com/edufound/ott/zijie/yuwen/mvp/presenter/MainPersenter.java

@@ -1,33 +1,36 @@
-package com.edufound.ott.zijie.yuwen.mvp.presenter;
+package com.edufound.bytedance.mvp.presenter;
 
-import android.annotation.SuppressLint;
 import android.content.Intent;
 import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
 import android.graphics.Color;
 import android.net.Uri;
 import android.os.Build;
-import android.os.Process;
+import android.view.KeyEvent;
 import android.view.View;
 import android.webkit.JavascriptInterface;
 import android.webkit.JsResult;
 import android.webkit.WebChromeClient;
+import android.webkit.WebResourceError;
 import android.webkit.WebResourceRequest;
-import android.webkit.WebResourceResponse;
 import android.webkit.WebSettings;
 import android.webkit.WebView;
 import android.webkit.WebViewClient;
 
-import com.edufound.ott.zijie.yuwen.base.BasePresenter;
-import com.edufound.ott.zijie.yuwen.mvp.model.MainModel;
-import com.edufound.ott.zijie.yuwen.mvp.view.MainView;
-import com.edufound.ott.zijie.yuwen.util.ContextUtil;
-import com.edufound.ott.zijie.yuwen.util.Logger;
-import com.edufound.ott.zijie.yuwen.util.SharedPerfenceUtil;
+import com.edufound.bytedance.application.MyApplication;
+import com.edufound.bytedance.base.BasePresenter;
+import com.edufound.bytedance.mvp.model.MainModel;
+import com.edufound.bytedance.mvp.view.MainView;
+import com.edufound.bytedance.util.ContextUtil;
+import com.edufound.bytedance.util.Logger;
+import com.edufound.bytedance.util.OkHttpUtil;
+import com.edufound.bytedance.util.SharedPerfenceUtil;
+
+import okhttp3.Request;
 
 public class MainPersenter extends BasePresenter<MainModel, MainView> {
 
     private String mLoadUrl;
+    private MainJsMethod mMainJsMethod;
 
     public void initWeb() {
         if (Build.VERSION.SDK_INT >= 19) {
@@ -42,11 +45,8 @@ public class MainPersenter extends BasePresenter<MainModel, MainView> {
         getView().getWebView().getSettings().setJavaScriptEnabled(true);
         getView().getWebView().getSettings().setJavaScriptCanOpenWindowsAutomatically(true);//允许js弹出窗口
         getView().getWebView().getSettings().setDomStorageEnabled(true);
-//        webview.getSettings().setMediaPlaybackRequiresUserGesture(false);
         getView().getWebView().getSettings().setBlockNetworkImage(false);
-        // webview.getSettings().set
         getView().getWebView().setBackgroundColor(Color.TRANSPARENT);
-//       webview.setBackgroundResource();
         getView().getWebView().getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
         getView().getWebView().getSettings().setUseWideViewPort(true);
         getView().getWebView().getSettings().setLoadWithOverviewMode(true);
@@ -86,7 +86,6 @@ public class MainPersenter extends BasePresenter<MainModel, MainView> {
 
             @Override
             public boolean shouldOverrideUrlLoading(WebView view, String url) {
-//                webview.removeAllViews();
                 view.loadUrl(url);
                 return true;
             }
@@ -95,22 +94,13 @@ public class MainPersenter extends BasePresenter<MainModel, MainView> {
             public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
                 super.onReceivedError(view, errorCode, description, failingUrl);
                 view.loadUrl("");// 避免出现默认的错误界面
-//                showDisConnNeWorkWindow();
                 Logger.e("onReceivedError--4参数");
                 getView().showDialogNetWork();
             }
 
             @Override
-            public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) {
-                super.onReceivedHttpError(view, request, errorResponse);
-                int statusCode = 0;
-                if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
-                    statusCode = errorResponse.getStatusCode();
-                }
-                System.out.println("onReceivedHttpError code = " + statusCode);
-                if (404 == statusCode) {
-                    view.loadUrl("");// 避免出现默认的错误界面
-                }
+            public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
+                view.loadUrl("");// 避免出现默认的错误界面
                 Logger.e("onReceivedError--3参数");
                 getView().showDialogNetWork();
             }
@@ -134,7 +124,8 @@ public class MainPersenter extends BasePresenter<MainModel, MainView> {
             }
 
         });
-        getView().getWebView().addJavascriptInterface(new MainJsMethod(), "efunboxJS");
+        mMainJsMethod = new MainJsMethod();
+        getView().getWebView().addJavascriptInterface(mMainJsMethod, "efunboxJS");
     }
 
 
@@ -152,6 +143,7 @@ public class MainPersenter extends BasePresenter<MainModel, MainView> {
             mLoadUrl = intent_url;
         }
         mLoadUrl = mLoadUrl + model.getLoadParams(getView().getActivity());
+        Logger.e("mLoadUrl:" + mLoadUrl);
         getView().getWebView().loadUrl(mLoadUrl);
     }
 
@@ -161,41 +153,99 @@ public class MainPersenter extends BasePresenter<MainModel, MainView> {
 
     }
 
+
+    public MainJsMethod getmMainJsMethod() {
+        if (mMainJsMethod == null) {
+            return null;
+        }
+        return mMainJsMethod;
+    }
+
+
+    public boolean onKeyDown(int keycode, KeyEvent event) {
+        switch (keycode) {
+            case KeyEvent.KEYCODE_BACK:
+            case KeyEvent.KEYCODE_ESCAPE:
+                getView().loadJsMehtod("boxEventHandler('key_down','KEY_BACK')");
+                return true;
+        }
+        return false;
+    }
+
+    public boolean onKeyUp(int keycode, KeyEvent event) {
+        switch (keycode) {
+            case KeyEvent.KEYCODE_BACK:
+            case KeyEvent.KEYCODE_ESCAPE:
+                // 返回键
+                getView().loadJsMehtod("boxEventHandler('key_up','KEY_BACK')");
+                return true;
+        }
+        return false;
+    }
     //--------------------------------------------------------JS方法
 
-    class MainJsMethod {
+
+    /**
+     * JS调用的Android方法类
+     */
+    public class MainJsMethod {
+
+        /**
+         * 关闭应用
+         */
         @JavascriptInterface
         public void closeApp() {
-            android.os.Process.killProcess(Process.myPid());
+            Logger.e("closeApp");
+            OkHttpUtil.postUserTime(new OkHttpUtil.ResultCallback() {
+                @Override
+                public void onError(Request request, Exception e) {
+                    Logger.e("上传使用时间:onError:" + request.toString());
+                    MyApplication.exitApp();
+                    android.os.Process.killProcess(android.os.Process.myPid());
+                }
+
+                @Override
+                public void onResponse(Object response) {
+                    Logger.e("上传使用时间:" + response.toString());
+                    MyApplication.exitApp();
+                    android.os.Process.killProcess(android.os.Process.myPid());
+                }
+            });
         }
 
 
-        /*
+        /**
          * 根据key设置SP参数方法
-         * */
+         */
         @JavascriptInterface
         public void setPreData(String key, String json) {
             SharedPerfenceUtil.setPrefString(ContextUtil.getmApplicationContext(), key, json);
         }
 
 
-        /*
+        /**
          * 根据key获取SP参数方法
-         * */
+         */
         @JavascriptInterface
         public String getPreData(String key) {
             return SharedPerfenceUtil.getPrefString(ContextUtil.getmApplicationContext(), key, "");
         }
 
-        /*
+        /**
          * 根据key删除SP参数
-         * */
+         */
         @JavascriptInterface
         public void delPreData(String key) {
             SharedPerfenceUtil.clearRecourds(ContextUtil.getmApplicationContext(), key);
         }
 
-
+        /**
+         * 設置webview背景颜色
+         */
+        @JavascriptInterface
+        public void setWebBackGroundColor(String colorString) {
+            getView().getWebView().setBackgroundColor(Color.parseColor(colorString));
+        }
     }
 
 }

+ 2 - 2
app/src/main/java/com/edufound/ott/zijie/yuwen/mvp/view/MainView.java

@@ -1,8 +1,8 @@
-package com.edufound.ott.zijie.yuwen.mvp.view;
+package com.edufound.bytedance.mvp.view;
 
 import android.webkit.WebView;
 
-import com.edufound.ott.zijie.yuwen.mvp.IView;
+import com.edufound.bytedance.mvp.IView;
 
 public interface MainView extends IView {
     void loadJsMehtod(String method);

+ 49 - 0
app/src/main/java/com/edufound/bytedance/receiver/HomeKeyEventReceiver.java

@@ -0,0 +1,49 @@
+package com.edufound.bytedance.receiver;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.text.TextUtils;
+
+import com.edufound.bytedance.application.MyApplication;
+import com.edufound.bytedance.util.Logger;
+import com.edufound.bytedance.util.OkHttpUtil;
+
+import okhttp3.Request;
+
+public class HomeKeyEventReceiver extends BroadcastReceiver {
+
+    String SYSTEM_REASON = "reason";
+    String SYSTEM_HOME_KEY = "homekey";
+    String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        // TODO Auto-generated method stub
+        String action = intent.getAction();
+        if (action.equals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) {
+            String reason = intent.getStringExtra(SYSTEM_REASON);
+            if (TextUtils.equals(reason, SYSTEM_HOME_KEY)) {
+                Logger.e("click home");
+                OkHttpUtil.postUserTime(new OkHttpUtil.ResultCallback() {
+                    @Override
+                    public void onError(Request request, Exception e) {
+                        Logger.e("上传使用时间:onError:" + request.toString());
+                        MyApplication.exitApp();
+                        android.os.Process.killProcess(android.os.Process.myPid());
+                    }
+
+                    @Override
+                    public void onResponse(Object response) {
+                        Logger.e("上传使用时间:" + response.toString());
+                        MyApplication.exitApp();
+                        android.os.Process.killProcess(android.os.Process.myPid());
+                    }
+                });
+                android.os.Process.killProcess(android.os.Process.myPid());
+            } else if (TextUtils.equals(reason, SYSTEM_DIALOG_REASON_RECENT_APPS)) {
+            }
+        }
+    }
+
+}

+ 8 - 7
app/src/main/java/com/edufound/ott/zijie/yuwen/receiver/NetworkChangeReceiver.java

@@ -1,4 +1,4 @@
-package com.edufound.ott.zijie.yuwen.receiver;
+package com.edufound.bytedance.receiver;
 
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -9,9 +9,9 @@ import android.os.Handler;
 import android.os.Message;
 import android.telephony.TelephonyManager;
 
-import com.edufound.ott.zijie.yuwen.activity.DialogNetworkActivity;
-import com.edufound.ott.zijie.yuwen.util.ContextUtil;
-import com.edufound.ott.zijie.yuwen.util.Logger;
+import com.edufound.bytedance.activity.DialogNetworkActivity;
+import com.edufound.bytedance.util.ContextUtil;
+import com.edufound.bytedance.util.Logger;
 
 
 /**
@@ -76,7 +76,7 @@ public class NetworkChangeReceiver extends BroadcastReceiver {
             }
         } else {
             strNetworkType = "-1";
-            handler.sendEmptyMessageDelayed(DISCONNECT, 2000);
+            handler.sendEmptyMessageDelayed(DISCONNECT, 500);
 
         }
         Logger.e("Network Type : " + strNetworkType);
@@ -101,8 +101,9 @@ public class NetworkChangeReceiver extends BroadcastReceiver {
                 case CONNECT:
                     //有网络连接
                     Logger.e("NetworkChangeReceiver--CONNECT");
-                    Intent intent_restart = new Intent(ContextUtil.CLOSE_DIALOG_NETWORK);
-                    mContext.sendBroadcast(intent_restart);
+                    //重新连接上之后也不给提示
+                    //Intent intent_restart = new Intent(ContextUtil.CLOSE_DIALOG_NETWORK);
+                    //mContext.sendBroadcast(intent_restart);
                     break;
             }
             return false;

+ 7 - 3
app/src/main/java/com/edufound/ott/zijie/yuwen/util/ContextUtil.java

@@ -1,4 +1,4 @@
-package com.edufound.ott.zijie.yuwen.util;
+package com.edufound.bytedance.util;
 
 import android.content.Context;
 
@@ -7,8 +7,8 @@ public class ContextUtil {
     private static Context mApplicationContext;
     private static String Uuid;
     public static String CLOSE_DIALOG_NETWORK = "com.edufound.ott.zijie.close.network";
-
-    public static boolean DialogNetWorkonShow = true;
+    private static String URL_POST_USER_TIME = "http://zijie-test.efunbox.cn/onlineTime";
+    public static boolean DialogNetWorkonShow = false;
 
     public static Long getAppStartTime() {
         return APP_START_TIME;
@@ -42,5 +42,9 @@ public class ContextUtil {
         DialogNetWorkonShow = dialogNetWorkonShow;
     }
 
+    public static String getUrlPostUserTime() {
+        return URL_POST_USER_TIME;
+    }
+
 
 }

+ 51 - 5
app/src/main/java/com/edufound/ott/zijie/yuwen/util/DeviceUtil.java

@@ -1,12 +1,12 @@
-package com.edufound.ott.zijie.yuwen.util;
+package com.edufound.bytedance.util;
 
 import android.app.Activity;
 import android.content.Context;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
-import android.os.Build;
 import android.telephony.TelephonyManager;
 import android.util.DisplayMetrics;
+import android.util.TypedValue;
 
 import java.io.UnsupportedEncodingException;
 import java.security.MessageDigest;
@@ -14,7 +14,7 @@ import java.util.Locale;
 
 public class DeviceUtil {
 
-    DisplayMetrics metric = new DisplayMetrics();
+    private static DisplayMetrics metric = new DisplayMetrics();
 
     /**
      * @return 序列号 SerialNumber
@@ -26,12 +26,18 @@ public class DeviceUtil {
     }
 
 
-    public int getWidth(Activity context) {
+    /**
+     * 获取宽度
+     */
+    public static int getWidth(Activity context) {
         context.getWindowManager().getDefaultDisplay().getMetrics(metric);
         return metric.widthPixels; // 屏幕宽度(像素)
     }
 
-    public int getHeight(Activity context) {
+    /**
+     * 获取宽度
+     */
+    public static int getHeight(Activity context) {
         context.getWindowManager().getDefaultDisplay().getMetrics(metric);
         return metric.heightPixels; // 屏幕高度(像素)
     }
@@ -168,4 +174,44 @@ public class DeviceUtil {
         return null;
     }
 
+    //dp转px
+    public static int dip2px(Context context, float dpValue) {
+        final float scale = context.getResources().getDisplayMetrics().density;
+        return (int) (dpValue * scale + 0.5f);
+    }
+
+    //px转dp
+    public static int px2dip(Context context, int pxValue) {
+        return ((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, pxValue, context.getResources().getDisplayMetrics()));
+    }
+
+    public static void initDesignSize(Context context, int screenWidth, int screenHeight) {
+        int designWidth = 960;
+        int designHeight = 600;
+        float ds = 1.0f * designWidth / designHeight;
+        float ts = 1.0f * screenWidth / screenHeight;
+        float designScale = 0.0f;
+        if (ds >= ts) {
+            int targetWidth = screenWidth;
+            designScale = 1.0f * targetWidth / designWidth;
+
+        } else {
+            int targetHeight = screenHeight;
+            designScale = 1.0f * targetHeight / designHeight;
+
+        }
+        setDisplay(context, designScale);
+    }
+
+    /**
+     * 设置dpi缩放比
+     */
+    private static void setDisplay(Context context, float designScale) {
+        DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
+        displayMetrics.density = designScale;
+        displayMetrics.scaledDensity = displayMetrics.density;
+        displayMetrics.xdpi = displayMetrics.density * 160;
+        displayMetrics.ydpi = displayMetrics.xdpi;
+        displayMetrics.densityDpi = Float.valueOf(displayMetrics.xdpi).intValue();
+    }
 }

+ 1 - 1
app/src/main/java/com/edufound/ott/zijie/yuwen/util/DeviceUuidFactory.java

@@ -1,4 +1,4 @@
-package com.edufound.ott.zijie.yuwen.util;
+package com.edufound.bytedance.util;
 
 import android.annotation.SuppressLint;
 import android.content.Context;

+ 1 - 1
app/src/main/java/com/edufound/ott/zijie/yuwen/util/Logger.java

@@ -1,4 +1,4 @@
-package com.edufound.ott.zijie.yuwen.util;
+package com.edufound.bytedance.util;
 
 import android.util.Log;
 

+ 700 - 0
app/src/main/java/com/edufound/bytedance/util/OkHttpUtil.java

@@ -0,0 +1,700 @@
+package com.edufound.bytedance.util;
+
+
+import android.os.Handler;
+import android.os.Looper;
+
+
+import com.edufound.bytedance.application.MyApplication;
+import com.google.gson.Gson;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.FileNameMap;
+import java.net.URLConnection;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import okhttp3.Call;
+import okhttp3.Callback;
+import okhttp3.Cookie;
+import okhttp3.CookieJar;
+import okhttp3.FormBody;
+import okhttp3.Headers;
+import okhttp3.HttpUrl;
+import okhttp3.Interceptor;
+import okhttp3.MediaType;
+import okhttp3.MultipartBody;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.RequestBody;
+import okhttp3.Response;
+import okhttp3.ResponseBody;
+import okio.Buffer;
+import okio.BufferedSource;
+import okio.ForwardingSource;
+import okio.Okio;
+
+
+public class OkHttpUtil {
+    private OkHttpClient okHttpClient;
+    private Handler handler;
+    private static OkHttpUtil mInstance;
+    private final HashMap<String, List<Cookie>> cookieStore = new HashMap<>();
+
+    private OkHttpUtil() {
+        //添加cookie
+        okHttpClient = new OkHttpClient.Builder().cookieJar(new CookieJar() {
+            @Override
+            public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
+                cookieStore.put(url.host(), cookies);
+
+            }
+
+            @Override
+            public List<Cookie> loadForRequest(HttpUrl url) {
+                List<Cookie> cookies = cookieStore.get(url.host());
+                return cookies != null ? cookies : new ArrayList<Cookie>();
+            }
+        }).build();
+        handler = new Handler(Looper.getMainLooper());
+    }
+
+    /**
+     * 单例模式创建OkHttpUtil
+     *
+     * @return mInstance
+     */
+    public static OkHttpUtil getInstance() {
+        if (mInstance == null) {
+            synchronized (OkHttpUtil.class) {
+                mInstance = new OkHttpUtil();
+            }
+        }
+        return mInstance;
+    }
+
+    /**
+     * get 同步请求
+     *
+     * @return response
+     */
+    private Response _getDataSync(String url) {
+        Request request = new Request.Builder()
+                .get()//默认get,可省略
+                .url(url)
+                .build();
+        Response response = null;
+        try {
+            response = okHttpClient.newCall(request).execute();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return response;
+    }
+
+    /**
+     * get 同步请求
+     *
+     * @return 字符串
+     */
+    private String _getDataString(String url) throws IOException {
+        Response response = _getDataSync(url);
+        if (response.body() != null) {
+            return response.body().string();
+        }
+        return null;
+    }
+
+    /**
+     * get 异步请求
+     */
+    private void _getDataAsync(String url, final ResultCallback callback) {
+        final Request request = new Request.Builder()
+                .url(url)
+                .build();
+        deliveryResult(callback, request);
+    }
+
+    /**
+     * post 同步请求
+     *
+     * @return response
+     */
+    private Response _postDataSync(String url, Param... params) throws IOException {
+        Request request = buildPostRequest(url, params);
+        return okHttpClient.newCall(request).execute();
+
+    }
+
+    /**
+     * post 同步请求
+     *
+     * @return 字符串
+     */
+    private String _postDataString(String url, Param... params) throws IOException {
+        Response response = _postDataSync(url, params);
+        return response.body().string();
+    }
+
+    /**
+     * post 异步请求
+     */
+    private void _postDataAsync(String url, final ResultCallback callback, Param... params) {
+        Request request = buildPostRequest(url, params);
+        deliveryResult(callback, request);
+
+    }
+
+    /**
+     * post 异步请求
+     */
+
+    private void _postDataAsync(String url, final ResultCallback callback, Map<String, String> params) {
+        Param[] paramsArr = map2Params(params);
+        Request request = buildPostRequest(url, paramsArr);
+        deliveryResult(callback, request);
+    }
+
+    /**
+     * post 同步文件上传
+     */
+    private Response _postDataFileSync(String url, File[] files, String[] fileKeys, Param... params) throws IOException {
+        Request request = buildMultipartFormRequest(url, files, fileKeys, params);
+        return okHttpClient.newCall(request).execute();
+    }
+
+    private Response _postDataFileSync(String url, File file, String fileKey) throws IOException {
+        Request request = buildMultipartFormRequest(url, new File[]{file}, new String[]{fileKey}, null);
+        return okHttpClient.newCall(request).execute();
+    }
+
+    private Response _postDataFileSync(String url, File file, String fileKey, Param... params) throws IOException {
+        Request request = buildMultipartFormRequest(url, new File[]{file}, new String[]{fileKey}, params);
+        return okHttpClient.newCall(request).execute();
+    }
+
+    /**
+     * 异步基于post的多文件上传
+     */
+    private void _postDataFileAsync(String url, final ResultCallback callback, File[] files, String[] fileKeys, Param... params) {
+        Request request = buildMultipartFormRequest(url, files, fileKeys, params);
+        deliveryResult(callback, request);
+    }
+
+    /**
+     * 异步基于post的文件上传,单文件不带参数上传
+     *
+     * @param url
+     * @param callback
+     * @param file
+     * @param fileKey
+     */
+    private void _postDataFileAsync(String url, ResultCallback callback, File file, String fileKey) {
+        Request request = buildMultipartFormRequest(url, new File[]{file}, new String[]{fileKey}, null);
+        deliveryResult(callback, request);
+    }
+
+    /**
+     * 异步基于post的文件上传,单文件且携带其他form参数上传
+     *
+     * @param url      接口地址
+     * @param callback callback
+     * @param file     file
+     * @param fileKey  fileKey
+     * @param params   params
+     */
+    private void _postDataFileAsync(String url, ResultCallback callback, File file, String fileKey, Param... params) {
+        Request request = buildMultipartFormRequest(url, new File[]{file}, new String[]{fileKey}, params);
+        deliveryResult(callback, request);
+    }
+
+    /**
+     * 同步 post上传json对象
+     *
+     * @param url     url;
+     * @param jsonStr json 字符串
+     * @return 字符串
+     * @throws IOException
+     */
+    private String _postJsonDataSync(String url, String jsonStr) throws IOException {
+        String result = null;
+        MediaType JSON = MediaType.parse("text/html;charset=utf-8");
+        RequestBody requestBody = RequestBody.create(JSON, jsonStr);
+        Request request = new Request.Builder().url(url).post(requestBody).build();
+        Response response = okHttpClient.newCall(request).execute();
+        result = response.body().string();
+        return result;
+    }
+
+    /**
+     * 异步 post上传json对象
+     *
+     * @param url      url
+     * @param jsonStr  json数据字符串
+     * @param callback callback
+     */
+    private void _postJsonDataAsync(String url, String jsonStr, final ResultCallback callback) {
+        MediaType JSON = MediaType.parse("text/html;charset=utf-8");
+        RequestBody requestBody = RequestBody.create(JSON, jsonStr);
+        Request request = new Request.Builder().url(url).post(requestBody).build();
+        deliveryResult(callback, request);
+    }
+
+    /**
+     * post 异步上传图片
+     *
+     * @param url      url
+     * @param callback callback
+     * @param file     file
+     * @param fileKey  fileKey
+     * @param map      map
+     */
+    private void _upLoadImg(String url, final ResultCallback callback, File file, String fileKey, Map<String, String> map) {
+        Param[] params = map2Params(map);
+        getInstance()._postDataFileAsync(url, callback, file, fileKey, params);
+    }
+
+    /**
+     * 创建 MultipartFormRequest
+     *
+     * @param url      接口地址
+     * @param files    files
+     * @param fileKeys file keys
+     * @param params   params
+     * @return MultipartFormRequest
+     */
+
+    private Request buildMultipartFormRequest(String url, File[] files,
+                                              String[] fileKeys, Param[] params) {
+        params = validateParam(params);
+
+        MultipartBody.Builder builder = new MultipartBody.Builder();
+        for (Param param : params) {
+            builder.addPart(Headers.of("Content-Disposition", "form-data; name=\"" + param.key + "\""),
+                    RequestBody.create(null, param.value));
+        }
+        if (files != null) {
+            RequestBody fileBody;
+            for (int i = 0; i < files.length; i++) {
+                File file = files[i];
+                String fileName = file.getName();
+                fileBody = RequestBody.create(MediaType.parse(guessMimeType(fileName)), file);
+                //TODO 根据文件名设置contentType
+                builder.addPart(Headers.of("Content-Disposition",
+                        "form-data; name=\"" + fileKeys[i] + "\"; filename=\"" + fileName + "\""),
+                        fileBody);
+            }
+        }
+
+        RequestBody requestBody = builder.build();
+        return new Request.Builder()
+                .url(url)
+                .post(requestBody)
+                .build();
+    }
+
+    private Param[] validateParam(Param[] params) {
+        if (params == null)
+            return new Param[0];
+        else
+            return params;
+    }
+
+    private String guessMimeType(String path) {
+        FileNameMap fileNameMap = URLConnection.getFileNameMap();
+        String contentTypeFor = fileNameMap.getContentTypeFor(path);
+        if (contentTypeFor == null) {
+            contentTypeFor = "application/octet-stream";
+        }
+        return contentTypeFor;
+    }
+
+    /**
+     * 异步下载文件
+     */
+    private void _downloadFileAsync(final String url, final String destFileDir,
+                                    final DownloadListener downloadListener) {
+        final Request request = new Request.Builder().url(url).build();
+        // 重写ResponseBody监听请求
+        Interceptor interceptor = new Interceptor() {
+            @Override
+            public Response intercept(Chain chain) throws IOException {
+                Response originalResponse = chain.proceed(chain.request());
+                return originalResponse.newBuilder()
+                        .body(new DownloadResponseBody(originalResponse, 0, downloadListener))
+                        .build();
+            }
+        };
+        OkHttpClient.Builder dlOkhttp = new OkHttpClient.Builder()
+                .addNetworkInterceptor(interceptor);
+        final Call call = dlOkhttp.build().newCall(request);
+        call.enqueue(new Callback() {
+
+            @Override
+            public void onFailure(Call call, IOException e) {
+                downloadListener.fail(e.getMessage());
+            }
+
+            @Override
+            public void onResponse(Call call, Response response) throws IOException {
+                long length = response.body().contentLength();
+                downloadListener.start(length);
+                InputStream is = null;
+                byte[] b = new byte[2048];
+                int len;
+                FileOutputStream fos = null;
+                try {
+                    is = response.body().byteStream();
+                    File file = new File(destFileDir, getFileName(url));
+                    fos = new FileOutputStream(file);
+                    while ((len = is.read(b)) != -1) {
+                        fos.write(b, 0, len);
+                    }
+                    fos.flush();
+                    // 如果下载文件成功,第一个参数为文件的绝对路径
+                    downloadListener.complete(file.getAbsolutePath());
+                } catch (Exception e) {
+                    downloadListener.loadfail(e.getMessage());
+                } finally {
+                    if (is != null) {
+                        is.close();
+                    }
+                    if (fos != null) {
+                        fos.close();
+                    }
+                }
+
+            }
+
+        });
+    }
+
+    private String getFileName(String path) {
+        int separatorIndex = path.lastIndexOf("/");
+        return (separatorIndex < 0) ? path : path.substring(separatorIndex + 1,
+                path.length());
+    }
+
+    /***************************************************************** 公共方法***************************************************/
+    /**
+     * get 同步请求
+     *
+     * @param url 接口地址
+     * @return response
+     */
+    public static Response getDataSync(String url) {
+        return getInstance()._getDataSync(url);
+    }
+
+    /**
+     * get 同步请求
+     *
+     * @param url 接口地址
+     * @return 字符串
+     * @throws IOException
+     */
+    public static String getDataString(String url) throws IOException {
+        return getInstance()._getDataString(url);
+    }
+
+    /**
+     * get 异步请求
+     *
+     * @param url 接口地址
+     */
+    public static void getDataAsync(String url, final ResultCallback callback) {
+        getInstance()._getDataAsync(url, callback);
+    }
+
+    /**
+     * post 同步请求
+     *
+     * @param url   url
+     * @param param param
+     * @return response
+     * @throws IOException
+     */
+    public static Response postDataSync(String url, Param... param) throws IOException {
+        return getInstance()._postDataSync(url, param);
+    }
+
+    /**
+     * post 同步请求
+     *
+     * @param url    url
+     * @param params param
+     * @return 字符串
+     * @throws IOException
+     */
+    public static String postDataString(String url, Param... params) throws IOException {
+        return getInstance()._postDataString(url, params);
+    }
+
+    /**
+     * post 异步请求
+     *
+     * @param url      url
+     * @param callback 异步回调
+     * @param params   params
+     */
+    public static void postDataAsync(String url, final ResultCallback callback, Param... params) {
+        getInstance()._postDataAsync(url, callback, params);
+    }
+
+    /**
+     * post map集合 异步请求
+     *
+     * @param url      url
+     * @param callback callback
+     * @param params   params
+     */
+    public static void postDataAsync(String url, final ResultCallback callback, Map<String, String> params) {
+        getInstance()._postDataAsync(url, callback, params);
+    }
+
+    /**
+     * post 异步上传图片
+     *
+     * @param url      url
+     * @param callback callback
+     * @param file     file
+     * @param fileKey  fileKey
+     * @param map      map
+     */
+    public static void upLoadImg(String url, final ResultCallback callback, File file, String fileKey, Map<String, String> map) {
+        getInstance()._upLoadImg(url, callback, file, fileKey, map);
+    }
+
+    /**
+     * @param url              下载地址
+     * @param destFileDir      保存地址
+     * @param downloadListener downloadListener
+     */
+    public static void downloadFileAsync(String url, String destFileDir, DownloadListener downloadListener) {
+        getInstance()._downloadFileAsync(url, destFileDir, downloadListener);
+    }
+
+
+    public static void postUserTime(ResultCallback resultCallback) {
+        Gson gson = new Gson();
+        Map<String, String> obj = new HashMap<>();
+        obj.put("channel", MyApplication.getAppCode());
+        long runtime = System.currentTimeMillis() - ContextUtil.getAppStartTime();
+        obj.put("timeAcc", String.valueOf(runtime));
+        obj.put("deviceCode", ContextUtil.getUuid());
+        String json = gson.toJson(obj);
+        Logger.e("post user time json:" + json);
+        getInstance()._postJsonDataAsync(ContextUtil.getUrlPostUserTime(), json, resultCallback);
+    }
+
+
+    /**
+     * map 转换为 Param
+     *
+     * @param params map
+     * @return params
+     */
+    private Param[] map2Params(Map<String, String> params) {
+        if (params == null) {
+            return new Param[0];
+        }
+        int size = params.size();
+        Param[] res = new Param[size];
+        Set<Map.Entry<String, String>> entries = params.entrySet();
+        int i = 0;
+        for (Map.Entry<String, String> entry : entries) {
+            res[i++] = new Param(entry.getKey(), entry.getValue());
+        }
+        return res;
+    }
+
+    /**
+     * 创建 PostRequest
+     *
+     * @param url    url
+     * @param params params
+     * @return request
+     */
+    private Request buildPostRequest(String url, Param[] params) {
+        if (params == null) {
+            params = new Param[0];
+        }
+        FormBody.Builder builder = new FormBody.Builder();
+        for (Param param : params) {
+            builder.add(param.key, param.value);
+        }
+        RequestBody requestBody = builder.build();
+        return new Request.Builder()
+                .url(url)
+                .post(requestBody)
+                .build();
+    }
+
+
+    /**
+     * 抽象类,用于请求成功后的回调
+     *
+     * @param <T>
+     */
+    public static abstract class ResultCallback<T> {
+        //这是请求数据的返回类型,包含常见的(Bean,List等)
+
+        //失败回调
+        public abstract void onError(Request request, Exception e);
+
+        //成功的回调
+        public abstract void onResponse(T response);
+    }
+
+    private Map<String, String> mSessions = new HashMap<>();
+
+    /**
+     * 请求回调处理方法并传递返回值
+     *
+     * @param callback Map类型请求参数
+     * @param request  Request请求
+     */
+    private void deliveryResult(final ResultCallback callback, final Request request) {
+        okHttpClient.newCall(request).enqueue(new Callback() {
+            @Override
+            public void onFailure(Call call, IOException e) {
+                sendFailedStringCallback(request, e, callback);
+            }
+
+            @Override
+            public void onResponse(Call call, Response response) throws IOException {
+                try {
+                    final String string = response.body().string();
+                    sendSuccessResultCallback(string, callback);
+                } catch (IOException e) {
+                    sendFailedStringCallback(response.request(), e, callback);
+                }
+            }
+
+        });
+    }
+
+    /**
+     * 处理请求失败的回调信息方法
+     *
+     * @param e        错误信息
+     * @param callback 回调类
+     */
+    private void sendFailedStringCallback(final Request request, final Exception e, final ResultCallback callback) {
+        handler.post(new Runnable() {
+            @Override
+            public void run() {
+                if (callback != null)
+                    callback.onError(request, e);
+            }
+        });
+    }
+
+    /**
+     * 处理请求成功的回调信息方法
+     *
+     * @param object   服务器响应信息
+     * @param callback 回调类
+     */
+    private void sendSuccessResultCallback(final Object object, final ResultCallback callback) {
+        handler.post(new Runnable() {
+            @Override
+            public void run() {
+                if (callback != null) {
+                    callback.onResponse(object);
+                }
+            }
+        });
+    }
+
+    public static class Param {
+        public Param() {
+        }
+
+        public Param(String key, String value) {
+            this.key = key;
+            this.value = value;
+        }
+
+        String key;
+        String value;
+    }
+
+
+    public class DownloadResponseBody extends ResponseBody {
+
+        private Response originalResponse;
+        private DownloadListener downloadListener;
+        private long oldPoint = 0;
+
+        public DownloadResponseBody(Response originalResponse, long startsPoint, DownloadListener downloadListener) {
+            this.originalResponse = originalResponse;
+            this.downloadListener = downloadListener;
+            this.oldPoint = startsPoint;
+            Logger.e("DownloadResponseBody");
+        }
+
+        @Override
+        public MediaType contentType() {
+            return originalResponse.body().contentType();
+        }
+
+        @Override
+        public long contentLength() {
+            return originalResponse.body().contentLength();
+        }
+
+        @Override
+        public BufferedSource source() {
+            return Okio.buffer(new ForwardingSource(originalResponse.body().source()) {
+                private long bytesReaded = 0;
+
+                @Override
+                public long read(Buffer sink, long byteCount) throws IOException {
+                    long bytesRead = super.read(sink, byteCount);
+                    bytesReaded += bytesRead == -1 ? 0 : bytesRead;
+                    if (downloadListener != null) {
+                        downloadListener.loading((int) ((bytesReaded + oldPoint)));
+                    }
+                    return bytesRead;
+                }
+            });
+        }
+    }
+
+    public interface DownloadListener {
+
+        /**
+         * 开始下载
+         */
+        void start(long max);
+
+        /**
+         * 正在下载
+         */
+        void loading(int progress);
+
+        /**
+         * 下载完成
+         */
+        void complete(String path);
+
+        /**
+         * 请求失败
+         */
+        void fail(String message);
+
+        /**
+         * 下载过程中失败
+         */
+        void loadfail(String message);
+    }
+}
+
+

+ 1 - 1
app/src/main/java/com/edufound/ott/zijie/yuwen/util/SharedPerfenceUtil.java

@@ -1,4 +1,4 @@
-package com.edufound.ott.zijie.yuwen.util;
+package com.edufound.bytedance.util;
 
 import android.content.Context;
 import android.content.SharedPreferences;

+ 16 - 0
app/src/main/java/com/edufound/bytedance/util/ToastUtil.java

@@ -0,0 +1,16 @@
+package com.edufound.bytedance.util;
+
+import android.widget.Toast;
+
+public class ToastUtil {
+    private static Toast toast;
+
+    public static void showToast(String message) {
+        if (toast == null) {
+            toast = Toast.makeText(ContextUtil.getmApplicationContext(), message, Toast.LENGTH_LONG);
+        } else {
+            toast.setText(message);
+        }
+        toast.show();
+    }
+}

+ 0 - 74
app/src/main/java/com/edufound/ott/zijie/yuwen/application/MyApplication.java

@@ -1,74 +0,0 @@
-package com.edufound.ott.zijie.yuwen.application;
-
-import android.app.Activity;
-import android.app.Application;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Process;
-
-import com.edufound.ott.zijie.yuwen.receiver.HomeKeyEventReceiver;
-import com.edufound.ott.zijie.yuwen.receiver.NetworkChangeReceiver;
-import com.edufound.ott.zijie.yuwen.util.ContextUtil;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-public class MyApplication extends Application {
-    //网络异常监听
-    NetworkChangeReceiver mNetworkReceiver;
-    //按home键的receiver
-    HomeKeyEventReceiver mHomeReceiver;
-
-    @Override
-    public void onCreate() {
-        super.onCreate();
-        ContextUtil.setAppStartTime(System.currentTimeMillis());
-        ContextUtil.setmApplicationContext(this);
-        initBoardCastReceiver();
-    }
-
-    void initBoardCastReceiver() {
-        mHomeReceiver = new HomeKeyEventReceiver();
-        registerReceiver(mHomeReceiver, new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
-        mNetworkReceiver = new NetworkChangeReceiver();
-        IntentFilter netFilter = new IntentFilter();
-        netFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
-        registerReceiver(mNetworkReceiver, netFilter);
-    }
-
-    private static List<Activity> getAllActivitys() {
-        List<Activity> list = new ArrayList<>();
-        try {
-            Class<?> activityThread = Class.forName("android.app.ActivityThread");
-            Method currentActivityThread = activityThread.getDeclaredMethod("currentActivityThread");
-            currentActivityThread.setAccessible(true);
-            //获取主线程对象
-            Object activityThreadObject = currentActivityThread.invoke(null);
-            Field mActivitiesField = activityThread.getDeclaredField("mActivities");
-            mActivitiesField.setAccessible(true);
-            Map<Object, Object> mActivities = (Map<Object, Object>) mActivitiesField.get(activityThreadObject);
-            for (Map.Entry<Object, Object> entry : mActivities.entrySet()) {
-                Object value = entry.getValue();
-                Class<?> activityClientRecordClass = value.getClass();
-                Field activityField = activityClientRecordClass.getDeclaredField("activity");
-                activityField.setAccessible(true);
-                Object o = activityField.get(value);
-                list.add((Activity) o);
-            }
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-        return list;
-    }
-
-    public static void exitApp() {
-        List<Activity> myAclist = getAllActivitys();
-        for (int i = 0; i < myAclist.size(); i++) {
-            myAclist.get(i).finish();
-        }
-        android.os.Process.killProcess(Process.myPid());
-    }
-}

+ 0 - 4
app/src/main/java/com/edufound/ott/zijie/yuwen/mvp/IModel.java

@@ -1,4 +0,0 @@
-package com.edufound.ott.zijie.yuwen.mvp;
-
-public interface IModel {
-}

+ 0 - 31
app/src/main/java/com/edufound/ott/zijie/yuwen/receiver/HomeKeyEventReceiver.java

@@ -1,31 +0,0 @@
-package com.edufound.ott.zijie.yuwen.receiver;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.text.TextUtils;
-
-import com.edufound.ott.zijie.yuwen.util.Logger;
-
-public class HomeKeyEventReceiver extends BroadcastReceiver {
-
-    String SYSTEM_REASON = "reason";
-    String SYSTEM_HOME_KEY = "homekey";
-    String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
-    public static boolean isClickHome = false;
-
-    @Override
-    public void onReceive(Context context, Intent intent) {
-        // TODO Auto-generated method stub
-        String action = intent.getAction();
-        if (action.equals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) {
-            String reason = intent.getStringExtra(SYSTEM_REASON);
-            if (TextUtils.equals(reason, SYSTEM_HOME_KEY)) {
-                Logger.e("click home");
-                android.os.Process.killProcess(android.os.Process.myPid());
-            } else if (TextUtils.equals(reason, SYSTEM_DIALOG_REASON_RECENT_APPS)) {
-            }
-        }
-    }
-
-}

+ 8 - 0
app/src/main/res/xml/network_security_config.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<network-security-config>
+    <base-config cleartextTrafficPermitted="true">
+        <trust-anchors>
+            <certificates src="system" />
+        </trust-anchors>
+    </base-config>
+</network-security-config>

+ 1 - 1
app/src/test/java/com/edufound/ott/zijie/yuwen/ExampleUnitTest.kt

@@ -1,4 +1,4 @@
-package com.edufound.ott.zijie.yuwen
+package com.edufound.bytedance.yuwen
 
 import org.junit.Test
 

+ 2 - 0
build.gradle

@@ -4,6 +4,7 @@ buildscript {
     repositories {
         google()
         jcenter()
+        maven { url 'https://dl.bintray.com/umsdk/release' }
     }
     dependencies {
         classpath "com.android.tools.build:gradle:4.0.1"
@@ -18,6 +19,7 @@ allprojects {
     repositories {
         google()
         jcenter()
+        maven { url 'https://dl.bintray.com/umsdk/release' }
     }
 }