Browse Source

1.提交移动端8.0android框架到学有义方

zhangmengjie 4 years ago
commit
21f692bf53
100 changed files with 9228 additions and 0 deletions
  1. 13 0
      .gitignore
  2. 29 0
      .idea/codeStyles/Project.xml
  3. 15 0
      .idea/gradle.xml
  4. 9 0
      .idea/misc.xml
  5. 12 0
      .idea/runConfigurations.xml
  6. 6 0
      .idea/vcs.xml
  7. 20 0
      README.md
  8. 1 0
      app/.gitignore
  9. 110 0
      app/build.gradle
  10. BIN
      app/libs/alipaySdk-20180601.jar
  11. BIN
      app/libs/bcprov-jdk15-136.jar
  12. BIN
      app/libs/codec.jar
  13. BIN
      app/libs/commons-codec-1.7.jar
  14. BIN
      app/libs/commons-lang-2.2.jar
  15. BIN
      app/libs/commons-net-3.3.jar
  16. BIN
      app/libs/dom4j-1.6.1.jar
  17. BIN
      app/libs/umeng-analytics-v6.0.9.jar
  18. 21 0
      app/proguard-rules.pro
  19. 26 0
      app/src/androidTest/java/com/edufound/mobile/ExampleInstrumentedTest.java
  20. 140 0
      app/src/main/AndroidManifest.xml
  21. 212 0
      app/src/main/java/com/edufound/mobile/activity/IJKPlayerActivity.java
  22. 223 0
      app/src/main/java/com/edufound/mobile/activity/MainActivity.java
  23. 205 0
      app/src/main/java/com/edufound/mobile/activity/VideoActivity.java
  24. 156 0
      app/src/main/java/com/edufound/mobile/application/EApplication.java
  25. 135 0
      app/src/main/java/com/edufound/mobile/base/BaseActivity.java
  26. 15 0
      app/src/main/java/com/edufound/mobile/base/BaseModel.java
  27. 9 0
      app/src/main/java/com/edufound/mobile/base/BasePersenter.java
  28. 15 0
      app/src/main/java/com/edufound/mobile/base/BaseView.java
  29. 14 0
      app/src/main/java/com/edufound/mobile/bean/FunPayDataBean.java
  30. 128 0
      app/src/main/java/com/edufound/mobile/bean/NotificationBean.java
  31. 8 0
      app/src/main/java/com/edufound/mobile/bean/UpgradeBean.java
  32. 103 0
      app/src/main/java/com/edufound/mobile/ijkplayer/application/Settings.java
  33. 57 0
      app/src/main/java/com/edufound/mobile/ijkplayer/media/FileMediaDataSource.java
  34. 42 0
      app/src/main/java/com/edufound/mobile/ijkplayer/media/IMediaController.java
  35. 87 0
      app/src/main/java/com/edufound/mobile/ijkplayer/media/IRenderView.java
  36. 1149 0
      app/src/main/java/com/edufound/mobile/ijkplayer/media/IjkVideoView.java
  37. 215 0
      app/src/main/java/com/edufound/mobile/ijkplayer/media/MeasureHelper.java
  38. 288 0
      app/src/main/java/com/edufound/mobile/ijkplayer/media/SurfaceRenderView.java
  39. 370 0
      app/src/main/java/com/edufound/mobile/ijkplayer/media/TextureRenderView.java
  40. 63 0
      app/src/main/java/com/edufound/mobile/ijkplayer/services/MediaPlayerService.java
  41. 42 0
      app/src/main/java/com/edufound/mobile/interfaces/EfunboxPayInterfaces.java
  42. 289 0
      app/src/main/java/com/edufound/mobile/interfaces/JsInterfaces.java
  43. 30 0
      app/src/main/java/com/edufound/mobile/main/MainModel.java
  44. 437 0
      app/src/main/java/com/edufound/mobile/main/MainPersenter.java
  45. 37 0
      app/src/main/java/com/edufound/mobile/main/MainView.java
  46. 113 0
      app/src/main/java/com/edufound/mobile/pay/PayActivity.java
  47. 46 0
      app/src/main/java/com/edufound/mobile/pay/PayInit.java
  48. 154 0
      app/src/main/java/com/edufound/mobile/pay/PayPersenter.java
  49. 1 0
      app/src/main/java/com/edufound/mobile/pay/ali/PayResult.java
  50. 37 0
      app/src/main/java/com/edufound/mobile/push/MipushTestActivity.java
  51. 33 0
      app/src/main/java/com/edufound/mobile/receiver/HomeKeyEventReceiver.java
  52. 103 0
      app/src/main/java/com/edufound/mobile/receiver/NetworkChangeReceiver.java
  53. 67 0
      app/src/main/java/com/edufound/mobile/util/AesUtil.java
  54. 60 0
      app/src/main/java/com/edufound/mobile/util/ContextUtil.java
  55. 192 0
      app/src/main/java/com/edufound/mobile/util/DeviceUtil.java
  56. 54 0
      app/src/main/java/com/edufound/mobile/util/DeviceUuidFactory.java
  57. 20 0
      app/src/main/java/com/edufound/mobile/util/DrawableUtil.java
  58. 691 0
      app/src/main/java/com/edufound/mobile/util/EduFoundUtil.java
  59. 151 0
      app/src/main/java/com/edufound/mobile/util/LiuHaiScreenUtil.java
  60. 19 0
      app/src/main/java/com/edufound/mobile/util/Logger.java
  61. 142 0
      app/src/main/java/com/edufound/mobile/util/NotificationUtil.java
  62. 147 0
      app/src/main/java/com/edufound/mobile/util/OKHttpUtil.java
  63. 230 0
      app/src/main/java/com/edufound/mobile/util/PlayerGestureListener.java
  64. 122 0
      app/src/main/java/com/edufound/mobile/util/SPutil.java
  65. 131 0
      app/src/main/java/com/edufound/mobile/util/ShowDebugUrl.java
  66. 142 0
      app/src/main/java/com/edufound/mobile/util/ShowDevice.java
  67. 140 0
      app/src/main/java/com/edufound/mobile/util/ShowSetting.java
  68. 16 0
      app/src/main/java/com/edufound/mobile/util/ToastUtil.java
  69. 150 0
      app/src/main/java/com/edufound/mobile/util/UpdateUtil.java
  70. 33 0
      app/src/main/java/com/edufound/mobile/video/VideoAView.java
  71. 15 0
      app/src/main/java/com/edufound/mobile/video/VideoModel.java
  72. 905 0
      app/src/main/java/com/edufound/mobile/video/VideoPersenter.java
  73. 98 0
      app/src/main/java/com/edufound/mobile/view/ErrorView.java
  74. 147 0
      app/src/main/java/com/edufound/mobile/wxapi/WXEntryActivity.java
  75. 68 0
      app/src/main/java/com/edufound/mobile/wxapi/WXPayEntryActivity.java
  76. 34 0
      app/src/main/res/drawable-v24/ic_launcher_foreground.xml
  77. 66 0
      app/src/main/res/drawable/edufound_loading.xml
  78. BIN
      app/src/main/res/drawable/edufound_player_pause.png
  79. BIN
      app/src/main/res/drawable/edufound_player_play.png
  80. BIN
      app/src/main/res/drawable/efunbox_window_bg.jpg
  81. 170 0
      app/src/main/res/drawable/ic_launcher_background.xml
  82. BIN
      app/src/main/res/drawable/icon_mobile_256_v8.png
  83. BIN
      app/src/main/res/drawable/loading1.png
  84. BIN
      app/src/main/res/drawable/loading10.png
  85. BIN
      app/src/main/res/drawable/loading11.png
  86. BIN
      app/src/main/res/drawable/loading12.png
  87. BIN
      app/src/main/res/drawable/loading13.png
  88. BIN
      app/src/main/res/drawable/loading14.png
  89. BIN
      app/src/main/res/drawable/loading15.png
  90. BIN
      app/src/main/res/drawable/loading16.png
  91. BIN
      app/src/main/res/drawable/loading17.png
  92. BIN
      app/src/main/res/drawable/loading18.png
  93. BIN
      app/src/main/res/drawable/loading19.png
  94. BIN
      app/src/main/res/drawable/loading2.png
  95. BIN
      app/src/main/res/drawable/loading20.png
  96. BIN
      app/src/main/res/drawable/loading3.png
  97. BIN
      app/src/main/res/drawable/loading4.png
  98. BIN
      app/src/main/res/drawable/loading5.png
  99. BIN
      app/src/main/res/drawable/loading6.png
  100. 0 0
      app/src/main/res/drawable/loading7.png

+ 13 - 0
.gitignore

@@ -0,0 +1,13 @@
+*.iml
+.gradle
+/local.properties
+/.idea/caches
+/.idea/libraries
+/.idea/modules.xml
+/.idea/workspace.xml
+/.idea/navEditor.xml
+/.idea/assetWizardSettings.xml
+.DS_Store
+/build
+/captures
+.externalNativeBuild

+ 29 - 0
.idea/codeStyles/Project.xml

@@ -0,0 +1,29 @@
+<component name="ProjectCodeStyleConfiguration">
+  <code_scheme name="Project" version="173">
+    <Objective-C-extensions>
+      <file>
+        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
+        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Macro" />
+        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Typedef" />
+        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Enum" />
+        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Constant" />
+        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Global" />
+        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Struct" />
+        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="FunctionPredecl" />
+        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Function" />
+      </file>
+      <class>
+        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Property" />
+        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Synthesize" />
+        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InitMethod" />
+        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="StaticMethod" />
+        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InstanceMethod" />
+        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="DeallocMethod" />
+      </class>
+      <extensions>
+        <pair source="cpp" header="h" fileNamingConvention="NONE" />
+        <pair source="c" header="h" fileNamingConvention="NONE" />
+      </extensions>
+    </Objective-C-extensions>
+  </code_scheme>
+</component>

+ 15 - 0
.idea/gradle.xml

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="GradleSettings">
+    <option name="linkedExternalProjectsSettings">
+      <GradleProjectSettings>
+        <compositeConfiguration>
+          <compositeBuild compositeDefinitionSource="SCRIPT" />
+        </compositeConfiguration>
+        <option name="distributionType" value="DEFAULT_WRAPPED" />
+        <option name="externalProjectPath" value="$PROJECT_DIR$" />
+        <option name="resolveModulePerSourceSet" value="false" />
+      </GradleProjectSettings>
+    </option>
+  </component>
+</project>

+ 9 - 0
.idea/misc.xml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="1.8" project-jdk-type="JavaSDK">
+    <output url="file://$PROJECT_DIR$/build/classes" />
+  </component>
+  <component name="ProjectType">
+    <option name="id" value="Android" />
+  </component>
+</project>

+ 12 - 0
.idea/runConfigurations.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="RunConfigurationProducerService">
+    <option name="ignoredProducers">
+      <set>
+        <option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
+        <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
+        <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
+      </set>
+    </option>
+  </component>
+</project>

+ 6 - 0
.idea/vcs.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="" vcs="Git" />
+  </component>
+</project>

+ 20 - 0
README.md

@@ -0,0 +1,20 @@
+# 义方快乐学堂8.0项目(移动端)
+## 基础调用方法:
+### 1.efunboxJS.upgradeApp(json);(应用自升级)
+####   json:"{'title': '升级','type': '1','context': '1.修正登录异常\n2.xxxxxx','download_url':'url'}"
+### 2.efunboxJS.closeApp();(关闭应用)
+### 3.efunboxJS.WeChatLogin() ----call back js ---WeChatLoginSuccess(data)(微信登录)
+### 4.efunboxJS.clickMusic(left,right);(点击音效 left,right是string类型:"1","1")
+### 5.efunboxJS.toMiniProgram(programId,path);(programId:小程序id,path:跳转路径(首页传空)
+
+-----
+## 支付调用方法:
+#### 1.WeChatPay(String json)(微信支付)
+#### 2.AliPay(String orderInfo) (支付宝支付)
+
+-----
+## 播放调用方法
+### efunboxJS.playVideo(json,playindex, playtype);
+### 样例 json:[{"videourl":"1","videoname":"name1","videoId":"321231","videoplaytime":"2000"},{"videourl":"1","videoname":"name1","videoId":"321231","videoplaytime":"2000"}]
+### playindex:0  (int类型)
+### playtype:0 (int类型,0=单独播放,播放完成直接关闭。1=单独循环播放。2=列表播放,播放完列表关闭)

+ 1 - 0
app/.gitignore

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

+ 110 - 0
app/build.gradle

@@ -0,0 +1,110 @@
+apply plugin: "com.android.application"
+
+android {
+    signingConfigs {
+        efunbox {
+            keyAlias "edufound_key"
+            keyPassword "edufound321"
+            storeFile file("C:/Users/Candy/Desktop/edufound.keystore")
+            storePassword "edufound123"
+        }
+        debug {
+            keyAlias "edufound_key"
+            keyPassword "edufound321"
+            storeFile file("C:/Users/Candy/Desktop/edufound.keystore")
+            storePassword "edufound123"
+        }
+    }
+    compileSdkVersion 28
+    defaultConfig {
+        applicationId "com.edufound.mobile"
+        minSdkVersion 16
+        targetSdkVersion 28
+        versionCode 80000
+        versionName "8.0.0.0"
+        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+        multiDexEnabled true
+    }
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro"
+        }
+    }
+    repositories {
+        flatDir {
+            dirs "libs"
+        }
+        mavenCentral()
+    }
+    sourceSets {
+        main {
+            jniLibs.srcDirs = ["libs"]
+        }
+    }
+}
+allprojects {
+    repositories {
+        jcenter()
+    }
+}
+dependencies {
+    implementation fileTree(dir: "libs", include: ["*.jar"])
+    implementation "com.android.support:appcompat-v7:28.0.0"
+    implementation "android.arch.navigation:navigation-fragment:1.0.0"
+    implementation "android.arch.navigation:navigation-ui:1.0.0"
+    implementation "com.android.support:design:28.0.0"
+    implementation "com.android.support.constraint:constraint-layout:1.1.3"
+    testImplementation "junit:junit:4.12"
+    androidTestImplementation "com.android.support.test:runner:1.0.2"
+    androidTestImplementation "com.android.support.test.espresso:espresso-core:3.0.2"
+    // required, enough for most devices.
+    api "tv.danmaku.ijk.media:ijkplayer-java:0.8.2"
+    api "tv.danmaku.ijk.media:ijkplayer-armv7a:0.8.2"
+    // Other ABIs: optional
+    api "tv.danmaku.ijk.media:ijkplayer-armv5:0.8.2"
+    api "tv.danmaku.ijk.media:ijkplayer-arm64:0.8.2"
+    api "tv.danmaku.ijk.media:ijkplayer-x86:0.8.2"
+    api "tv.danmaku.ijk.media:ijkplayer-x86_64:0.8.2"
+    // ExoPlayer as IMediaPlayer: optional, experimental
+    api "tv.danmaku.ijk.media:ijkplayer-exo:0.8.2"
+    api files("libs/codec.jar")
+    api files("libs/commons-codec-1.7.jar")
+    api files("libs/commons-lang-2.2.jar")
+    api files("libs/commons-net-3.3.jar")
+    api files("libs/bcprov-jdk15-136.jar")
+    api "com.google.code.gson:gson:2.8.6"
+    //微信登录、微信支付等
+    implementation "com.tencent.mm.opensdk:wechat-sdk-android-with-mta:+"
+    //支付宝支付
+    implementation files("libs/alipaySdk-20180601.jar")
+    implementation files("libs/dom4j-1.6.1.jar")
+    //okhttp
+    implementation "com.squareup.okhttp3:okhttp:3.4.1"
+
+    //多种seekbar
+    implementation "com.github.warkiz.widget:indicatorseekbar:2.1.0"
+
+//    //PushSDK必须依赖基础组件库,所以需要加入对应依赖
+//    implementation "com.umeng.umsdk:common:2.1.0"
+//    //PushSDK
+//    implementation "com.umeng.umsdk:push:6.0.1"
+    api project(":push")
+    //小米Push通道
+    implementation "com.umeng.umsdk:xiaomi-push:3.6.17"
+    implementation "com.umeng.umsdk:xiaomi-umengaccs:1.1.0"
+    //华为Push通道
+    implementation "com.umeng.umsdk:huawei-basetb:2.6.3.305"
+    implementation "com.umeng.umsdk:huawei-pushtb:2.6.3.305"
+    implementation "com.umeng.umsdk:huawei-umengaccs:1.2.1"
+    //魅族Push通道
+    implementation "com.umeng.umsdk:meizu-push:3.8.1"
+    implementation "com.umeng.umsdk:meizu-umengaccs:1.0.6"
+    //vivo Push通道
+    implementation "com.umeng.umsdk:vivo-push:2.3.1"
+    implementation "com.umeng.umsdk:vivo-umengaccs:1.0.4"
+    //Oppo Push通道
+    implementation "com.umeng.umsdk:oppo-push:1.0.1"
+    implementation "com.umeng.umsdk:oppo-umengaccs:1.0.3"
+}
+

BIN
app/libs/alipaySdk-20180601.jar


BIN
app/libs/bcprov-jdk15-136.jar


BIN
app/libs/codec.jar


BIN
app/libs/commons-codec-1.7.jar


BIN
app/libs/commons-lang-2.2.jar


BIN
app/libs/commons-net-3.3.jar


BIN
app/libs/dom4j-1.6.1.jar


BIN
app/libs/umeng-analytics-v6.0.9.jar


+ 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

+ 26 - 0
app/src/androidTest/java/com/edufound/mobile/ExampleInstrumentedTest.java

@@ -0,0 +1,26 @@
+package com.edufound.mobile;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+    @Test
+    public void useAppContext() {
+        // Context of the app under test.
+        Context appContext = InstrumentationRegistry.getTargetContext();
+
+        assertEquals("com.edufound.mobile", appContext.getPackageName());
+    }
+}

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

@@ -0,0 +1,140 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    package="com.edufound.mobile">
+
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.WAKE_LOCK" />
+    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
+    <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+    <uses-permission android:name="com.xiaomi.permission.AUTH_THIRDPAY" />
+
+    <uses-sdk tools:overrideLibrary="tv.danmaku.ijk.media.player_arm64,tv.danmaku.ijk.media.player_x86_64" />
+
+
+    <application
+        android:name=".application.EApplication"
+        android:allowBackup="false"
+        android:icon="@drawable/icon_mobile_256_v8"
+        android:label="@string/app_name"
+        android:networkSecurityConfig="@xml/network_security_config"
+        android:resizeableActivity="true"
+        android:supportsRtl="true"
+        android:theme="@style/NoTitle"
+        tools:replace="allowBackup">
+
+        <meta-data
+            android:name="android.notch_support"
+            android:value="true" />
+        <meta-data
+            android:name="android.max_aspect"
+            android:value="2.1" />
+        <meta-data
+            android:name="notch.config"
+            android:value="portrait|landscape" />
+
+        <activity
+            android:name=".activity.MainActivity"
+            android:configChanges="orientation|keyboardHidden|screenSize"
+            android:maxAspectRatio="2.1"
+            android:resizeableActivity="true"
+            android:screenOrientation="landscape"
+            android:theme="@style/AppStartTheme">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+
+        </activity>
+        <activity
+            android:name=".activity.IJKPlayerActivity"
+            android:configChanges="orientation|screenSize"
+            android:screenOrientation="landscape"
+            android:theme="@style/NoTitle"></activity>
+        <activity
+            android:name=".activity.VideoActivity"
+            android:configChanges="orientation|screenSize"
+            android:screenOrientation="landscape"
+            android:theme="@style/NoTitle"></activity>
+
+
+        <!--友盟start-->
+        <meta-data
+            android:name="UMENG_APPKEY"
+            android:value="5e34d2fb4ca3574b1800005b" />
+        <meta-data
+            android:name="UMENG_CHANNEL"
+            android:value="@string/app_code_yf" />
+        <!--友盟end-->
+
+        <activity
+            android:name=".pay.PayActivity"
+            android:configChanges="orientation|screenSize"
+            android:screenOrientation="portrait"
+            android:theme="@style/NoTitle"></activity>
+
+        <provider
+            android:name="android.support.v4.content.FileProvider"
+            android:authorities="com.edufound.mobile.fileprovider"
+            android:exported="false"
+            android:grantUriPermissions="true">
+            <meta-data
+                android:name="android.support.FILE_PROVIDER_PATHS"
+                android:resource="@xml/apk_file_paths" />
+        </provider>
+
+        <activity
+            android:name=".wxapi.WXEntryActivity"
+            android:exported="true"
+            android:screenOrientation="landscape"
+            android:theme="@style/transcutestyle"></activity>
+
+        <activity
+            android:name=".wxapi.WXPayEntryActivity"
+            android:exported="true"
+            android:screenOrientation="landscape"
+            android:theme="@style/transcutestyle">
+
+        </activity>
+
+        <activity
+            android:name="com.alipay.sdk.app.H5PayActivity"
+            android:configChanges="orientation|keyboardHidden|navigation|screenSize"
+            android:exported="false"
+            android:screenOrientation="behind"
+            android:windowSoftInputMode="adjustResize|stateHidden"></activity>
+        <activity
+            android:name="com.alipay.sdk.app.H5AuthActivity"
+            android:configChanges="orientation|keyboardHidden|navigation"
+            android:exported="false"
+            android:screenOrientation="behind"
+            android:windowSoftInputMode="adjustResize|stateHidden"></activity>
+
+
+        <activity
+            android:name=".push.MipushTestActivity"
+            android:exported="true"
+            android:launchMode="singleTask" />
+
+
+        <meta-data
+            android:name="com.huawei.hms.client.appid"
+            android:value="appid=xxxxxx" />
+
+        <!--vivo push参数声明 -->
+        <!-- vivo start-->
+        <meta-data
+            android:name="com.vivo.push.api_key"
+            android:value="xxxxxx" />
+        <meta-data
+            android:name="com.vivo.push.app_id"
+            android:value="xxxxxx" />
+        <!-- VIVO end-->
+    </application>
+
+</manifest>

+ 212 - 0
app/src/main/java/com/edufound/mobile/activity/IJKPlayerActivity.java

@@ -0,0 +1,212 @@
+package com.edufound.mobile.activity;
+
+import android.app.Activity;
+import android.net.Uri;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.view.GestureDetector;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.widget.FrameLayout;
+
+import com.edufound.mobile.R;
+import com.edufound.mobile.base.BaseActivity;
+import com.edufound.mobile.ijkplayer.media.IjkVideoView;
+import com.edufound.mobile.util.ContextUtil;
+import com.edufound.mobile.util.EduFoundUtil;
+import com.edufound.mobile.util.Logger;
+import com.edufound.mobile.util.ToastUtil;
+import com.edufound.mobile.video.VideoAView;
+import com.edufound.mobile.video.VideoPersenter;
+
+import tv.danmaku.ijk.media.player.IMediaPlayer;
+import tv.danmaku.ijk.media.player.IjkMediaPlayer;
+
+public class IJKPlayerActivity extends BaseActivity implements VideoAView {
+
+    VideoPersenter mPersenter;
+    IjkVideoView mVideoView;
+    FrameLayout mFrameLayout;
+    IJKPlayerActivity mActivity;
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        setContentView(R.layout.activity_player);
+        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+        // init player
+        IjkMediaPlayer.loadLibrariesOnce(null);
+        IjkMediaPlayer.native_profileBegin("libijkplayer.so");
+        mPersenter = new VideoPersenter(this);
+        super.onCreate(savedInstanceState);
+    }
+
+
+    @Override
+    protected void initVew() {
+        super.initVew();
+        mFrameLayout = findViewById(R.id.player_frame);
+        mVideoView = new IjkVideoView(ContextUtil.getContext());
+        mVideoView.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
+        mVideoView.setOnCompletionListener(new IMediaPlayer.OnCompletionListener() {
+            @Override
+            public void onCompletion(IMediaPlayer iMediaPlayer) {
+                mPersenter.onCompletion();
+            }
+        });
+        mVideoView.setOnPreparedListener(new IMediaPlayer.OnPreparedListener() {
+            @Override
+            public void onPrepared(IMediaPlayer iMediaPlayer) {
+                mPersenter.onPrepared();
+            }
+        });
+        mVideoView.setOnInfoListener(new IMediaPlayer.OnInfoListener() {
+            @Override
+            public boolean onInfo(IMediaPlayer iMediaPlayer, int what, int extra) {
+                mPersenter.onInfo(what, extra);
+                return true;
+            }
+        });
+        mVideoView.setOnErrorListener(new IMediaPlayer.OnErrorListener() {
+            @Override
+            public boolean onError(IMediaPlayer iMediaPlayer, int what, int extra) {
+
+                return mPersenter.onError(what, extra);
+            }
+        });
+        mFrameLayout.addView(mVideoView);
+        mFrameLayout.addView(mPersenter.getPlayerController());
+        mPersenter.loadVideo(getIntent());
+    }
+
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        return mPersenter.onKeyDown(keyCode, event);
+    }
+
+    @Override
+    public boolean onKeyUp(int keyCode, KeyEvent event) {
+        return mPersenter.onKeyUp(keyCode, event);
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        activityFinish();
+
+    }
+
+    @Override
+    public void setVideoUri(Uri uri) {
+        mVideoView.setVideoURI(uri);
+    }
+
+    @Override
+    public void start() {
+        mVideoView.start();
+    }
+
+    @Override
+    public void pause() {
+        mVideoView.pause();
+    }
+
+    @Override
+    public void stop() {
+        mVideoView.stopPlayback();
+    }
+
+    @Override
+    public void releaseVideo() {
+        mVideoView.stopPlayback();
+        mVideoView.resume();
+        mVideoView.release(true);
+    }
+
+    @Override
+    public void seek(int seek) {
+        mVideoView.seekTo(seek);
+    }
+
+    @Override
+    public boolean isPlaying() {
+        return mVideoView.isPlaying();
+    }
+
+    @Override
+    public int getDuration() {
+        return mVideoView.getDuration();
+    }
+
+    @Override
+    public int getCurrent() {
+        return mVideoView.getCurrentPosition();
+    }
+
+    @Override
+    public void activityFinish() {
+        if (mVideoView != null) {
+            mVideoView.stopPlayback();
+        }
+        mVideoView = null;
+        mPersenter.destroy();
+        finish();
+//        System.exit(0);
+    }
+
+
+    @Override
+    public void showData(String text) {
+
+    }
+
+    @Override
+    public void DisconnNetWork() {
+        super.DisconnNetWork();
+        if (getLocalPckClas().equals(getTopActivity(this))) {
+            mPersenter.onDisConnNetWork();
+        }
+    }
+
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        return mPersenter.onTouchEvent(event);
+    }
+
+    @Override
+    public void ConnNeWork() {
+        super.ConnNeWork();
+        if (getLocalPckClas().equals(getTopActivity(this))) {
+            mPersenter.onConnNetWork();
+        }
+    }
+
+    @Override
+    public Activity getActivity() {
+        if (mActivity == null) {
+            mActivity = this;
+        }
+        return mActivity;
+    }
+
+
+    @Override
+    protected void onSaveInstanceState(Bundle outState) {
+//        super.onSaveInstanceState(outState);
+        mPersenter.onSaveInstanceState(outState);
+    }
+
+    @Override
+    protected void onRestoreInstanceState(Bundle savedInstanceState) {
+//        super.onRestoreInstanceState(savedInstanceState);
+        mPersenter.onRestoreInstanceState(savedInstanceState);
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        mPersenter.onResume();
+    }
+}

+ 223 - 0
app/src/main/java/com/edufound/mobile/activity/MainActivity.java

@@ -0,0 +1,223 @@
+package com.edufound.mobile.activity;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.graphics.drawable.AnimationDrawable;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.webkit.WebView;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+
+import com.edufound.mobile.R;
+import com.edufound.mobile.application.EApplication;
+import com.edufound.mobile.base.BaseActivity;
+import com.edufound.mobile.main.MainPersenter;
+import com.edufound.mobile.main.MainView;
+import com.edufound.mobile.util.ContextUtil;
+import com.edufound.mobile.util.DeviceUuidFactory;
+import com.edufound.mobile.util.Logger;
+import com.edufound.mobile.util.NotificationUtil;
+import com.edufound.mobile.util.SPutil;
+import com.edufound.mobile.util.ShowDebugUrl;
+
+
+//调用Persenter里面的方法
+public class MainActivity extends BaseActivity implements MainView {
+
+    private Activity mActivity;
+    FrameLayout mRootView;
+    ImageView mLoading;
+    MainPersenter mPersenter;
+    WebView mWebView;
+    boolean activityPay;
+    AnimationDrawable mLoadingAnim;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        setContentView(R.layout.activity_main);
+        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+        mActivity = this;
+        mPersenter = new MainPersenter(this);
+        initCloseMain();
+        super.onCreate(savedInstanceState);
+    }
+
+
+    @Override
+    protected void initVew() {
+        Logger.DebugE("initVew");
+        mRootView = findViewById(R.id.main_root);
+        mLoading = findViewById(R.id.main_webloading);
+        mLoadingAnim = (AnimationDrawable) mLoading.getBackground();
+        mLoadingAnim.start();
+//        为防止内存泄漏,用ContextUtil.getContext,但是不弹alert
+        mWebView = new WebView(ContextUtil.getContext());
+        //        //支持alert,但是容易内存泄漏
+//        mWebView = new WebView(MainActivity.this);
+        mPersenter.initWebView(mWebView);
+        mWebView.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
+        mRootView.addView(mWebView);
+        mWebView.bringToFront();
+        mLoading.bringToFront();
+        new DeviceUuidFactory(ContextUtil.getContext());
+        mPersenter.openWeb(getIntent());
+    }
+
+
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        ShowDebugUrl.dispatchKeyEvent(event, this);
+        super.onKeyDown(keyCode, event);
+        return mPersenter.onKeyDown(keyCode, event);
+    }
+
+    @Override
+    public boolean onKeyUp(int keyCode, KeyEvent event) {
+        return mPersenter.onKeyUp(keyCode, event);
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+//        System.exit(0);
+        mPersenter.getJsInterfaces().desClickMusic();
+        unregisterReceiver(mainBroad);
+        mWebView.loadUrl("");
+        mWebView.removeAllViews();
+        mWebView.destroy();
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        NotificationUtil.choseNotification(mActivity);
+        if (!ContextUtil.getNetWorkState()) {
+            //断网状态
+            DisconnNetWork();
+        }
+    }
+
+    @Override
+    public void showData(String text) {
+//        Toast.makeText(ContextUtil.getContext(), text, Toast.LENGTH_SHORT).show();
+    }
+
+    @Override
+    public void loadUrl(String url) {
+        mWebView.loadUrl(url);
+    }
+
+
+    @Override
+    public void loadJsMehtod(String method) {
+        mWebView.loadUrl("javascript:" + method + "");
+    }
+
+
+    @Override
+    public void DisconnNetWork() {
+        super.DisconnNetWork();
+        if (getLocalPckClas().equals(getTopActivity(this))) {
+            mPersenter.onDisConnNetWork();
+        }
+    }
+
+    @Override
+    public void ConnNeWork() {
+        super.ConnNeWork();
+        if (getLocalPckClas().equals(getTopActivity(this))) {
+            mPersenter.onConnNetWork();
+        }
+    }
+
+    @Override
+    public Activity getActivity() {
+        if (mActivity == null) {
+            mActivity = this;
+        }
+        return mActivity;
+    }
+
+    @Override
+    public void setActivityPay(boolean bool) {
+        activityPay = bool;
+    }
+
+    @Override
+    public boolean getActivityPay() {
+        return activityPay;
+    }
+
+    @Override
+    public void acPostDelayed(Runnable runnable, int time) {
+        mWebView.postDelayed(runnable, time);
+    }
+
+    @Override
+    public void destroyWeb() {
+        mWebView.clearCache(true);
+        mWebView.removeAllViews();
+        mWebView.clearHistory();
+//        mWebView.destroy();
+    }
+
+    @Override
+    public void hideLoading() {
+        mLoading.setVisibility(View.GONE);
+    }
+
+    @Override
+    public void stopWebView() {
+        mWebView.pauseTimers();
+    }
+
+    @Override
+    public void resumeWebView() {
+        mWebView.resumeTimers();
+    }
+
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
+        super.onActivityResult(requestCode, resultCode, data);
+        mPersenter.onActivityResult(requestCode, resultCode, data);
+    }
+
+    void initCloseMain() {
+        IntentFilter intentFilter = new IntentFilter();
+        intentFilter.addAction(ContextUtil.CLOSE_ACTIVITY_MAIN);
+        intentFilter.addAction(ContextUtil.NOTIFICATION_WEB_PLAYERTIME);
+        registerReceiver(mainBroad, intentFilter);
+    }
+
+    BroadcastReceiver mainBroad = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            switch (intent.getAction()) {
+                case ContextUtil.CLOSE_ACTIVITY_MAIN:
+                    EApplication.clearActivity();
+                    Intent intent_restart = new Intent(ContextUtil.CLOSE_ACTIVITY_SPLASH);
+                    getActivity().sendBroadcast(intent_restart);
+                    break;
+                case ContextUtil.NOTIFICATION_WEB_PLAYERTIME:
+                    String time = intent.getStringExtra("over_time");
+                    String id = intent.getStringExtra("over_id");
+                    String neetpost = intent.getStringExtra("over_neetpost");
+                    String moduletype = intent.getStringExtra("over_moduletype");
+                    loadJsMehtod("videoTimeRecord(" + id + "," + time + "," + neetpost + ",'" + moduletype + "')");
+                    break;
+            }
+
+        }
+    };
+
+
+}

+ 205 - 0
app/src/main/java/com/edufound/mobile/activity/VideoActivity.java

@@ -0,0 +1,205 @@
+package com.edufound.mobile.activity;
+
+import android.app.Activity;
+import android.media.MediaPlayer;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.annotation.RequiresApi;
+import android.view.Gravity;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.widget.FrameLayout;
+import android.widget.VideoView;
+
+import com.edufound.mobile.R;
+import com.edufound.mobile.base.BaseActivity;
+import com.edufound.mobile.util.ContextUtil;
+import com.edufound.mobile.util.Logger;
+import com.edufound.mobile.util.ToastUtil;
+import com.edufound.mobile.video.VideoAView;
+import com.edufound.mobile.video.VideoPersenter;
+
+public class VideoActivity extends BaseActivity implements VideoAView {
+
+    VideoActivity mActivity;
+    VideoPersenter mPersenter;
+    VideoView mVideoView;
+    FrameLayout mFrameLayout;
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        setContentView(R.layout.activity_player);
+        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+        mPersenter = new VideoPersenter(this);
+        super.onCreate(savedInstanceState);
+    }
+
+    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
+    @Override
+    protected void initVew() {
+        super.initVew();
+        mFrameLayout = findViewById(R.id.player_frame);
+        mVideoView = new VideoView(ContextUtil.getContext());
+        mVideoView.resume();
+        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
+        params.gravity = Gravity.CENTER;
+        mVideoView.setLayoutParams(params);
+        mVideoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
+            @Override
+            public void onCompletion(MediaPlayer mp) {
+                mPersenter.onCompletion();
+            }
+        });
+        mVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
+            @Override
+            public void onPrepared(MediaPlayer mp) {
+                mPersenter.onPrepared();
+            }
+        });
+        mVideoView.setOnInfoListener(new MediaPlayer.OnInfoListener() {
+            @Override
+            public boolean onInfo(MediaPlayer mp, int what, int extra) {
+                mPersenter.onInfo(what, extra);
+                return true;
+            }
+        });
+        mVideoView.setOnErrorListener(new MediaPlayer.OnErrorListener() {
+            @Override
+            public boolean onError(MediaPlayer mp, int what, int extra) {
+                return mPersenter.onError(what, extra);
+            }
+        });
+        mFrameLayout.addView(mVideoView);
+        mFrameLayout.addView(mPersenter.getPlayerController());
+        mPersenter.loadVideo(getIntent());
+    }
+
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        return mPersenter.onKeyDown(keyCode, event);
+    }
+
+    @Override
+    public boolean onKeyUp(int keyCode, KeyEvent event) {
+        return mPersenter.onKeyUp(keyCode, event);
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        activityFinish();
+
+    }
+
+    @Override
+    public void setVideoUri(Uri uri) {
+        mVideoView.setVideoURI(uri);
+    }
+
+    @Override
+    public void start() {
+        mVideoView.start();
+    }
+
+    @Override
+    public void pause() {
+        mVideoView.pause();
+    }
+
+    @Override
+    public void stop() {
+        mVideoView.stopPlayback();
+    }
+
+    @Override
+    public void releaseVideo() {
+        mVideoView.stopPlayback();
+        mVideoView.resume();
+    }
+
+    @Override
+    public void seek(int seek) {
+        mVideoView.seekTo(seek);
+    }
+
+    @Override
+    public boolean isPlaying() {
+        return mVideoView.isPlaying();
+    }
+
+    @Override
+    public int getDuration() {
+        return mVideoView.getDuration();
+    }
+
+    @Override
+    public int getCurrent() {
+        return mVideoView.getCurrentPosition();
+    }
+
+    @Override
+    public void activityFinish() {
+        if (mVideoView != null) {
+            mVideoView.stopPlayback();
+        }
+        mVideoView = null;
+        mPersenter.destroy();
+        finish();
+    }
+
+
+    @Override
+    public void showData(String text) {
+
+    }
+
+    @Override
+    public void DisconnNetWork() {
+        super.DisconnNetWork();
+        if (getLocalPckClas().equals(getTopActivity(this))) {
+            mPersenter.onDisConnNetWork();
+        }
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        return mPersenter.onTouchEvent(event);
+    }
+
+    @Override
+    public void ConnNeWork() {
+        super.ConnNeWork();
+        if (getLocalPckClas().equals(getTopActivity(this))) {
+        }
+    }
+
+    @Override
+    public Activity getActivity() {
+        if (mActivity == null) {
+            mActivity = this;
+        }
+        return mActivity;
+    }
+
+    @Override
+    protected void onSaveInstanceState(Bundle outState) {
+//        super.onSaveInstanceState(outState);
+        mPersenter.onSaveInstanceState(outState);
+    }
+
+    @Override
+    protected void onRestoreInstanceState(Bundle savedInstanceState) {
+//        super.onRestoreInstanceState(savedInstanceState);
+        mPersenter.onRestoreInstanceState(savedInstanceState);
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        mPersenter.onResume();
+    }
+}

+ 156 - 0
app/src/main/java/com/edufound/mobile/application/EApplication.java

@@ -0,0 +1,156 @@
+package com.edufound.mobile.application;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.app.Application;
+import android.content.Context;
+import android.content.Intent;
+import android.support.annotation.Nullable;
+import android.view.Window;
+
+import com.edufound.mobile.R;
+import com.edufound.mobile.pay.PayInit;
+import com.edufound.mobile.util.ContextUtil;
+import com.edufound.mobile.util.Logger;
+import com.edufound.mobile.util.SPutil;
+import com.umeng.commonsdk.UMConfigure;
+import com.umeng.message.IUmengRegisterCallback;
+import com.umeng.message.PushAgent;
+
+import org.android.agoo.huawei.HuaWeiRegister;
+import org.android.agoo.vivo.VivoRegister;
+import org.android.agoo.xiaomi.MiPushRegistar;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public class EApplication extends Application {
+
+
+    final String XIAOMI_ID = "";
+    final String XIAOMI_KEY = "";
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        ContextUtil.setContext(this);
+        ContextUtil.setApplication(this);
+        //上线关掉debug模式
+        ContextUtil.setIsDebug(true);
+        //根据appcode初始化支付sdk
+        UMConfigure.setLogEnabled(true);
+        UMConfigure.init(this, "5e34d2fb4ca3574b1800005b", getAppCode() + "", UMConfigure.DEVICE_TYPE_PHONE, "dfc59afd6dc6b1550ff1c2e0c7eb10fd");
+        PushAgent mPushAgent = PushAgent.getInstance(this);
+        mPushAgent.register(new IUmengRegisterCallback() {
+            @Override
+            public void onSuccess(String deviceToken) {
+                Logger.e("DeviceToken:" + deviceToken);
+            }
+
+            @Override
+            public void onFailure(String s, String s1) {
+                Logger.e("注册失败:-------->  " + "s:" + s + ",s1:" + s1);
+            }
+        });
+
+
+        if (getAppCode().equals(getString(R.string.app_code_xm))) {
+            MiPushRegistar.register(this, XIAOMI_ID, XIAOMI_KEY);
+        } else if (getAppCode().equals(getString(R.string.app_code_huawei))) {
+            HuaWeiRegister.register(this);
+        } else if (getAppCode().equals(getString(R.string.app_code_vivo))) {
+            VivoRegister.register(this);
+        }
+
+
+        PayInit.getInstance().initPaySDK(Integer.valueOf(getAppCode()), EApplication.this);
+        if (!getPackageName().equals(
+                getProcessName(getApplicationContext(), android.os.Process.myPid()))) {
+            return;
+        }
+
+        //如果是新应用,默认设置播放器为ijkplayer
+        if (SPutil.getPrefInt(this, SPutil.videoType, 0) == 0) {
+            SPutil.setPrefInt(this, SPutil.videoType, SPutil.VIDEO_IJKPLAYER);
+        }
+        /*
+        *    AppKey
+                5e34d2fb4ca3574b1800005b
+            Umeng Message Secret
+                dfc59afd6dc6b1550ff1c2e0c7eb10fd
+            App Master Secret
+                ojy29ycnnynpvyetpunc2m0ija4vskyo
+        *
+        * */
+
+    }
+
+    public static void exitApp() {
+        Intent intent_close = new Intent(ContextUtil.CLOSE_ACTIVITY_SPLASH);
+        ContextUtil.getContext().sendBroadcast(intent_close);
+    }
+
+    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 clearActivity() {
+        List<Activity> myAclist = getAllActivitys();
+        for (int i = 0; i < myAclist.size(); i++) {
+            myAclist.get(i).finish();
+        }
+    }
+
+    @Nullable
+    public String getProcessName(Context cxt, int pid) {
+        ActivityManager am = (ActivityManager) cxt.getSystemService(Context.ACTIVITY_SERVICE);
+        if (am == null) {
+            return null;
+        }
+
+        List<ActivityManager.RunningAppProcessInfo> runningApps = am.getRunningAppProcesses();
+        if (runningApps != null && !runningApps.isEmpty()) {
+            for (ActivityManager.RunningAppProcessInfo procInfo : runningApps) {
+                if (procInfo.pid == pid) {
+                    return procInfo.processName;
+                }
+            }
+        }
+
+        return null;
+    }
+
+
+    public static String getAppCode() {
+        //记得改友盟code
+        return ContextUtil.getContext().getString(R.string.app_code_yf);
+    }
+
+
+}
+
+

+ 135 - 0
app/src/main/java/com/edufound/mobile/base/BaseActivity.java

@@ -0,0 +1,135 @@
+package com.edufound.mobile.base;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Build;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.Window;
+
+import com.edufound.mobile.application.EApplication;
+import com.edufound.mobile.receiver.HomeKeyEventReceiver;
+import com.edufound.mobile.receiver.NetworkChangeReceiver;
+import com.edufound.mobile.util.ContextUtil;
+import com.edufound.mobile.util.EduFoundUtil;
+import com.edufound.mobile.util.LiuHaiScreenUtil;
+import com.edufound.mobile.util.Logger;
+import com.edufound.mobile.util.ShowDevice;
+import com.edufound.mobile.util.ShowSetting;
+import com.umeng.analytics.MobclickAgent;
+import com.umeng.message.PushAgent;
+
+public class BaseActivity extends Activity implements BaseView {
+
+    //按home键的receiver
+    HomeKeyEventReceiver mHomeReceiver;
+    //网络异常监听
+    NetworkChangeReceiver mNetworkReceiver;
+    Window mWindow;
+    Activity activity;
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        activity = this;
+        mWindow = getWindow();
+        mWindow.getDecorView().setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() {
+            @Override
+            public void onSystemUiVisibilityChange(int visibility) {
+                EduFoundUtil.setHideVirtualKey(mWindow);
+            }
+        });
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
+            LiuHaiScreenUtil.openFullScreenModel(activity);
+        }
+        initBoardCastReceiver();
+        PushAgent.getInstance(this).onAppStart();
+        initVew();
+    }
+
+    @Override
+    protected void onStart() {
+        super.onStart();
+    }
+
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        ShowDevice.dispatchKeyEvent(event, this);
+        ShowSetting.dispatchKeyEvent(event, this);
+        return super.onKeyDown(keyCode, event);
+    }
+
+
+    void initBoardCastReceiver() {
+        Logger.DebugE("BaseActivity---initBoardCastReceiver");
+        mHomeReceiver = new HomeKeyEventReceiver();
+        registerReceiver(mHomeReceiver, new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
+        mNetworkReceiver = new NetworkChangeReceiver(this);
+        IntentFilter netFilter = new IntentFilter();
+        netFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
+        registerReceiver(mNetworkReceiver, netFilter);
+    }
+
+    protected void initVew() {
+
+    }
+
+    @Override
+    protected void onResume() {
+        MobclickAgent.onResume(this);
+//        if (DeviceUuidFactory.getUuid().toString() != null) {
+//            MobclickAgent.onProfileSignIn(DeviceUuidFactory.getUuid().toString());
+//        }
+        super.onResume();
+    }
+
+    @Override
+    protected void onPause() {
+        MobclickAgent.onPause(this);
+        MobclickAgent.onProfileSignOff();
+        super.onPause();
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        unregisterReceiver(mHomeReceiver);
+        unregisterReceiver(mNetworkReceiver);
+    }
+
+
+    @Override
+    public void showData(String text) {
+
+    }
+
+    @Override
+    public void DisconnNetWork() {
+
+    }
+
+    @Override
+    public void ConnNeWork() {
+    }
+
+    @Override
+    public Activity getActivity() {
+        return null;
+    }
+
+    public String getTopActivity(Context context) {
+        ActivityManager am = (ActivityManager) context.getSystemService(context.ACTIVITY_SERVICE);
+        ComponentName cn = am.getRunningTasks(1).get(0).topActivity;
+        return cn.getClassName();
+    }
+
+    public String getLocalPckClas() {
+        return getPackageName() + "." + getLocalClassName();
+    }
+}

+ 15 - 0
app/src/main/java/com/edufound/mobile/base/BaseModel.java

@@ -0,0 +1,15 @@
+package com.edufound.mobile.base;
+
+public interface BaseModel {
+
+    void LoadData(LoadDataBack callback);
+
+    interface LoadDataBack {
+
+        void success(String datajson);
+
+        void failure();
+    }
+
+}
+

+ 9 - 0
app/src/main/java/com/edufound/mobile/base/BasePersenter.java

@@ -0,0 +1,9 @@
+package com.edufound.mobile.base;
+
+public interface BasePersenter {
+    void loadData();
+
+    void onDisConnNetWork();
+
+    void onConnNetWork();
+}

+ 15 - 0
app/src/main/java/com/edufound/mobile/base/BaseView.java

@@ -0,0 +1,15 @@
+package com.edufound.mobile.base;
+
+import android.app.Activity;
+
+public interface BaseView {
+
+    void showData(String text);
+
+    void DisconnNetWork();
+
+    void ConnNeWork();
+
+    Activity getActivity();
+
+}

+ 14 - 0
app/src/main/java/com/edufound/mobile/bean/FunPayDataBean.java

@@ -0,0 +1,14 @@
+package com.edufound.mobile.bean;
+
+public class FunPayDataBean {
+    public String accountName;
+    public String appOrderCode;
+    public String orderType;
+    public String payMoney;
+    public String commodityName;
+    public String commodityId;
+    public int commodityCount;
+    public String serverId;
+    public String serverName;
+
+}

+ 128 - 0
app/src/main/java/com/edufound/mobile/bean/NotificationBean.java

@@ -0,0 +1,128 @@
+package com.edufound.mobile.bean;
+
+public class NotificationBean {
+    private String display_type;
+    private String msg_id;
+    private String random_min;
+    private ExtraBean extra;
+    private BodyBean body;
+
+    public String getDisplay_type() {
+        return display_type;
+    }
+
+    public void setDisplay_type(String display_type) {
+        this.display_type = display_type;
+    }
+
+    public String getMsg_id() {
+        return msg_id;
+    }
+
+    public void setMsg_id(String msg_id) {
+        this.msg_id = msg_id;
+    }
+
+    public String getRandom_min() {
+        return random_min;
+    }
+
+    public void setRandom_min(String random_min) {
+        this.random_min = random_min;
+    }
+
+    public ExtraBean getExtra() {
+        return extra;
+    }
+
+    public void setExtra(ExtraBean extra) {
+        this.extra = extra;
+    }
+
+    public BodyBean getBody() {
+        return body;
+    }
+
+    public void setBody(BodyBean body) {
+        this.body = body;
+    }
+
+    public class ExtraBean {
+        private String url;
+
+        public String getUrl() {
+            return url;
+        }
+
+        public void setUrl(String url) {
+            this.url = url;
+        }
+    }
+
+    public class BodyBean {
+        private String after_open;
+        private String play_lights;
+        private String ticker;
+        private String play_vibrate;
+
+        public String getAfter_open() {
+            return after_open;
+        }
+
+        public void setAfter_open(String after_open) {
+            this.after_open = after_open;
+        }
+
+        public String getPlay_lights() {
+            return play_lights;
+        }
+
+        public void setPlay_lights(String play_lights) {
+            this.play_lights = play_lights;
+        }
+
+        public String getTicker() {
+            return ticker;
+        }
+
+        public void setTicker(String ticker) {
+            this.ticker = ticker;
+        }
+
+        public String getPlay_vibrate() {
+            return play_vibrate;
+        }
+
+        public void setPlay_vibrate(String play_vibrate) {
+            this.play_vibrate = play_vibrate;
+        }
+
+        public String getText() {
+            return text;
+        }
+
+        public void setText(String text) {
+            this.text = text;
+        }
+
+        public String getTitle() {
+            return title;
+        }
+
+        public void setTitle(String title) {
+            this.title = title;
+        }
+
+        public String getPlay_sound() {
+            return play_sound;
+        }
+
+        public void setPlay_sound(String play_sound) {
+            this.play_sound = play_sound;
+        }
+
+        private String text;
+        private String title;
+        private String play_sound;
+    }
+}

+ 8 - 0
app/src/main/java/com/edufound/mobile/bean/UpgradeBean.java

@@ -0,0 +1,8 @@
+package com.edufound.mobile.bean;
+
+public class UpgradeBean {
+    public String title;
+    public String type;
+    public String context;
+    public String download_url;
+}

+ 103 - 0
app/src/main/java/com/edufound/mobile/ijkplayer/application/Settings.java

@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2015 Bilibili
+ * Copyright (C) 2015 Zhang Rui <bbcallen@gmail.com>
+ *
+ * Licensed 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.edufound.mobile.ijkplayer.application;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.preference.PreferenceManager;
+
+import com.edufound.mobile.R;
+
+public class Settings {
+    private Context mAppContext;
+    private SharedPreferences mSharedPreferences;
+
+    public static final int PV_PLAYER__AndroidMediaPlayer = 1;
+    public static final int PV_PLAYER__IjkMediaPlayer = 2;
+    public static final int PV_PLAYER__IjkExoMediaPlayer = 3;
+
+    public Settings(Context context) {
+        mAppContext = context.getApplicationContext();
+        mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(mAppContext);
+    }
+
+    public boolean getEnableBackgroundPlay() {
+        String key = mAppContext.getString(R.string.pref_key_enable_background_play);
+        return mSharedPreferences.getBoolean(key, false);
+    }
+
+    public int getPlayer() {
+        String key = mAppContext.getString(R.string.pref_key_player);
+        String value = mSharedPreferences.getString(key, "");
+        try {
+            return Integer.valueOf(value).intValue();
+        } catch (NumberFormatException e) {
+            return 0;
+        }
+    }
+
+    public boolean getUsingMediaCodec() {
+        String key = mAppContext.getString(R.string.pref_key_using_media_codec);
+        return mSharedPreferences.getBoolean(key, false);
+    }
+
+    public boolean getUsingMediaCodecAutoRotate() {
+        String key = mAppContext.getString(R.string.pref_key_using_media_codec_auto_rotate);
+        return mSharedPreferences.getBoolean(key, false);
+    }
+
+    public boolean getMediaCodecHandleResolutionChange() {
+        String key = mAppContext.getString(R.string.pref_key_media_codec_handle_resolution_change);
+        return mSharedPreferences.getBoolean(key, false);
+    }
+
+    public boolean getUsingOpenSLES() {
+        String key = mAppContext.getString(R.string.pref_key_using_opensl_es);
+        return mSharedPreferences.getBoolean(key, false);
+    }
+
+    public String getPixelFormat() {
+        String key = mAppContext.getString(R.string.pref_key_pixel_format);
+        return mSharedPreferences.getString(key, "");
+    }
+
+    public boolean getEnableNoView() {
+        String key = mAppContext.getString(R.string.pref_key_enable_no_view);
+        return mSharedPreferences.getBoolean(key, false);
+    }
+
+    public boolean getEnableSurfaceView() {
+        String key = mAppContext.getString(R.string.pref_key_enable_surface_view);
+        return mSharedPreferences.getBoolean(key, false);
+    }
+
+    public boolean getEnableTextureView() {
+        String key = mAppContext.getString(R.string.pref_key_enable_texture_view);
+        return mSharedPreferences.getBoolean(key, false);
+    }
+
+    public boolean getEnableDetachedSurfaceTextureView() {
+        String key = mAppContext.getString(R.string.pref_key_enable_detached_surface_texture);
+        return mSharedPreferences.getBoolean(key, false);
+    }
+
+    public boolean getUsingMediaDataSource() {
+        String key = mAppContext.getString(R.string.pref_key_using_mediadatasource);
+        return mSharedPreferences.getBoolean(key, false);
+    }
+}

+ 57 - 0
app/src/main/java/com/edufound/mobile/ijkplayer/media/FileMediaDataSource.java

@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2015 Bilibili
+ * Copyright (C) 2015 Zhang Rui <bbcallen@gmail.com>
+ *
+ * Licensed 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.edufound.mobile.ijkplayer.media;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+
+import tv.danmaku.ijk.media.player.misc.IMediaDataSource;
+
+public class FileMediaDataSource implements IMediaDataSource {
+    private RandomAccessFile mFile;
+    private long mFileSize;
+
+    public FileMediaDataSource(File file) throws IOException {
+        mFile = new RandomAccessFile(file, "r");
+        mFileSize = mFile.length();
+    }
+
+    @Override
+    public int readAt(long position, byte[] buffer, int offset, int size) throws IOException {
+        if (mFile.getFilePointer() != position)
+            mFile.seek(position);
+
+        if (size == 0)
+            return 0;
+
+        return mFile.read(buffer, 0, size);
+    }
+
+    @Override
+    public long getSize() throws IOException {
+        return mFileSize;
+    }
+
+    @Override
+    public void close() throws IOException {
+        mFileSize = 0;
+        mFile.close();
+        mFile = null;
+    }
+}

+ 42 - 0
app/src/main/java/com/edufound/mobile/ijkplayer/media/IMediaController.java

@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2015 Bilibili
+ * Copyright (C) 2015 Zhang Rui <bbcallen@gmail.com>
+ *
+ * Licensed 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.edufound.mobile.ijkplayer.media;
+
+import android.view.View;
+import android.widget.MediaController;
+
+public interface IMediaController {
+    void hide();
+
+    boolean isShowing();
+
+    void setAnchorView(View view);
+
+    void setEnabled(boolean enabled);
+
+    void setMediaPlayer(MediaController.MediaPlayerControl player);
+
+    void show(int timeout);
+
+    void show();
+
+    //----------
+    // Extends
+    //----------
+    void showOnce(View view);
+}

+ 87 - 0
app/src/main/java/com/edufound/mobile/ijkplayer/media/IRenderView.java

@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2015 Bilibili
+ * Copyright (C) 2015 Zhang Rui <bbcallen@gmail.com>
+ *
+ * Licensed 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.edufound.mobile.ijkplayer.media;
+
+import android.graphics.SurfaceTexture;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+import android.view.View;
+
+import tv.danmaku.ijk.media.player.IMediaPlayer;
+
+public interface IRenderView {
+    int AR_ASPECT_FIT_PARENT = 0; // without clip
+    int AR_ASPECT_FILL_PARENT = 1; // may clip
+    int AR_ASPECT_WRAP_CONTENT = 2;
+    int AR_MATCH_PARENT = 3;
+    int AR_16_9_FIT_PARENT = 4;
+    int AR_4_3_FIT_PARENT = 5;
+
+    View getView();
+
+    boolean shouldWaitForResize();
+
+    void setVideoSize(int videoWidth, int videoHeight);
+
+    void setVideoSampleAspectRatio(int videoSarNum, int videoSarDen);
+
+    void setVideoRotation(int degree);
+
+    void setAspectRatio(int aspectRatio);
+
+    void addRenderCallback(@NonNull IRenderCallback callback);
+
+    void removeRenderCallback(@NonNull IRenderCallback callback);
+
+    interface ISurfaceHolder {
+        void bindToMediaPlayer(IMediaPlayer mp);
+
+        @NonNull
+        IRenderView getRenderView();
+
+        @Nullable
+        SurfaceHolder getSurfaceHolder();
+
+        @Nullable
+        Surface openSurface();
+
+        @Nullable
+        SurfaceTexture getSurfaceTexture();
+    }
+
+    interface IRenderCallback {
+        /**
+         * @param holder
+         * @param width  could be 0
+         * @param height could be 0
+         */
+        void onSurfaceCreated(@NonNull ISurfaceHolder holder, int width, int height);
+
+        /**
+         * @param holder
+         * @param format could be 0
+         * @param width
+         * @param height
+         */
+        void onSurfaceChanged(@NonNull ISurfaceHolder holder, int format, int width, int height);
+
+        void onSurfaceDestroyed(@NonNull ISurfaceHolder holder);
+    }
+}

File diff suppressed because it is too large
+ 1149 - 0
app/src/main/java/com/edufound/mobile/ijkplayer/media/IjkVideoView.java


+ 215 - 0
app/src/main/java/com/edufound/mobile/ijkplayer/media/MeasureHelper.java

@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2015 Bilibili
+ * Copyright (C) 2015 Zhang Rui <bbcallen@gmail.com>
+ *
+ * Licensed 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.edufound.mobile.ijkplayer.media;
+
+import android.view.View;
+
+import java.lang.ref.WeakReference;
+
+public final class MeasureHelper {
+    private WeakReference<View> mWeakView;
+
+    private int mVideoWidth;
+    private int mVideoHeight;
+    private int mVideoSarNum;
+    private int mVideoSarDen;
+
+    private int mVideoRotationDegree;
+
+    private int mMeasuredWidth;
+    private int mMeasuredHeight;
+
+    private int mCurrentAspectRatio = IRenderView.AR_ASPECT_FIT_PARENT;
+
+    public MeasureHelper(View view) {
+        mWeakView = new WeakReference<View>(view);
+    }
+
+    public View getView() {
+        if (mWeakView == null)
+            return null;
+        return mWeakView.get();
+    }
+
+    public void setVideoSize(int videoWidth, int videoHeight) {
+        mVideoWidth = videoWidth;
+        mVideoHeight = videoHeight;
+    }
+
+    public void setVideoSampleAspectRatio(int videoSarNum, int videoSarDen) {
+        mVideoSarNum = videoSarNum;
+        mVideoSarDen = videoSarDen;
+    }
+
+    public void setVideoRotation(int videoRotationDegree) {
+        mVideoRotationDegree = videoRotationDegree;
+    }
+
+    /**
+     * Must be called by View.onMeasure(int, int)
+     *
+     * @param widthMeasureSpec
+     * @param heightMeasureSpec
+     */
+    public void doMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        //Log.i("@@@@", "onMeasure(" + MeasureSpec.toString(widthMeasureSpec) + ", "
+        //        + MeasureSpec.toString(heightMeasureSpec) + ")");
+        if (mVideoRotationDegree == 90 || mVideoRotationDegree == 270) {
+            int tempSpec = widthMeasureSpec;
+            widthMeasureSpec  = heightMeasureSpec;
+            heightMeasureSpec = tempSpec;
+        }
+
+        int width = View.getDefaultSize(mVideoWidth, widthMeasureSpec);
+        int height = View.getDefaultSize(mVideoHeight, heightMeasureSpec);
+        if (mCurrentAspectRatio == IRenderView.AR_MATCH_PARENT) {
+            width = widthMeasureSpec;
+            height = heightMeasureSpec;
+        } else if (mVideoWidth > 0 && mVideoHeight > 0) {
+            int widthSpecMode = View.MeasureSpec.getMode(widthMeasureSpec);
+            int widthSpecSize = View.MeasureSpec.getSize(widthMeasureSpec);
+            int heightSpecMode = View.MeasureSpec.getMode(heightMeasureSpec);
+            int heightSpecSize = View.MeasureSpec.getSize(heightMeasureSpec);
+
+            if (widthSpecMode == View.MeasureSpec.AT_MOST && heightSpecMode == View.MeasureSpec.AT_MOST) {
+                float specAspectRatio = (float) widthSpecSize / (float) heightSpecSize;
+                float displayAspectRatio;
+                switch (mCurrentAspectRatio) {
+                    case IRenderView.AR_16_9_FIT_PARENT:
+                        displayAspectRatio = 16.0f / 9.0f;
+                        if (mVideoRotationDegree == 90 || mVideoRotationDegree == 270)
+                            displayAspectRatio = 1.0f / displayAspectRatio;
+                        break;
+                    case IRenderView.AR_4_3_FIT_PARENT:
+                        displayAspectRatio = 4.0f / 3.0f;
+                        if (mVideoRotationDegree == 90 || mVideoRotationDegree == 270)
+                            displayAspectRatio = 1.0f / displayAspectRatio;
+                        break;
+                    case IRenderView.AR_ASPECT_FIT_PARENT:
+                    case IRenderView.AR_ASPECT_FILL_PARENT:
+                    case IRenderView.AR_ASPECT_WRAP_CONTENT:
+                    default:
+                        displayAspectRatio = (float) mVideoWidth / (float) mVideoHeight;
+                        if (mVideoSarNum > 0 && mVideoSarDen > 0)
+                            displayAspectRatio = displayAspectRatio * mVideoSarNum / mVideoSarDen;
+                        break;
+                }
+                boolean shouldBeWider = displayAspectRatio > specAspectRatio;
+
+                switch (mCurrentAspectRatio) {
+                    case IRenderView.AR_ASPECT_FIT_PARENT:
+                    case IRenderView.AR_16_9_FIT_PARENT:
+                    case IRenderView.AR_4_3_FIT_PARENT:
+                        if (shouldBeWider) {
+                            // too wide, fix width
+                            width = widthSpecSize;
+                            height = (int) (width / displayAspectRatio);
+                        } else {
+                            // too high, fix height
+                            height = heightSpecSize;
+                            width = (int) (height * displayAspectRatio);
+                        }
+                        break;
+                    case IRenderView.AR_ASPECT_FILL_PARENT:
+                        if (shouldBeWider) {
+                            // not high enough, fix height
+                            height = heightSpecSize;
+                            width = (int) (height * displayAspectRatio);
+                        } else {
+                            // not wide enough, fix width
+                            width = widthSpecSize;
+                            height = (int) (width / displayAspectRatio);
+                        }
+                        break;
+                    case IRenderView.AR_ASPECT_WRAP_CONTENT:
+                    default:
+                        if (shouldBeWider) {
+                            // too wide, fix width
+                            width = Math.min(mVideoWidth, widthSpecSize);
+                            height = (int) (width / displayAspectRatio);
+                        } else {
+                            // too high, fix height
+                            height = Math.min(mVideoHeight, heightSpecSize);
+                            width = (int) (height * displayAspectRatio);
+                        }
+                        break;
+                }
+            } else if (widthSpecMode == View.MeasureSpec.EXACTLY && heightSpecMode == View.MeasureSpec.EXACTLY) {
+                // the size is fixed
+                width = widthSpecSize;
+                height = heightSpecSize;
+
+                // for compatibility, we adjust size based on aspect ratio
+                if (mVideoWidth * height < width * mVideoHeight) {
+                    //Log.i("@@@", "image too wide, correcting");
+                    width = height * mVideoWidth / mVideoHeight;
+                } else if (mVideoWidth * height > width * mVideoHeight) {
+                    //Log.i("@@@", "image too tall, correcting");
+                    height = width * mVideoHeight / mVideoWidth;
+                }
+            } else if (widthSpecMode == View.MeasureSpec.EXACTLY) {
+                // only the width is fixed, adjust the height to match aspect ratio if possible
+                width = widthSpecSize;
+                height = width * mVideoHeight / mVideoWidth;
+                if (heightSpecMode == View.MeasureSpec.AT_MOST && height > heightSpecSize) {
+                    // couldn't match aspect ratio within the constraints
+                    height = heightSpecSize;
+                }
+            } else if (heightSpecMode == View.MeasureSpec.EXACTLY) {
+                // only the height is fixed, adjust the width to match aspect ratio if possible
+                height = heightSpecSize;
+                width = height * mVideoWidth / mVideoHeight;
+                if (widthSpecMode == View.MeasureSpec.AT_MOST && width > widthSpecSize) {
+                    // couldn't match aspect ratio within the constraints
+                    width = widthSpecSize;
+                }
+            } else {
+                // neither the width nor the height are fixed, try to use actual video size
+                width = mVideoWidth;
+                height = mVideoHeight;
+                if (heightSpecMode == View.MeasureSpec.AT_MOST && height > heightSpecSize) {
+                    // too tall, decrease both width and height
+                    height = heightSpecSize;
+                    width = height * mVideoWidth / mVideoHeight;
+                }
+                if (widthSpecMode == View.MeasureSpec.AT_MOST && width > widthSpecSize) {
+                    // too wide, decrease both width and height
+                    width = widthSpecSize;
+                    height = width * mVideoHeight / mVideoWidth;
+                }
+            }
+        } else {
+            // no size yet, just adopt the given spec sizes
+        }
+
+        mMeasuredWidth = width;
+        mMeasuredHeight = height;
+    }
+
+    public int getMeasuredWidth() {
+        return mMeasuredWidth;
+    }
+
+    public int getMeasuredHeight() {
+        return mMeasuredHeight;
+    }
+
+    public void setAspectRatio(int aspectRatio) {
+        mCurrentAspectRatio = aspectRatio;
+    }
+}

+ 288 - 0
app/src/main/java/com/edufound/mobile/ijkplayer/media/SurfaceRenderView.java

@@ -0,0 +1,288 @@
+/*
+ * Copyright (C) 2015 Bilibili
+ * Copyright (C) 2015 Zhang Rui <bbcallen@gmail.com>
+ *
+ * Licensed 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.edufound.mobile.ijkplayer.media;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.graphics.SurfaceTexture;
+import android.os.Build;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
+
+import java.lang.ref.WeakReference;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import tv.danmaku.ijk.media.player.IMediaPlayer;
+import tv.danmaku.ijk.media.player.ISurfaceTextureHolder;
+
+public class SurfaceRenderView extends SurfaceView implements IRenderView {
+    private MeasureHelper mMeasureHelper;
+
+    public SurfaceRenderView(Context context) {
+        super(context);
+        initView(context);
+    }
+
+    public SurfaceRenderView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        initView(context);
+    }
+
+    public SurfaceRenderView(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        initView(context);
+    }
+
+    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+    public SurfaceRenderView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+        initView(context);
+    }
+
+    private void initView(Context context) {
+        mMeasureHelper = new MeasureHelper(this);
+        mSurfaceCallback = new SurfaceCallback(this);
+        getHolder().addCallback(mSurfaceCallback);
+        //noinspection deprecation
+        getHolder().setType(SurfaceHolder.SURFACE_TYPE_NORMAL);
+    }
+
+    @Override
+    public View getView() {
+        return this;
+    }
+
+    @Override
+    public boolean shouldWaitForResize() {
+        return true;
+    }
+
+    //--------------------
+    // Layout & Measure
+    //--------------------
+    @Override
+    public void setVideoSize(int videoWidth, int videoHeight) {
+        if (videoWidth > 0 && videoHeight > 0) {
+            mMeasureHelper.setVideoSize(videoWidth, videoHeight);
+            getHolder().setFixedSize(videoWidth, videoHeight);
+            requestLayout();
+        }
+    }
+
+    @Override
+    public void setVideoSampleAspectRatio(int videoSarNum, int videoSarDen) {
+        if (videoSarNum > 0 && videoSarDen > 0) {
+            mMeasureHelper.setVideoSampleAspectRatio(videoSarNum, videoSarDen);
+            requestLayout();
+        }
+    }
+
+    @Override
+    public void setVideoRotation(int degree) {
+        Log.e("", "SurfaceView doesn't support rotation (" + degree + ")!\n");
+    }
+
+    @Override
+    public void setAspectRatio(int aspectRatio) {
+        mMeasureHelper.setAspectRatio(aspectRatio);
+        requestLayout();
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        mMeasureHelper.doMeasure(widthMeasureSpec, heightMeasureSpec);
+        setMeasuredDimension(mMeasureHelper.getMeasuredWidth(), mMeasureHelper.getMeasuredHeight());
+    }
+
+    //--------------------
+    // SurfaceViewHolder
+    //--------------------
+
+    private static final class InternalSurfaceHolder implements ISurfaceHolder {
+        private SurfaceRenderView mSurfaceView;
+        private SurfaceHolder mSurfaceHolder;
+
+        public InternalSurfaceHolder(@NonNull SurfaceRenderView surfaceView,
+                                     @Nullable SurfaceHolder surfaceHolder) {
+            mSurfaceView = surfaceView;
+            mSurfaceHolder = surfaceHolder;
+        }
+
+        public void bindToMediaPlayer(IMediaPlayer mp) {
+            if (mp != null) {
+                if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) &&
+                        (mp instanceof ISurfaceTextureHolder)) {
+                    ISurfaceTextureHolder textureHolder = (ISurfaceTextureHolder) mp;
+                    textureHolder.setSurfaceTexture(null);
+                }
+                mp.setDisplay(mSurfaceHolder);
+            }
+        }
+
+        @NonNull
+        @Override
+        public IRenderView getRenderView() {
+            return mSurfaceView;
+        }
+
+        @Nullable
+        @Override
+        public SurfaceHolder getSurfaceHolder() {
+            return mSurfaceHolder;
+        }
+
+        @Nullable
+        @Override
+        public SurfaceTexture getSurfaceTexture() {
+            return null;
+        }
+
+        @Nullable
+        @Override
+        public Surface openSurface() {
+            if (mSurfaceHolder == null)
+                return null;
+            return mSurfaceHolder.getSurface();
+        }
+    }
+
+    //-------------------------
+    // SurfaceHolder.Callback
+    //-------------------------
+
+    @Override
+    public void addRenderCallback(IRenderCallback callback) {
+        mSurfaceCallback.addRenderCallback(callback);
+    }
+
+    @Override
+    public void removeRenderCallback(IRenderCallback callback) {
+        mSurfaceCallback.removeRenderCallback(callback);
+    }
+
+    private SurfaceCallback mSurfaceCallback;
+
+    private static final class SurfaceCallback implements SurfaceHolder.Callback {
+        private SurfaceHolder mSurfaceHolder;
+        private boolean mIsFormatChanged;
+        private int mFormat;
+        private int mWidth;
+        private int mHeight;
+
+        private WeakReference<SurfaceRenderView> mWeakSurfaceView;
+        private Map<IRenderCallback, Object> mRenderCallbackMap = new ConcurrentHashMap<IRenderCallback, Object>();
+
+        public SurfaceCallback(@NonNull SurfaceRenderView surfaceView) {
+            mWeakSurfaceView = new WeakReference<SurfaceRenderView>(surfaceView);
+        }
+
+        public void addRenderCallback(@NonNull IRenderCallback callback) {
+            mRenderCallbackMap.put(callback, callback);
+
+            ISurfaceHolder surfaceHolder = null;
+            if (mSurfaceHolder != null) {
+                if (surfaceHolder == null)
+                    surfaceHolder = new InternalSurfaceHolder(mWeakSurfaceView.get(), mSurfaceHolder);
+                callback.onSurfaceCreated(surfaceHolder, mWidth, mHeight);
+            }
+
+            if (mIsFormatChanged) {
+                if (surfaceHolder == null)
+                    surfaceHolder = new InternalSurfaceHolder(mWeakSurfaceView.get(), mSurfaceHolder);
+                callback.onSurfaceChanged(surfaceHolder, mFormat, mWidth, mHeight);
+            }
+        }
+
+        public void removeRenderCallback(@NonNull IRenderCallback callback) {
+            mRenderCallbackMap.remove(callback);
+        }
+
+        @Override
+        public void surfaceCreated(SurfaceHolder holder) {
+            mSurfaceHolder = holder;
+            mIsFormatChanged = false;
+            mFormat = 0;
+            mWidth = 0;
+            mHeight = 0;
+
+            ISurfaceHolder surfaceHolder = new InternalSurfaceHolder(mWeakSurfaceView.get(), mSurfaceHolder);
+            for (IRenderCallback renderCallback : mRenderCallbackMap.keySet()) {
+                renderCallback.onSurfaceCreated(surfaceHolder, 0, 0);
+            }
+        }
+
+        @Override
+        public void surfaceDestroyed(SurfaceHolder holder) {
+            mSurfaceHolder = null;
+            mIsFormatChanged = false;
+            mFormat = 0;
+            mWidth = 0;
+            mHeight = 0;
+
+            ISurfaceHolder surfaceHolder = new InternalSurfaceHolder(mWeakSurfaceView.get(), mSurfaceHolder);
+            for (IRenderCallback renderCallback : mRenderCallbackMap.keySet()) {
+                renderCallback.onSurfaceDestroyed(surfaceHolder);
+            }
+        }
+
+        @Override
+        public void surfaceChanged(SurfaceHolder holder, int format,
+                                   int width, int height) {
+            mSurfaceHolder = holder;
+            mIsFormatChanged = true;
+            mFormat = format;
+            mWidth = width;
+            mHeight = height;
+
+            // mMeasureHelper.setVideoSize(width, height);
+
+            ISurfaceHolder surfaceHolder = new InternalSurfaceHolder(mWeakSurfaceView.get(), mSurfaceHolder);
+            for (IRenderCallback renderCallback : mRenderCallbackMap.keySet()) {
+                renderCallback.onSurfaceChanged(surfaceHolder, format, width, height);
+            }
+        }
+    }
+
+    //--------------------
+    // Accessibility
+    //--------------------
+
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(SurfaceRenderView.class.getName());
+    }
+
+    @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
+            info.setClassName(SurfaceRenderView.class.getName());
+        }
+    }
+}

+ 370 - 0
app/src/main/java/com/edufound/mobile/ijkplayer/media/TextureRenderView.java

@@ -0,0 +1,370 @@
+/*
+ * Copyright (C) 2015 Bilibili
+ * Copyright (C) 2015 Zhang Rui <bbcallen@gmail.com>
+ *
+ * Licensed 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.edufound.mobile.ijkplayer.media;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.graphics.SurfaceTexture;
+import android.os.Build;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+import android.view.TextureView;
+import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
+
+import java.lang.ref.WeakReference;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import tv.danmaku.ijk.media.player.IMediaPlayer;
+import tv.danmaku.ijk.media.player.ISurfaceTextureHolder;
+import tv.danmaku.ijk.media.player.ISurfaceTextureHost;
+
+@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
+public class TextureRenderView extends TextureView implements IRenderView {
+    private static final String TAG = "TextureRenderView";
+    private MeasureHelper mMeasureHelper;
+
+    public TextureRenderView(Context context) {
+        super(context);
+        initView(context);
+    }
+
+    public TextureRenderView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        initView(context);
+    }
+
+    public TextureRenderView(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        initView(context);
+    }
+
+    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+    public TextureRenderView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+        initView(context);
+    }
+
+    private void initView(Context context) {
+        mMeasureHelper = new MeasureHelper(this);
+        mSurfaceCallback = new SurfaceCallback(this);
+        setSurfaceTextureListener(mSurfaceCallback);
+    }
+
+    @Override
+    public View getView() {
+        return this;
+    }
+
+    @Override
+    public boolean shouldWaitForResize() {
+        return false;
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        mSurfaceCallback.willDetachFromWindow();
+        super.onDetachedFromWindow();
+        mSurfaceCallback.didDetachFromWindow();
+    }
+
+    //--------------------
+    // Layout & Measure
+    //--------------------
+    @Override
+    public void setVideoSize(int videoWidth, int videoHeight) {
+        if (videoWidth > 0 && videoHeight > 0) {
+            mMeasureHelper.setVideoSize(videoWidth, videoHeight);
+            requestLayout();
+        }
+    }
+
+    @Override
+    public void setVideoSampleAspectRatio(int videoSarNum, int videoSarDen) {
+        if (videoSarNum > 0 && videoSarDen > 0) {
+            mMeasureHelper.setVideoSampleAspectRatio(videoSarNum, videoSarDen);
+            requestLayout();
+        }
+    }
+
+    @Override
+    public void setVideoRotation(int degree) {
+        mMeasureHelper.setVideoRotation(degree);
+        setRotation(degree);
+    }
+
+    @Override
+    public void setAspectRatio(int aspectRatio) {
+        mMeasureHelper.setAspectRatio(aspectRatio);
+        requestLayout();
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        mMeasureHelper.doMeasure(widthMeasureSpec, heightMeasureSpec);
+        setMeasuredDimension(mMeasureHelper.getMeasuredWidth(), mMeasureHelper.getMeasuredHeight());
+    }
+
+    //--------------------
+    // TextureViewHolder
+    //--------------------
+
+    public ISurfaceHolder getSurfaceHolder() {
+        return new InternalSurfaceHolder(this, mSurfaceCallback.mSurfaceTexture, mSurfaceCallback);
+    }
+
+    private static final class InternalSurfaceHolder implements ISurfaceHolder {
+        private TextureRenderView mTextureView;
+        private SurfaceTexture mSurfaceTexture;
+        private ISurfaceTextureHost mSurfaceTextureHost;
+
+        public InternalSurfaceHolder(@NonNull TextureRenderView textureView,
+                                     @Nullable SurfaceTexture surfaceTexture,
+                                     @NonNull ISurfaceTextureHost surfaceTextureHost) {
+            mTextureView = textureView;
+            mSurfaceTexture = surfaceTexture;
+            mSurfaceTextureHost = surfaceTextureHost;
+        }
+
+        @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
+        public void bindToMediaPlayer(IMediaPlayer mp) {
+            if (mp == null)
+                return;
+
+            if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) &&
+                    (mp instanceof ISurfaceTextureHolder)) {
+                ISurfaceTextureHolder textureHolder = (ISurfaceTextureHolder) mp;
+                mTextureView.mSurfaceCallback.setOwnSurfaceTexture(false);
+
+                SurfaceTexture surfaceTexture = textureHolder.getSurfaceTexture();
+                if (surfaceTexture != null) {
+                    mTextureView.setSurfaceTexture(surfaceTexture);
+                } else {
+                    textureHolder.setSurfaceTexture(mSurfaceTexture);
+                    textureHolder.setSurfaceTextureHost(mTextureView.mSurfaceCallback);
+                }
+            } else {
+                mp.setSurface(openSurface());
+            }
+        }
+
+        @NonNull
+        @Override
+        public IRenderView getRenderView() {
+            return mTextureView;
+        }
+
+        @Nullable
+        @Override
+        public SurfaceHolder getSurfaceHolder() {
+            return null;
+        }
+
+        @Nullable
+        @Override
+        public SurfaceTexture getSurfaceTexture() {
+            return mSurfaceTexture;
+        }
+
+        @Nullable
+        @Override
+        public Surface openSurface() {
+            if (mSurfaceTexture == null)
+                return null;
+            return new Surface(mSurfaceTexture);
+        }
+    }
+
+    //-------------------------
+    // SurfaceHolder.Callback
+    //-------------------------
+
+    @Override
+    public void addRenderCallback(IRenderCallback callback) {
+        mSurfaceCallback.addRenderCallback(callback);
+    }
+
+    @Override
+    public void removeRenderCallback(IRenderCallback callback) {
+        mSurfaceCallback.removeRenderCallback(callback);
+    }
+
+    private SurfaceCallback mSurfaceCallback;
+
+    private static final class SurfaceCallback implements SurfaceTextureListener, ISurfaceTextureHost {
+        private SurfaceTexture mSurfaceTexture;
+        private boolean mIsFormatChanged;
+        private int mWidth;
+        private int mHeight;
+
+        private boolean mOwnSurfaceTexture = true;
+        private boolean mWillDetachFromWindow = false;
+        private boolean mDidDetachFromWindow = false;
+
+        private WeakReference<TextureRenderView> mWeakRenderView;
+        private Map<IRenderCallback, Object> mRenderCallbackMap = new ConcurrentHashMap<IRenderCallback, Object>();
+
+        public SurfaceCallback(@NonNull TextureRenderView renderView) {
+            mWeakRenderView = new WeakReference<TextureRenderView>(renderView);
+        }
+
+        public void setOwnSurfaceTexture(boolean ownSurfaceTexture) {
+            mOwnSurfaceTexture = ownSurfaceTexture;
+        }
+
+        public void addRenderCallback(@NonNull IRenderCallback callback) {
+            mRenderCallbackMap.put(callback, callback);
+
+            ISurfaceHolder surfaceHolder = null;
+            if (mSurfaceTexture != null) {
+                if (surfaceHolder == null)
+                    surfaceHolder = new InternalSurfaceHolder(mWeakRenderView.get(), mSurfaceTexture, this);
+                callback.onSurfaceCreated(surfaceHolder, mWidth, mHeight);
+            }
+
+            if (mIsFormatChanged) {
+                if (surfaceHolder == null)
+                    surfaceHolder = new InternalSurfaceHolder(mWeakRenderView.get(), mSurfaceTexture, this);
+                callback.onSurfaceChanged(surfaceHolder, 0, mWidth, mHeight);
+            }
+        }
+
+        public void removeRenderCallback(@NonNull IRenderCallback callback) {
+            mRenderCallbackMap.remove(callback);
+        }
+
+        @Override
+        public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
+            mSurfaceTexture = surface;
+            mIsFormatChanged = false;
+            mWidth = 0;
+            mHeight = 0;
+
+            ISurfaceHolder surfaceHolder = new InternalSurfaceHolder(mWeakRenderView.get(), surface, this);
+            for (IRenderCallback renderCallback : mRenderCallbackMap.keySet()) {
+                renderCallback.onSurfaceCreated(surfaceHolder, 0, 0);
+            }
+        }
+
+        @Override
+        public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
+            mSurfaceTexture = surface;
+            mIsFormatChanged = true;
+            mWidth = width;
+            mHeight = height;
+
+            ISurfaceHolder surfaceHolder = new InternalSurfaceHolder(mWeakRenderView.get(), surface, this);
+            for (IRenderCallback renderCallback : mRenderCallbackMap.keySet()) {
+                renderCallback.onSurfaceChanged(surfaceHolder, 0, width, height);
+            }
+        }
+
+        @Override
+        public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
+            mSurfaceTexture = surface;
+            mIsFormatChanged = false;
+            mWidth = 0;
+            mHeight = 0;
+
+            ISurfaceHolder surfaceHolder = new InternalSurfaceHolder(mWeakRenderView.get(), surface, this);
+            for (IRenderCallback renderCallback : mRenderCallbackMap.keySet()) {
+                renderCallback.onSurfaceDestroyed(surfaceHolder);
+            }
+
+            Log.d(TAG, "onSurfaceTextureDestroyed: destroy: " + mOwnSurfaceTexture);
+            return mOwnSurfaceTexture;
+        }
+
+        @Override
+        public void onSurfaceTextureUpdated(SurfaceTexture surface) {
+        }
+
+        //-------------------------
+        // ISurfaceTextureHost
+        //-------------------------
+
+        @Override
+        public void releaseSurfaceTexture(SurfaceTexture surfaceTexture) {
+            if (surfaceTexture == null) {
+                Log.d(TAG, "releaseSurfaceTexture: null");
+            } else if (mDidDetachFromWindow) {
+                if (surfaceTexture != mSurfaceTexture) {
+                    Log.d(TAG, "releaseSurfaceTexture: didDetachFromWindow(): release different SurfaceTexture");
+                    surfaceTexture.release();
+                } else if (!mOwnSurfaceTexture) {
+                    Log.d(TAG, "releaseSurfaceTexture: didDetachFromWindow(): release detached SurfaceTexture");
+                    surfaceTexture.release();
+                } else {
+                    Log.d(TAG, "releaseSurfaceTexture: didDetachFromWindow(): already released by TextureView");
+                }
+            } else if (mWillDetachFromWindow) {
+                if (surfaceTexture != mSurfaceTexture) {
+                    Log.d(TAG, "releaseSurfaceTexture: willDetachFromWindow(): release different SurfaceTexture");
+                    surfaceTexture.release();
+                } else if (!mOwnSurfaceTexture) {
+                    Log.d(TAG, "releaseSurfaceTexture: willDetachFromWindow(): re-attach SurfaceTexture to TextureView");
+                    setOwnSurfaceTexture(true);
+                } else {
+                    Log.d(TAG, "releaseSurfaceTexture: willDetachFromWindow(): will released by TextureView");
+                }
+            } else {
+                if (surfaceTexture != mSurfaceTexture) {
+                    Log.d(TAG, "releaseSurfaceTexture: alive: release different SurfaceTexture");
+                    surfaceTexture.release();
+                } else if (!mOwnSurfaceTexture) {
+                    Log.d(TAG, "releaseSurfaceTexture: alive: re-attach SurfaceTexture to TextureView");
+                    setOwnSurfaceTexture(true);
+                } else {
+                    Log.d(TAG, "releaseSurfaceTexture: alive: will released by TextureView");
+                }
+            }
+        }
+
+        public void willDetachFromWindow() {
+            Log.d(TAG, "willDetachFromWindow()");
+            mWillDetachFromWindow = true;
+        }
+
+        public void didDetachFromWindow() {
+            Log.d(TAG, "didDetachFromWindow()");
+            mDidDetachFromWindow = true;
+        }
+    }
+
+    //--------------------
+    // Accessibility
+    //--------------------
+
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(TextureRenderView.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(TextureRenderView.class.getName());
+    }
+}

+ 63 - 0
app/src/main/java/com/edufound/mobile/ijkplayer/services/MediaPlayerService.java

@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2015 Bilibili
+ * Copyright (C) 2015 Zhang Rui <bbcallen@gmail.com>
+ *
+ * Licensed 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.edufound.mobile.ijkplayer.services;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.os.IBinder;
+import android.support.annotation.Nullable;
+
+import tv.danmaku.ijk.media.player.IMediaPlayer;
+
+public class MediaPlayerService extends Service {
+    private static IMediaPlayer sMediaPlayer;
+
+    public static Intent newIntent(Context context) {
+        Intent intent = new Intent(context, MediaPlayerService.class);
+        return intent;
+    }
+
+    public static void intentToStart(Context context) {
+        context.startService(newIntent(context));
+    }
+
+    public static void intentToStop(Context context) {
+        context.stopService(newIntent(context));
+    }
+
+    @Nullable
+    @Override
+    public IBinder onBind(Intent intent) {
+        return null;
+    }
+
+    public static void setMediaPlayer(IMediaPlayer mp) {
+        if (sMediaPlayer != null && sMediaPlayer != mp) {
+            if (sMediaPlayer.isPlaying())
+                sMediaPlayer.stop();
+            sMediaPlayer.release();
+            sMediaPlayer = null;
+        }
+        sMediaPlayer = mp;
+    }
+
+    public static IMediaPlayer getMediaPlayer() {
+        return sMediaPlayer;
+    }
+}

+ 42 - 0
app/src/main/java/com/edufound/mobile/interfaces/EfunboxPayInterfaces.java

@@ -0,0 +1,42 @@
+package com.edufound.mobile.interfaces;
+
+import android.content.Intent;
+import android.webkit.JavascriptInterface;
+
+import com.edufound.mobile.main.MainView;
+import com.edufound.mobile.pay.PayActivity;
+import com.edufound.mobile.pay.PayPersenter;
+import com.edufound.mobile.util.Logger;
+
+public class EfunboxPayInterfaces {
+    public static final int START_PAY_DB = 0x3211;
+    public static final int START_PAY_HUANWANG = 0x3212;
+    public static final int START_PAY_SKYWORTH = 0x3213;
+    public static final int START_PAY_XIAOMI = 0x3214;
+    public static final int PAY_SUCCESS = 0x00153ff5;
+    public static final int PAY_ERROR = 0x00153ff6;
+    public static final int PAY_CANCEL = 0x00153ff7;
+    public static final int PAY_BEGIN = 0x00153ff8;
+    private MainView mView;
+
+    public EfunboxPayInterfaces(MainView view) {
+        mView = view;
+    }
+
+    @JavascriptInterface
+    public void WeChatPay(String json) {
+        Intent intent = new Intent(mView.getActivity(), PayActivity.class);
+        intent.putExtra("type", "1");
+        intent.putExtra("payString", json);
+        mView.getActivity().startActivity(intent);
+    }
+
+    @JavascriptInterface
+    public void AliPay(String orderInfo) {
+        Intent intent = new Intent(mView.getActivity(), PayActivity.class);
+        intent.putExtra("type", "2");
+        intent.putExtra("payString", orderInfo);
+        mView.getActivity().startActivity(intent);
+    }
+
+}

+ 289 - 0
app/src/main/java/com/edufound/mobile/interfaces/JsInterfaces.java

@@ -0,0 +1,289 @@
+package com.edufound.mobile.interfaces;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.media.MediaPlayer;
+import android.view.KeyEvent;
+import android.webkit.JavascriptInterface;
+
+import com.edufound.mobile.R;
+import com.edufound.mobile.activity.IJKPlayerActivity;
+import com.edufound.mobile.activity.VideoActivity;
+import com.edufound.mobile.application.EApplication;
+import com.edufound.mobile.bean.UpgradeBean;
+import com.edufound.mobile.main.MainView;
+import com.edufound.mobile.pay.PayInit;
+import com.edufound.mobile.util.ContextUtil;
+import com.edufound.mobile.util.Logger;
+import com.edufound.mobile.util.SPutil;
+import com.edufound.mobile.util.ShowDebugUrl;
+import com.edufound.mobile.util.ShowDevice;
+import com.edufound.mobile.util.ShowSetting;
+import com.edufound.mobile.util.ToastUtil;
+import com.edufound.mobile.util.UpdateUtil;
+import com.google.gson.Gson;
+import com.tencent.mm.opensdk.modelbiz.WXLaunchMiniProgram;
+import com.tencent.mm.opensdk.modelmsg.SendAuth;
+
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.security.interfaces.ECKey;
+import java.util.HashMap;
+import java.util.Map;
+
+public class JsInterfaces {
+
+    Gson mGson;
+    MainView mView;
+    MediaPlayer mediaPlayer;
+
+    public JsInterfaces(MainView view) {
+        mGson = new Gson();
+        mView = view;
+        if (mediaPlayer == null) {
+            mediaPlayer = new MediaPlayer();
+            mediaPlayer.reset();
+            mediaPlayer = MediaPlayer.create(mView.getActivity(), R.raw.click_music);
+        }
+    }
+
+    Map<String, String> jsMap = new HashMap<>();
+
+    /*
+     * 关闭应用方法
+     * */
+    @JavascriptInterface
+    public void closeApp() {
+        EApplication.clearActivity();
+    }
+
+    /*
+     * 根据key设置SP参数方法
+     * */
+    @JavascriptInterface
+    public void setPreData(String key, String json_data) {
+        SPutil.setPrefString(ContextUtil.getContext(), key, json_data);
+    }
+
+
+    /*
+     * 根据key获取SP参数方法
+     * */
+    @JavascriptInterface
+    public String getPreData(String key) {
+        return SPutil.getPrefString(ContextUtil.getContext(), key, "");
+    }
+
+    /*
+     * 根据key删除SP参数
+     * */
+    @JavascriptInterface
+    public void delPreData(String key) {
+        SPutil.clearRecourds(ContextUtil.getContext(), key);
+    }
+
+
+    /*
+     * 设置map参数方法
+     * */
+    @JavascriptInterface
+    public void setStorageByKey(String key, String data) {
+        jsMap.put(key, data);
+    }
+
+    /*
+     * 获取map里参数
+     *
+     * */
+    @JavascriptInterface
+    public String getStorageByKey(String key) {
+        return jsMap.get(key).toString();
+    }
+
+    /*
+     * 清空map
+     * */
+    @JavascriptInterface
+    public void clearStorage() {
+        jsMap.clear();
+    }
+
+    /*
+     * 播放视频方法
+     * */
+    @JavascriptInterface
+    public void playVideo(String play_jsons, int play_index, int play_type, String moduleType) {
+        //可能要改播放器的逻辑
+        Logger.e("play_jsons:" + play_jsons);
+        Logger.e("play_index:" + play_index);
+        Logger.e("play_type:" + play_type);
+        Logger.e("moduleType:" + moduleType);
+        Intent intent = new Intent();
+        int selectid = SPutil.getPrefInt(mView.getActivity(), SPutil.videoType, 0);
+        switch (selectid) {
+            case SPutil.VIDEO_VIDEOVIEW:
+                intent.setClass(mView.getActivity(), VideoActivity.class);
+                break;
+            case SPutil.VIDEO_IJKPLAYER:
+                intent.setClass(mView.getActivity(), IJKPlayerActivity.class);
+                break;
+            default:
+                intent.setClass(mView.getActivity(), IJKPlayerActivity.class);
+                break;
+        }
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        intent.putExtra("play_jsons", play_jsons);
+        intent.putExtra("play_index", play_index);
+        intent.putExtra("play_type", play_type);
+        intent.putExtra("play_moduletype", moduleType);
+        mView.getActivity().startActivity(intent);
+    }
+
+    //JS调用方法,设置播放器
+    @JavascriptInterface
+    public void setPlayType(int type) {
+//        ToastUtil.showToast("setPlayType:" + type);
+        int toType = 0;
+        switch (type) {
+            case 2:
+//                ToastUtil.showToast("已选择默认播放器");
+                toType = SPutil.VIDEO_VIDEOVIEW;
+                break;
+            case 1:
+                toType = SPutil.VIDEO_IJKPLAYER;
+//                ToastUtil.showToast("已选择IJKPlayer播放器");
+                break;
+        }
+        SPutil.setPrefInt(ContextUtil.getContext(), SPutil.videoType, toType);
+    }
+
+    //JS调用方法,获取system系统参数
+    @JavascriptInterface
+    public String getProperty(String key, String defaultValue) {
+        String value = defaultValue;
+        try {
+            Class<?> c = Class.forName("android.os.SystemProperties");
+            Method get = c.getMethod("get", String.class, String.class);
+            value = (String) (get.invoke(c, key, "unknown"));
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            return value;
+        }
+    }
+
+
+    /*
+     * 自升级方法
+     * */
+    @JavascriptInterface
+    public void upgradeApp(String infoJson) {
+        // 测试json {'title': '升级','type': '1','context': '修正登录异常','download_url':
+        // 'http://www.baidu.com'}
+        Logger.DebugE("升级提示框:" + infoJson);
+        final UpgradeBean entity = mGson.fromJson(infoJson, UpgradeBean.class);
+        AlertDialog.Builder builder = new AlertDialog.Builder(mView.getActivity());
+        builder.setTitle(entity.title);
+        builder.setMessage(entity.context);
+        // 判断type,如果是,1、可选升级;2、强制升级
+        if (Integer.valueOf(entity.type) == 1) {
+            builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
+
+                @Override
+                public void onClick(DialogInterface dialog, int which) {
+                    // TODO Auto-generated method stub
+                    dialog.dismiss();
+                }
+            });
+        }
+        builder.setPositiveButton("升级", new DialogInterface.OnClickListener() {
+
+            @Override
+            public void onClick(DialogInterface dialog, int which) {
+                // TODO Auto-generated method stub
+                // 这里做升级操作
+                new Thread(new Runnable() {
+                    @Override
+                    public void run() {
+                        UpdateUtil uputil = new UpdateUtil(mView.getActivity());
+                        try {
+                            uputil.down_file(entity.download_url);
+                        } catch (IOException e) {
+                            // TODO Auto-generated catch block
+                            e.printStackTrace();
+                        }
+                    }
+                }).start();
+
+            }
+        });
+
+        AlertDialog dialog = builder.create();
+        dialog.setOnKeyListener(new DialogInterface.OnKeyListener() {
+
+            @Override
+            public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
+                // TODO Auto-generated method stub
+                if (event.getKeyCode() == KeyEvent.KEYCODE_BACK || event.getKeyCode() == KeyEvent.KEYCODE_ESCAPE) {
+                    return true;
+                }
+                return false;
+            }
+        });
+        dialog.show();
+    }
+
+    //JS条用方法,调起微信登录
+    @JavascriptInterface
+    public void WeChatLogin() {
+        if (!PayInit.getInstance().WX_API.isWXAppInstalled()) {
+            ToastUtil.showToast("请安装微信");
+        } else {
+            final SendAuth.Req req = new SendAuth.Req();
+            req.scope = "snsapi_userinfo";
+            req.state = "wechat_sdk_demo_test";
+            PayInit.getInstance().WX_API.sendReq(req);
+        }
+    }
+
+    @JavascriptInterface
+    public void clickMusic(String left, String right) {
+        mediaPlayer.setVolume(Float.valueOf(left), Float.valueOf(right));
+        mediaPlayer.start();
+    }
+
+    public void desClickMusic() {
+        mediaPlayer = null;
+    }
+
+    @JavascriptInterface
+    public void toMiniProgram(String programId, String path) {
+        if (!PayInit.getInstance().WX_API.isWXAppInstalled()) {
+            ToastUtil.showToast("请安装微信");
+            return;
+        }
+        WXLaunchMiniProgram.Req req = new WXLaunchMiniProgram.Req();
+        req.userName = programId; // 填小程序原始id
+        req.path = path;                  //拉起小程序页面的可带参路径,不填默认拉起小程序首页
+        req.miniprogramType = WXLaunchMiniProgram.Req.MINIPTOGRAM_TYPE_RELEASE;// 可选打开 开发版,体验版和正式版
+        PayInit.getInstance().WX_API.sendReq(req);
+    }
+
+
+    @JavascriptInterface
+    public void showDeviceInfo() {
+        ShowDevice.getInstance().show(mView.getActivity());
+    }
+
+    @JavascriptInterface
+    public void showChoseVideo() {
+        ShowSetting.getInstance().show(mView.getActivity());
+    }
+
+    @JavascriptInterface
+    public void showDebugDialog() {
+        ShowDebugUrl.getInstance().show(mView);
+    }
+}

+ 30 - 0
app/src/main/java/com/edufound/mobile/main/MainModel.java

@@ -0,0 +1,30 @@
+package com.edufound.mobile.main;
+
+import com.edufound.mobile.R;
+import com.edufound.mobile.base.BaseModel;
+import com.edufound.mobile.util.ContextUtil;
+
+//做请求操作之类的
+public class MainModel implements BaseModel {
+
+
+    public MainModel() {
+
+    }
+
+    @Override
+    public void LoadData(LoadDataBack callback) {
+        if (true) {
+            callback.success("12333333");
+        } else {
+            callback.failure();
+        }
+    }
+
+
+    public String getDefaultLoadUrl() {
+        return ContextUtil.getContext().getString(R.string.default_url) + "?";
+    }
+
+
+}

+ 437 - 0
app/src/main/java/com/edufound/mobile/main/MainPersenter.java

@@ -0,0 +1,437 @@
+package com.edufound.mobile.main;
+
+import android.annotation.SuppressLint;
+import android.annotation.TargetApi;
+import android.app.Activity;
+import android.app.Dialog;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.support.annotation.Nullable;
+import android.view.Display;
+import android.view.Gravity;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+import android.webkit.JsResult;
+import android.webkit.WebChromeClient;
+import android.webkit.WebResourceRequest;
+import android.webkit.WebResourceResponse;
+import android.webkit.WebSettings;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+
+import com.edufound.mobile.application.EApplication;
+import com.edufound.mobile.base.BaseModel;
+import com.edufound.mobile.base.BasePersenter;
+import com.edufound.mobile.interfaces.EfunboxPayInterfaces;
+import com.edufound.mobile.interfaces.JsInterfaces;
+import com.edufound.mobile.util.ContextUtil;
+import com.edufound.mobile.util.DeviceUtil;
+import com.edufound.mobile.util.DeviceUuidFactory;
+import com.edufound.mobile.util.Logger;
+import com.edufound.mobile.util.SPutil;
+import com.edufound.mobile.util.ToastUtil;
+import com.edufound.mobile.view.ErrorView;
+
+public class MainPersenter implements MainIPersenter {
+
+    public static final int WECHAT_LOGIN = 0x76761;
+    public static final int PAY_RESULT = 0x76762;
+    private static MainView mView = null;
+    private MainModel mModel = null;
+    private JsInterfaces mJsInterfaces = null;
+    private EfunboxPayInterfaces mPayInterfaces = null;
+    private String mLoadUrl;
+    ErrorView mErrorView;
+    Dialog mErrorViewDialog;
+    private DeviceUtil deviceUtil;
+
+
+    public MainPersenter(MainView view) {
+        mView = view;
+        mModel = new MainModel();
+        deviceUtil = new DeviceUtil();
+        mJsInterfaces = new JsInterfaces(mView);
+        mPayInterfaces = new EfunboxPayInterfaces(mView);
+    }
+
+    @Override
+    public void loadData() {
+        mModel.LoadData(new BaseModel.LoadDataBack() {
+            @Override
+            public void success(String datajson) {
+                Logger.e("datajson:" + datajson);
+                mView.showData(datajson);
+            }
+
+            @Override
+            public void failure() {
+                Logger.e("failure");
+            }
+        });
+    }
+
+    // 设置WebView
+    @SuppressLint("JavascriptInterface")
+    @Override
+    public void initWebView(final WebView webview) {
+        if (Build.VERSION.SDK_INT >= 19) {
+            webview.getSettings().setLoadsImagesAutomatically(true);
+        } else {
+            webview.getSettings().setLoadsImagesAutomatically(false);
+        }
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+            webview.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
+        }
+        webview.requestFocus(View.FOCUS_DOWN);
+        webview.getSettings().setJavaScriptEnabled(true);
+        webview.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);//允许js弹出窗口
+        webview.getSettings().setDomStorageEnabled(true);
+//        webview.getSettings().setMediaPlaybackRequiresUserGesture(false);
+        webview.getSettings().setBlockNetworkImage(false);
+        // webview.getSettings().set
+        webview.setBackgroundColor(Color.TRANSPARENT);
+//       webview.setBackgroundResource();
+        webview.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
+        webview.getSettings().setUseWideViewPort(true);
+        webview.getSettings().setLoadWithOverviewMode(true);
+        webview.getSettings().setTextZoom(100);
+        webview.setWebChromeClient(new WebChromeClient() {
+
+            @Override
+            public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
+
+                return super.onJsAlert(view, url, message, result);
+            }
+
+            @Override
+            public void onShowCustomView(View view, CustomViewCallback callback) {
+
+                super.onShowCustomView(view, callback);
+            }
+
+            @Override
+            public void onProgressChanged(WebView view, int newProgress) {
+
+                if (newProgress >= 100) {
+                }
+                super.onProgressChanged(view, newProgress);
+            }
+
+        });
+
+        webview.setWebViewClient(new WebViewClient() {
+
+            @Override
+            public boolean shouldOverrideUrlLoading(WebView view, String url) {
+//                webview.removeAllViews();
+                view.loadUrl(url);
+                return true;
+            }
+
+            @Override
+            public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
+                super.onReceivedError(view, errorCode, description, failingUrl);
+                view.loadUrl("");
+                showDisConnNeWorkWindow();
+            }
+
+            @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("about:blank");// 避免出现默认的错误界面
+//                    showDisConnNeWorkWindow();
+//                }
+
+            }
+
+            @Override
+            public void onPageStarted(WebView view, String url, Bitmap favicon) {
+                super.onPageStarted(view, url, favicon);
+            }
+
+            @Override
+            public void onPageFinished(WebView view, String url) {
+                if (!webview.getSettings().getLoadsImagesAutomatically()) {
+                    webview.getSettings().setLoadsImagesAutomatically(true);
+                }
+                mView.hideLoading();
+                super.onPageFinished(view, url);
+            }
+
+        });
+        webview.addJavascriptInterface(mJsInterfaces, "efunboxJS");
+        webview.addJavascriptInterface(mPayInterfaces, "efunboxPay");
+
+    }
+
+    public int dip2px(Context context, float dpValue) {
+        final float scale = context.getResources().getDisplayMetrics().density;
+        return (int) (dpValue * scale + 0.5f);
+    }
+
+    @Override
+    public JsInterfaces getJsInterfaces() {
+        return mJsInterfaces;
+    }
+
+    @Override
+    public EfunboxPayInterfaces getPayInterfaces() {
+        return mPayInterfaces;
+    }
+
+    @Override
+    public void openWeb(Intent intent) {
+        mView.loadUrl("");
+        mLoadUrl = mModel.getDefaultLoadUrl();
+        String intent_url = intent.getStringExtra("url");
+        Logger.e("-----------------------------");
+        Logger.e("intent_url:" + intent_url);
+        Logger.e("-----------------------------");
+        if (intent_url != null && !intent_url.isEmpty()) {
+            mLoadUrl = intent_url;
+        }
+        String preuuid = SPutil.getPrefString(ContextUtil.getContext(), DeviceUuidFactory.UUID_SPKEY, "");
+        if (preuuid.equals("")) {
+            preuuid = DeviceUuidFactory.getUuid().toString();
+        }
+
+        StringBuffer buffer = new StringBuffer();
+        buffer.append("appCode=" + EApplication.getAppCode());
+        buffer.append("&uuid=" + preuuid);
+        buffer.append("&width=" + deviceUtil.getWidth(mView.getActivity()));
+        buffer.append("&height=" + deviceUtil.getHeight(mView.getActivity()));
+        buffer.append("&version=" + deviceUtil.getVersionCode(mView.getActivity()));
+        mLoadUrl += buffer.toString();
+        Logger.DebugE("LOADURL=" + mLoadUrl);
+        mView.loadUrl(mLoadUrl);
+    }
+
+    @Override
+    public boolean onKeyDown(int keycode, KeyEvent event) {
+        switch (keycode) {
+            case KeyEvent.KEYCODE_DPAD_CENTER:
+            case KeyEvent.KEYCODE_ENTER:
+                mView.loadJsMehtod("boxEventHandler('key_down','KEY_SELECT')");
+                break;
+            case KeyEvent.KEYCODE_BACK:
+            case KeyEvent.KEYCODE_ESCAPE:
+                mView.loadJsMehtod("boxEventHandler('key_down','KEY_BACK')");
+                return true;
+            case KeyEvent.KEYCODE_HOME:
+                // Home键 -,- P.S:不一定能监听到
+                Logger.DebugE("click home");
+                EApplication.exitApp();
+                break;
+            case KeyEvent.KEYCODE_DPAD_UP:
+                // 上
+                mView.loadJsMehtod("boxEventHandler('key_down','KEY_UP')");
+                break;
+            case KeyEvent.KEYCODE_DPAD_RIGHT:
+                // 右
+                mView.loadJsMehtod("boxEventHandler('key_down','KEY_RIGHT')");
+                break;
+            case KeyEvent.KEYCODE_DPAD_DOWN:
+                // 下
+                mView.loadJsMehtod("boxEventHandler('key_down','KEY_DOWN')");
+                break;
+            case KeyEvent.KEYCODE_DPAD_LEFT:
+                // 左
+                mView.loadJsMehtod("boxEventHandler('key_down','KEY_LEFT')");
+                break;
+        }
+        return false;
+    }
+
+    @Override
+    public boolean onKeyUp(int keycode, KeyEvent event) {
+//        getJsInterfaces().clickMusic("1", "1");
+        if (mView.getActivityPay()) {
+            return true;
+        }
+        switch (keycode) {
+            case KeyEvent.KEYCODE_DPAD_CENTER:
+            case KeyEvent.KEYCODE_ENTER:
+                // 确认键
+                mView.loadJsMehtod("boxEventHandler('key_up','KEY_SELECT')");
+                break;
+            case KeyEvent.KEYCODE_BACK:
+            case KeyEvent.KEYCODE_ESCAPE:
+                // 返回键
+                mView.loadJsMehtod("boxEventHandler('key_up','KEY_BACK')");
+//                mJsInterfaces.closeApp();
+                return true;
+            case KeyEvent.KEYCODE_DPAD_UP:
+                // 上
+                mView.loadJsMehtod("boxEventHandler('key_up','KEY_UP')");
+                break;
+            case KeyEvent.KEYCODE_DPAD_RIGHT:
+                // 右
+                mView.loadJsMehtod("boxEventHandler('key_up','KEY_RIGHT')");
+                break;
+            case KeyEvent.KEYCODE_DPAD_DOWN:
+                // 下
+                mView.loadJsMehtod("boxEventHandler('key_up','KEY_DOWN')");
+                break;
+            case KeyEvent.KEYCODE_DPAD_LEFT:
+                // 左
+                mView.loadJsMehtod("boxEventHandler('key_up','KEY_LEFT')");
+                break;
+        }
+        return false;
+    }
+
+    @Override
+    public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
+        switch (requestCode) {
+            case EfunboxPayInterfaces.START_PAY_DB:
+                if (resultCode == Activity.RESULT_OK) {
+                    Bundle bundle = data.getExtras();
+                    int back = bundle.getInt("back");
+                    //back为返回值
+                    String Out_trade_no = bundle.getString("Out_trade_no");
+                    // Out_trade_no为订单号
+                } else if (requestCode == Activity.RESULT_CANCELED) {
+                }
+                break;
+            case EfunboxPayInterfaces.START_PAY_HUANWANG:
+                break;
+            case EfunboxPayInterfaces.START_PAY_SKYWORTH:
+//                ToastUtil.showToast("START_PAY_SKYWORTH");
+                break;
+            case EfunboxPayInterfaces.START_PAY_XIAOMI:
+//                ToastUtil.showToast("START_PAY_XIAOMI");
+                break;
+
+        }
+        mView.acPostDelayed(new Runnable() {
+            @Override
+            public void run() {
+                mView.setActivityPay(false);
+            }
+        }, 1000);
+    }
+
+
+    @Override
+    public void onDisConnNetWork() {
+//        ToastUtil.showToast("断网了。。");
+        mView.stopWebView();
+        showDisConnNeWorkWindow();
+    }
+
+    @Override
+    public void onConnNetWork() {
+        Logger.e("onConnNetWork");
+//        if (mErrorViewDialog != null) {
+//            mErrorViewDialog.dismiss();
+//            mView.resumeWebView();
+//        }
+    }
+
+    void showDisConnNeWorkWindow() {
+        if (mErrorView == null) {
+            mErrorViewDialog = new Dialog(mView.getActivity());
+            try {
+                int dividerID = mView.getActivity().getResources().getIdentifier("android:id/titleDivider", null, null);
+                View divider = mErrorViewDialog.findViewById(dividerID);
+                divider.setBackgroundColor(Color.TRANSPARENT);
+            } catch (Exception e) {
+                //上面的代码,是用来去除Holo主题的蓝色线条
+                e.printStackTrace();
+            }
+            mErrorView = new ErrorView(mView);
+            mErrorView.setViewBgColor(Color.TRANSPARENT);
+            mErrorView.setBtnClickListener(new ErrorView.BtnClickListener() {
+                @Override
+                public void clickRelase() {
+                    //重新加载
+                    if (ContextUtil.getNetWorkState()) {
+                        mView.destroyWeb();
+                        mErrorViewDialog.dismiss();
+                        mView.resumeWebView();
+                        openWeb(mView.getActivity().getIntent());
+                    } else {
+                        ToastUtil.showToast("请检查网络连接状况");
+                    }
+                }
+
+                @Override
+                public void clickExit() {
+                    //退出
+                    mErrorViewDialog.dismiss();
+                    mView.getActivity().finish();
+                    EApplication.clearActivity();
+                }
+            });
+            mErrorViewDialog.setCancelable(false);
+            mErrorViewDialog.setContentView(mErrorView);
+            Window dialogWindow = mErrorViewDialog.getWindow();
+            dialogWindow.setGravity(Gravity.CENTER);
+            dialogWindow.getDecorView().setPadding(0, 0, 0, 0);
+            dialogWindow.getDecorView().setBackgroundColor(Color.TRANSPARENT);
+            WindowManager m = mView.getActivity().getWindowManager();
+            Display d = m.getDefaultDisplay(); // 获取屏幕宽、高用
+            WindowManager.LayoutParams p = dialogWindow.getAttributes(); // 获取对话框当前的参数值
+            p.height = (int) (d.getHeight() * 1);
+            p.width = WindowManager.LayoutParams.MATCH_PARENT;
+            p.horizontalMargin = 0;
+            dialogWindow.setAttributes(p);
+        }
+        if (!mErrorViewDialog.isShowing()) {
+            mErrorViewDialog.show();
+        }
+    }
+
+
+    public static Handler mPersenterHandler = new Handler(new Handler.Callback() {
+        @Override
+        public boolean handleMessage(Message msg) {
+            switch (msg.what) {
+                case WECHAT_LOGIN:
+//                    Logger.e("微信用户信息:" + msg.obj.toString());
+                    mView.loadJsMehtod("WeChatLoginSuccess('" + msg.obj.toString() + "')");
+                    break;
+                case PAY_RESULT:
+                    mView.loadJsMehtod("commonPayResult(" + msg.obj.toString() + ")");
+                    Intent intent_restart = new Intent(ContextUtil.CLOSE_ACTIVITY_PAY);
+                    mView.getActivity().sendBroadcast(intent_restart);
+                    break;
+            }
+            return false;
+        }
+    });
+
+
+}
+
+
+interface MainIPersenter extends BasePersenter {
+    void initWebView(WebView webview);
+
+    JsInterfaces getJsInterfaces();
+
+    EfunboxPayInterfaces getPayInterfaces();
+
+    void openWeb(Intent intent);
+
+    boolean onKeyDown(int keycode, KeyEvent event);
+
+    boolean onKeyUp(int keycode, KeyEvent event);
+
+    void onActivityResult(int requestCode, int resultCode, @Nullable Intent data);
+
+}

+ 37 - 0
app/src/main/java/com/edufound/mobile/main/MainView.java

@@ -0,0 +1,37 @@
+package com.edufound.mobile.main;
+
+import android.app.Activity;
+
+import com.edufound.mobile.base.BaseView;
+
+
+public interface MainView extends BaseView {
+    //把View拋出給Presenter調用
+
+    void loadUrl(String url);
+
+    @Override
+    void DisconnNetWork();
+
+    @Override
+    void ConnNeWork();
+
+    void loadJsMehtod(String method);
+
+    Activity getActivity();
+
+    void setActivityPay(boolean bool);
+
+    boolean getActivityPay();
+
+    void acPostDelayed(Runnable runnable, int time);
+
+    void destroyWeb();
+
+    void hideLoading();
+
+    void stopWebView();
+
+    void resumeWebView();
+
+}

+ 113 - 0
app/src/main/java/com/edufound/mobile/pay/PayActivity.java

@@ -0,0 +1,113 @@
+package com.edufound.mobile.pay;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.text.TextUtils;
+
+import com.alipay.sdk.app.PayTask;
+import com.edufound.mobile.R;
+import com.edufound.mobile.application.EApplication;
+import com.edufound.mobile.base.BaseView;
+import com.edufound.mobile.interfaces.EfunboxPayInterfaces;
+import com.edufound.mobile.pay.ali.PayResult;
+import com.edufound.mobile.util.ContextUtil;
+import com.edufound.mobile.util.Logger;
+import com.edufound.mobile.util.ToastUtil;
+import com.tencent.mm.opensdk.modelpay.PayReq;
+
+import org.json.JSONObject;
+
+import java.util.Map;
+
+public class PayActivity extends Activity implements BaseView {
+
+    String payjson = "";
+    PayPersenter mPersenter;
+    Activity mActivity;
+    int firstResume = 0;
+    int wechatOrAli = 0;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_pay);
+        mActivity = this;
+        mPersenter = new PayPersenter(this);
+        int type = Integer.valueOf(getIntent().getStringExtra("type"));
+        final String payjson = getIntent().getStringExtra("payString");
+        wechatOrAli = type;
+        switch (type) {
+            case 1:
+                mPersenter.WeChatPay(payjson);
+                break;
+            case 2:
+                mPersenter.ALIPay(payjson);
+                break;
+        }
+        IntentFilter intentFilter = new IntentFilter();
+        intentFilter.addAction(ContextUtil.CLOSE_ACTIVITY_PAY);
+        registerReceiver(payBroad, intentFilter);
+    }
+
+
+    BroadcastReceiver payBroad = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            switch (intent.getAction()) {
+                case ContextUtil.CLOSE_ACTIVITY_PAY:
+                    finish();
+                    break;
+            }
+        }
+    };
+
+    @Override
+    public void showData(String text) {
+
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        switch (wechatOrAli) {
+            case 1:
+                if (firstResume >= 1) {
+                    finish();
+                } else {
+                    firstResume++;
+                }
+                break;
+            case 2:
+                //阿里应该就不用管了
+                break;
+        }
+    }
+
+
+    @Override
+    public void DisconnNetWork() {
+        mPersenter.onDisConnNetWork();
+    }
+
+    @Override
+    public void ConnNeWork() {
+        mPersenter.onConnNetWork();
+    }
+
+    @Override
+    public Activity getActivity() {
+        return mActivity;
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        unregisterReceiver(payBroad);
+    }
+}

+ 46 - 0
app/src/main/java/com/edufound/mobile/pay/PayInit.java

@@ -0,0 +1,46 @@
+package com.edufound.mobile.pay;
+
+import android.app.Application;
+
+import com.edufound.mobile.R;
+import com.edufound.mobile.util.ContextUtil;
+import com.edufound.mobile.util.Logger;
+import com.tencent.mm.opensdk.openapi.IWXAPI;
+import com.tencent.mm.opensdk.openapi.WXAPIFactory;
+
+public class PayInit {
+    private static PayInit mIntences;
+    //微信api
+    public IWXAPI WX_API;
+    //微信appid
+    public String WX_APPID = "wx51acc19c8f7a0f6f";
+    public String WX_SECRET = "e830d45f497025041269ef6221140c3d";
+
+    public static PayInit getInstance() {
+        if (mIntences == null) {
+            mIntences = new PayInit();
+        }
+        return mIntences;
+    }
+
+
+    public void initPaySDK(int code, Application application) {
+        WX_API = WXAPIFactory.createWXAPI(ContextUtil.getContext(), WX_APPID);
+        WX_API.registerApp(WX_APPID);
+
+    }
+
+    public void destroyPaySDK(int code, Application application) {
+//        if (String.valueOf(code).equals(application.getString(R.string.app_code_yf))) {
+//        } else if (String.valueOf(code).equals(application.getString(R.string.app_code_db))) {
+//        } else if (String.valueOf(code).equals(application.getString(R.string.app_code_xal))) {
+//        } else if (String.valueOf(code).equals(application.getString(R.string.app_code_cwkk))) {
+//        } else if (String.valueOf(code).equals(application.getString(R.string.app_code_sf))) {
+//        } else if (String.valueOf(code).equals(application.getString(R.string.app_code_fx))) {
+//        } else if (String.valueOf(code).equals(application.getString(R.string.app_code_xm))) {
+//        } else if (String.valueOf(code).equals(application.getString(R.string.app_code_hw))) {
+//        } else if (String.valueOf(code).equals(application.getString(R.string.app_code_lx))) {
+//        }
+    }
+
+}

+ 154 - 0
app/src/main/java/com/edufound/mobile/pay/PayPersenter.java

@@ -0,0 +1,154 @@
+package com.edufound.mobile.pay;
+
+import android.os.Handler;
+import android.os.Message;
+import android.text.TextUtils;
+
+import com.alipay.sdk.app.PayTask;
+import com.edufound.mobile.base.BasePersenter;
+import com.edufound.mobile.base.BaseView;
+import com.edufound.mobile.interfaces.EfunboxPayInterfaces;
+import com.edufound.mobile.main.MainPersenter;
+import com.edufound.mobile.pay.ali.PayResult;
+import com.edufound.mobile.util.Logger;
+import com.edufound.mobile.util.ToastUtil;
+import com.tencent.mm.opensdk.modelpay.PayReq;
+
+import org.json.JSONObject;
+
+import java.util.Map;
+
+public class PayPersenter implements PayIPersenter {
+
+    BaseView mView;
+
+    public PayPersenter(BaseView view) {
+        mView = view;
+    }
+
+    @Override
+    public void loadData() {
+
+    }
+
+    @Override
+    public void onDisConnNetWork() {
+
+    }
+
+    @Override
+    public void onConnNetWork() {
+
+    }
+
+    @Override
+    public void WeChatPay(String json) {
+        if (!PayInit.getInstance().WX_API.isWXAppInstalled()) {
+            ToastUtil.showToast("请安装微信");
+            return;
+        }
+        Message msg = new Message();
+        msg.obj = json;
+        msg.what = 0xffbcd14;
+        resultHandler.sendMessageDelayed(msg, 0);
+    }
+
+    @Override
+    public void ALIPay(final String orderInfo) {
+        Logger.e("orderInfo:" + orderInfo);
+        Runnable payRunnable = new Runnable() {
+            @Override
+            public void run() {
+                PayTask alipay = new PayTask(mView.getActivity());
+                Map<String, String> result = alipay.payV2(orderInfo, true);
+                Message msg = new Message();
+                msg.what = 0xffbcd15;
+                msg.obj = result;
+                resultHandler.sendMessage(msg);
+            }
+        };
+        Thread payThread = new Thread(payRunnable);
+        payThread.start();
+    }
+
+    Handler resultHandler = new Handler(new Handler.Callback() {
+        @Override
+        public boolean handleMessage(Message msg) {
+            switch (msg.what) {
+                case EfunboxPayInterfaces.PAY_BEGIN:
+                    ToastUtil.showToast("支付开始");
+                    break;
+                case EfunboxPayInterfaces.PAY_SUCCESS:
+                    ToastUtil.showToast("支付成功");
+                    break;
+                case EfunboxPayInterfaces.PAY_ERROR:
+                    ToastUtil.showToast("支付失败");
+                    break;
+                case EfunboxPayInterfaces.PAY_CANCEL:
+                    ToastUtil.showToast("取消支付");
+                    break;
+                case 0xffbcd14:
+                    //微信支付
+                    try {
+                        String jsonmessage = msg.obj.toString();
+                        if (jsonmessage != null && jsonmessage.length() > 0) {
+                            JSONObject json = new JSONObject(jsonmessage);
+                            Logger.e("json:" + json);
+                            if (null != json) {
+                                PayReq req = new PayReq();
+                                req.appId = json.getString("appid");
+                                req.partnerId = json.getString("partnerid");
+                                req.prepayId = json.getString("prepayid");
+                                req.nonceStr = json.getString("noncestr");
+                                req.timeStamp = json.getString("timestamp");
+                                req.packageValue = json.getString("package");
+                                req.sign = json.getString("sign");
+                                PayInit.getInstance().WX_API.sendReq(req);
+                            } else {
+                                Logger.e("返回错误" + json.getString("retmsg"));
+                                mView.getActivity().finish();
+                            }
+                        } else {
+                            Logger.e("服务器请求错误");
+                            mView.getActivity().finish();
+                        }
+                    } catch (Exception e) {
+                        Logger.e("异常:" + e.getMessage());
+                        mView.getActivity().finish();
+                    }
+                    break;
+                case 0xffbcd15:
+                    //支付宝支付
+                    PayResult payResult = new PayResult((Map<String, String>) msg.obj);
+                    String resultInfo = payResult.getResult();// 同步返回需要验证的信息
+                    String resultStatus = payResult.getResultStatus();
+                    Logger.e("resultInfo:" + resultInfo);
+                    Logger.e("resultStatus:" + resultStatus);
+                    Message alimsg = new Message();
+                    alimsg.what = MainPersenter.PAY_RESULT;
+                    // 判断resultStatus 为9000则代表支付成功
+                    if (TextUtils.equals(resultStatus, "9000")) {
+                        // 该笔订单是否真实支付成功,需要依赖服务端的异步通知。
+//                        ToastUtil.showToast( "支付成功");
+                        alimsg.obj = 0;
+                    } else {
+                        // 该笔订单真实的支付结果,需要依赖服务端的异步通知。
+//                        CustomToast.showToast(mContext, "支付失败", 3000);
+                        alimsg.obj = -11;
+                    }
+                    MainPersenter.mPersenterHandler.sendMessage(alimsg);
+                    break;
+            }
+            return false;
+        }
+    });
+
+
+}
+
+
+interface PayIPersenter extends BasePersenter {
+    void WeChatPay(String json);
+
+    void ALIPay(String orderInfo);
+}

File diff suppressed because it is too large
+ 1 - 0
app/src/main/java/com/edufound/mobile/pay/ali/PayResult.java


+ 37 - 0
app/src/main/java/com/edufound/mobile/push/MipushTestActivity.java

@@ -0,0 +1,37 @@
+package com.edufound.mobile.push;
+
+import android.content.Intent;
+import android.os.Bundle;
+
+import com.edufound.mobile.R;
+import com.edufound.mobile.activity.MainActivity;
+import com.edufound.mobile.bean.NotificationBean;
+import com.edufound.mobile.util.Logger;
+import com.google.gson.Gson;
+import com.umeng.message.UmengNotifyClickActivity;
+
+import org.android.agoo.common.AgooConstants;
+
+public class MipushTestActivity extends UmengNotifyClickActivity {
+    String intent_url = "";
+
+    @Override
+    protected void onCreate(Bundle bundle) {
+        super.onCreate(bundle);
+//        setContentView(R.layout.activity_mipush);
+        intent_url = getIntent().getStringExtra("url");
+    }
+
+    @Override
+    public void onMessage(Intent intent) {
+        super.onMessage(intent);  //此方法必须调用,否则无法统计打开数
+        String body = intent.getStringExtra(AgooConstants.MESSAGE_BODY);
+        Logger.e("小米推送activity--body:" + body);
+        Gson gson = new Gson();
+        NotificationBean bean = gson.fromJson(body, NotificationBean.class);
+        Intent intent1 = new Intent(MipushTestActivity.this, MainActivity.class);
+        intent1.putExtra("url", bean.getExtra().getUrl());
+        startActivity(intent1);
+        finish();
+    }
+}

+ 33 - 0
app/src/main/java/com/edufound/mobile/receiver/HomeKeyEventReceiver.java

@@ -0,0 +1,33 @@
+package com.edufound.mobile.receiver;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.text.TextUtils;
+
+import com.edufound.mobile.application.EApplication;
+import com.edufound.mobile.util.Logger;
+
+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.DebugE("click home");
+//                EApplication.exitApp();
+//                android.os.Process.killProcess(android.os.Process.myPid());
+            } else if (TextUtils.equals(reason, SYSTEM_DIALOG_REASON_RECENT_APPS)) {
+                Logger.DebugE(" click recentapps");
+            }
+        }
+    }
+
+}

+ 103 - 0
app/src/main/java/com/edufound/mobile/receiver/NetworkChangeReceiver.java

@@ -0,0 +1,103 @@
+package com.edufound.mobile.receiver;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.os.Handler;
+import android.os.Message;
+import android.telephony.TelephonyManager;
+
+import com.edufound.mobile.base.BaseView;
+import com.edufound.mobile.util.ContextUtil;
+import com.edufound.mobile.util.Logger;
+import com.edufound.mobile.util.ToastUtil;
+
+
+/**
+ * Created by Candy on 2018/4/8.
+ */
+
+public class NetworkChangeReceiver extends BroadcastReceiver {
+    BaseView mView;
+    final int DISCONNECT = 0x21;
+    final int CONNECT = 0x22;
+    String strNetworkType;
+
+    public NetworkChangeReceiver(BaseView view) {
+        mView = view;
+    }
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        GetNetworkType(context);
+
+    }
+
+    public void GetNetworkType(Context context) {
+        ConnectivityManager connectMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+        NetworkInfo networkInfo = connectMgr.getActiveNetworkInfo();
+        if (networkInfo != null && networkInfo.isConnected()) {
+            handler.sendEmptyMessage(CONNECT);
+            if (networkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
+                strNetworkType = "WIFI";
+                ContextUtil.setmNetWorkState(true);
+            } else if (networkInfo.getType() == ConnectivityManager.TYPE_MOBILE) {
+                String _strSubTypeName = networkInfo.getSubtypeName();
+                Logger.e("Network getSubtypeName : " + _strSubTypeName);
+                int networkType = networkInfo.getSubtype();
+                switch (networkType) {
+                    case TelephonyManager.NETWORK_TYPE_GPRS:
+                    case TelephonyManager.NETWORK_TYPE_EDGE:
+                    case TelephonyManager.NETWORK_TYPE_CDMA:
+                    case TelephonyManager.NETWORK_TYPE_1xRTT:
+                    case TelephonyManager.NETWORK_TYPE_IDEN: //api<8 : replace by 11
+                        strNetworkType = "2G";
+                        break;
+                    case TelephonyManager.NETWORK_TYPE_UMTS:
+                    case TelephonyManager.NETWORK_TYPE_EVDO_0:
+                    case TelephonyManager.NETWORK_TYPE_EVDO_A:
+                    case TelephonyManager.NETWORK_TYPE_HSDPA:
+                    case TelephonyManager.NETWORK_TYPE_HSUPA:
+                    case TelephonyManager.NETWORK_TYPE_HSPA:
+                    case TelephonyManager.NETWORK_TYPE_EVDO_B: //api<9 : replace by 14
+                    case TelephonyManager.NETWORK_TYPE_EHRPD:  //api<11 : replace by 12
+                    case TelephonyManager.NETWORK_TYPE_HSPAP:  //api<13 : replace by 15
+                        strNetworkType = "3G";
+                        break;
+                    case TelephonyManager.NETWORK_TYPE_LTE:    //api<11 : replace by 13
+                        strNetworkType = "4G";
+                        break;
+
+                }
+                Logger.e("Network getSubtype : " + Integer.valueOf(networkType).toString());
+                ToastUtil.showToast("当前网络环境:" + strNetworkType);
+                ContextUtil.setmNetWorkState(true);
+            }
+        } else {
+            ContextUtil.setmNetWorkState(false);
+            strNetworkType = "-1";
+            handler.sendEmptyMessageDelayed(DISCONNECT, 2000);
+
+        }
+        Logger.e("Network Type : " + strNetworkType);
+    }
+
+
+    Handler handler = new Handler(new Handler.Callback() {
+        @Override
+        public boolean handleMessage(Message msg) {
+            switch (msg.what) {
+                case DISCONNECT:
+                    mView.DisconnNetWork();
+                    break;
+                case CONNECT:
+                    handler.removeMessages(DISCONNECT);
+                    mView.ConnNeWork();
+                    break;
+            }
+            return false;
+        }
+    });
+}

+ 67 - 0
app/src/main/java/com/edufound/mobile/util/AesUtil.java

@@ -0,0 +1,67 @@
+package com.edufound.mobile.util;
+
+import org.bouncycastle.util.encoders.Base64;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.SecretKeySpec;
+
+public class AesUtil {
+
+    static final String sKey = "GfqqwfctR8gdNGUS";
+
+    // 解密
+    public static String Decrypt(String sSrc) throws Exception {
+        try {
+            // 判断Key是否正确
+            if (sKey == null) {
+                System.out.print("Key为空null");
+                return null;
+            }
+            // 判断Key是否为16位
+            if (sKey.length() != 16) {
+                System.out.print("Key长度不是16位");
+                return null;
+            }
+            byte[] raw = sKey.getBytes("utf-8");
+            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
+            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
+            cipher.init(Cipher.DECRYPT_MODE, skeySpec);
+            //先用base64转码
+            //byte[] encrypted1 = new Base64().decode(sSrc);
+            byte[] encrypted1 = Base64.decode(sSrc);
+            try {
+                byte[] original = cipher.doFinal(encrypted1);
+                String originalString = new String(original, "utf-8");
+                return originalString;
+            } catch (Exception e) {
+                System.out.println(e.toString());
+                return null;
+            }
+        } catch (Exception ex) {
+            System.out.println(ex.toString());
+            return null;
+        }
+    }
+
+    //加密
+    public static String Encrypt(String sSrc) throws Exception {
+        if (sKey == null) {
+            System.out.print("Key为空null");
+            return null;
+        }
+        // 判断Key是否为16位
+        if (sKey.length() != 16) {
+            System.out.print("Key长度不是16位");
+            return null;
+        }
+        byte[] raw = sKey.getBytes("utf-8");
+        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
+        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");//"算法/模式/补码方式"
+        cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
+        byte[] encrypted = cipher.doFinal(sSrc.getBytes("utf-8"));
+        //此处使用BASE64做转码功能,同时能起到2次加密的作用。
+        //return new Base64().encodeToString(encrypted);
+        return new String(Base64.encode(encrypted));
+    }
+
+}

+ 60 - 0
app/src/main/java/com/edufound/mobile/util/ContextUtil.java

@@ -0,0 +1,60 @@
+package com.edufound.mobile.util;
+
+import android.app.Application;
+import android.content.Context;
+
+import com.edufound.mobile.base.BaseView;
+
+public class ContextUtil {
+
+    public static final String CLOSE_ACTIVITY_SPLASH = "com.edufound.mobile.close.splash";
+    public static final String CLOSE_ACTIVITY_MAIN = "com.edufound.mobile.close.main";
+    public static final String CLOSE_ACTIVITY_PAY = "com.edufound.mobile.close.pay";
+    public static final String RESTART_ACTIVITY_MAIN = "com.edufound.mobile.restart.main";
+    public static final String CHANGE_VIDEO_TYPE_VIDEO = "com.edufound.mobile.change.video";
+    public static final String CHANGE_VIDEO_TYPE_IJKPLAYER = "com.edufound.mobile.change.ijkplayer";
+    public static final String NOTIFICATION_WEB_PLAYERTIME = "com.edufound.mobile.notification.playertime";
+    static Context mContext;
+    static Application application;
+
+    public static Application getApplication() {
+        return application;
+    }
+
+    public static void setApplication(Application application) {
+        ContextUtil.application = application;
+    }
+
+    static boolean isDebug;
+    static boolean mNetWorkState = true;
+
+    public static boolean getNetWorkState() {
+        return mNetWorkState;
+    }
+
+    public static void setmNetWorkState(boolean mNetWorkState) {
+        ContextUtil.mNetWorkState = mNetWorkState;
+    }
+
+    public static void setContext(Context context) {
+        mContext = context;
+    }
+
+    public static Context getContext() {
+        if (mContext == null) {
+            return null;
+        }
+        return mContext;
+    }
+
+
+    public static boolean isIsDebug() {
+        return isDebug;
+    }
+
+    public static void setIsDebug(boolean isDebug) {
+        ContextUtil.isDebug = isDebug;
+    }
+
+
+}

+ 192 - 0
app/src/main/java/com/edufound/mobile/util/DeviceUtil.java

@@ -0,0 +1,192 @@
+package com.edufound.mobile.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 java.io.UnsupportedEncodingException;
+import java.security.MessageDigest;
+import java.util.Locale;
+
+public class DeviceUtil {
+
+	DisplayMetrics metric = new DisplayMetrics();
+
+	/**
+	 * @author zhangmengjie
+	 * @return 序列号 SerialNumber
+	 */
+	public String SerialNumber() {
+
+		return android.os.Build.SERIAL;
+	}
+
+	/**
+	 * @author zhangmengjie
+	 * @return MD5加密自定义SerialNum
+	 */
+	public String getSerial() {
+		String s;
+		if (EduFoundUtil.isEmpty(EduFoundUtil.getMacAddress())) {
+			s = "35" + Build.BOARD.length() + Build.BRAND.length() + Build.CPU_ABI.length() + Build.DEVICE.length()
+					+ Build.DISPLAY.length() + Build.HOST.length() + Build.ID.length() + Build.MANUFACTURER.length()
+					+ Build.MODEL.length() + Build.PRODUCT.length() + Build.TAGS.length() + Build.TYPE.length()
+					+ Build.USER.length() + EduFoundUtil.getEthernetMac();
+		} else {
+			s = "35" + Build.BOARD.length() + Build.BRAND.length() + Build.CPU_ABI.length() + Build.DEVICE.length()
+					+ Build.DISPLAY.length() + Build.HOST.length() + Build.ID.length() + Build.MANUFACTURER.length()
+					+ Build.MODEL.length() + Build.PRODUCT.length() + Build.TAGS.length() + Build.TYPE.length()
+					+ Build.USER.length() + EduFoundUtil.getMacAddress();
+		}
+
+		return md5Encode(s);
+	}
+
+	public int getWidth(Activity context) {
+		context.getWindowManager().getDefaultDisplay().getMetrics(metric);
+		return metric.widthPixels; // 屏幕宽度(像素)
+	}
+
+	public int getHeight(Activity context) {
+		context.getWindowManager().getDefaultDisplay().getMetrics(metric);
+		return metric.heightPixels; // 屏幕高度(像素)
+	}
+
+	public float getDensity(Activity context) {
+		context.getWindowManager().getDefaultDisplay().getMetrics(metric);
+		return metric.density; // 屏幕密度(0.75 / 1.0 / 1.5)
+	}
+
+	public int getDensityDpi(Activity context) {
+		context.getWindowManager().getDefaultDisplay().getMetrics(metric);
+		return metric.densityDpi; // // 屏幕密度DPI(120 / 160 / 240)
+	}
+
+	// md5加密
+	public String md5Encode(String inStr) {
+		MessageDigest md5 = null;
+		try {
+			md5 = MessageDigest.getInstance("MD5");
+		} catch (Exception e) {
+			System.out.println(e.toString());
+			e.printStackTrace();
+			return "";
+		}
+
+		byte[] byteArray = null;
+		try {
+			byteArray = inStr.getBytes("UTF-8");
+		} catch (UnsupportedEncodingException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+		byte[] md5Bytes = md5.digest(byteArray);
+		StringBuffer hexValue = new StringBuffer();
+		for (int i = 0; i < md5Bytes.length; i++) {
+			int val = ((int) md5Bytes[i]) & 0xff;
+			if (val < 16) {
+				hexValue.append("0");
+			}
+			hexValue.append(Integer.toHexString(val));
+		}
+		return hexValue.toString();
+	}
+
+	/**
+	 * @author zhangmengjie
+	 * @return VersionCode
+	 */
+	public String getVersionCode(Context context) {
+		PackageManager packageManager = context.getPackageManager();
+		PackageInfo packageInfo;
+		String versionCode = "";
+		try {
+			packageInfo = packageManager.getPackageInfo(context.getPackageName(), 0);
+			versionCode = packageInfo.versionCode + "";
+		} catch (PackageManager.NameNotFoundException e) {
+			e.printStackTrace();
+		}
+		return versionCode;
+	}
+
+	/**
+	 * @author zhangmengjie
+	 * @return VersionName
+	 *
+	 */
+	public String getVersionName(Context context) {
+		PackageManager packageManager = context.getPackageManager();
+		PackageInfo packageInfo;
+		String versionName = "";
+		try {
+			packageInfo = packageManager.getPackageInfo(context.getPackageName(), 0);
+			versionName = packageInfo.versionName;
+		} catch (PackageManager.NameNotFoundException e) {
+			e.printStackTrace();
+		}
+		return versionName;
+	}
+
+	/**
+	 * 获取当前手机系统语言。
+	 *
+	 * @return 返回当前系统语言。例如:当前设置的是“中文-中国”,则返回“zh-CN”
+	 */
+	public String getSystemLanguage() {
+		return Locale.getDefault().getLanguage();
+	}
+
+	/**
+	 * 获取当前系统上的语言列表(Locale列表)
+	 *
+	 * @return 语言列表
+	 */
+	public Locale[] getSystemLanguageList() {
+		return Locale.getAvailableLocales();
+	}
+
+	/**
+	 * 获取当前手机系统版本号
+	 *
+	 * @return 系统版本号
+	 */
+	public String getSystemVersion() {
+		return android.os.Build.VERSION.RELEASE;
+	}
+
+	/**
+	 * 获取手机型号
+	 *
+	 * @return 手机型号
+	 */
+	public String getSystemModel() {
+		return android.os.Build.MODEL;
+	}
+
+	/**
+	 * 获取手机厂商
+	 *
+	 * @return 手机厂商
+	 */
+	public String getDeviceBrand() {
+		return android.os.Build.BRAND;
+	}
+
+	/**
+	 * 获取手机IMEI(需要“android.permission.READ_PHONE_STATE”权限)
+	 * 
+	 * @return 手机IMEI
+	 */
+	public String getIMEI(Context ctx) {
+		TelephonyManager tm = (TelephonyManager) ctx.getSystemService(Activity.TELEPHONY_SERVICE);
+		if (tm != null) {
+			return tm.getDeviceId();
+		}
+		return null;
+	}
+
+}

+ 54 - 0
app/src/main/java/com/edufound/mobile/util/DeviceUuidFactory.java

@@ -0,0 +1,54 @@
+package com.edufound.mobile.util;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.provider.Settings;
+import android.telephony.TelephonyManager;
+
+import java.io.UnsupportedEncodingException;
+import java.util.UUID;
+
+public class DeviceUuidFactory {
+    public static final String UUID_SPKEY = "uuid";
+    protected static UUID uuid;
+
+    public DeviceUuidFactory(Context context) {
+        if (uuid == null) {
+            synchronized (DeviceUuidFactory.class) {
+                if (uuid == null) {
+                    try {
+                        final String androidId = Settings.Secure.getString(
+                                context.getContentResolver(), Settings.Secure.ANDROID_ID);
+                        if (!"9774d56d682e549c".equals(androidId)) {
+                            uuid = UUID.nameUUIDFromBytes(androidId.getBytes("utf8"));
+                        } else {
+                            @SuppressLint("MissingPermission") final String deviceId = ((TelephonyManager) context
+                                    .getSystemService(Context.TELEPHONY_SERVICE))
+                                    .getDeviceId();
+                            uuid = deviceId != null ? UUID.nameUUIDFromBytes(deviceId
+                                    .getBytes("utf8")) : UUID.randomUUID();
+                            try {
+                            } catch (Exception e) {
+                                e.printStackTrace();
+                            }
+                        }
+                    } catch (UnsupportedEncodingException e) {
+                        throw new RuntimeException(e);
+                    }
+                }
+                SPutil.setPrefString(context, UUID_SPKEY, uuid.toString());
+            }
+        }
+    }
+
+
+    /**
+     * @return UUID
+     */
+    public static UUID getUuid() {
+        if (uuid == null || uuid.equals("") || uuid.equals("null")) {
+            return null;
+        }
+        return uuid;
+    }
+}

+ 20 - 0
app/src/main/java/com/edufound/mobile/util/DrawableUtil.java

@@ -0,0 +1,20 @@
+package com.edufound.mobile.util;
+
+import android.app.Activity;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.drawable.BitmapDrawable;
+
+public class DrawableUtil {
+    public static BitmapDrawable getNewDrawable(Activity context, int restId, int dstWidth, int dstHeight) {
+        Bitmap Bmp = BitmapFactory.decodeResource(
+                context.getResources(), restId);
+        Bitmap bmp = Bmp.createScaledBitmap(Bmp, dstWidth, dstHeight, true);
+        BitmapDrawable d = new BitmapDrawable(bmp);
+        Bitmap bitmap = d.getBitmap();
+        if (bitmap.getDensity() == Bitmap.DENSITY_NONE) {
+            d.setTargetDensity(context.getResources().getDisplayMetrics());
+        }
+        return d;
+    }
+}

+ 691 - 0
app/src/main/java/com/edufound/mobile/util/EduFoundUtil.java

@@ -0,0 +1,691 @@
+package com.edufound.mobile.util;
+
+import android.app.Activity;
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.net.Uri;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+import android.os.Build;
+import android.text.Editable;
+import android.text.Selection;
+import android.text.TextWatcher;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.EditText;
+import android.widget.TextView;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.net.HttpURLConnection;
+import java.net.InetAddress;
+import java.net.MalformedURLException;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.net.URL;
+import java.security.MessageDigest;
+import java.util.Enumeration;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class EduFoundUtil {
+
+    /**
+     * getVersionCode 得到名称
+     */
+    public static String getVersion(Context context)// 得到版本
+    {
+        try {
+            PackageInfo pi = context.getPackageManager()
+                    .getPackageInfo(context.getPackageName(), 0);
+            return pi.versionName;
+        } catch (NameNotFoundException e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    /**
+     * getVersionCode 得到版本号
+     */
+    public static int getVersionCode(Context context) {
+        try {
+            PackageInfo pi = context.getPackageManager()
+                    .getPackageInfo(context.getPackageName(), 0);
+            return pi.versionCode;
+        } catch (NameNotFoundException e) {
+            e.printStackTrace();
+            return 0;
+        }
+    }
+
+    private static String parseByte(byte b) {
+        String s = "00" + Integer.toHexString(b) + ":";
+        return s.substring(s.length() - 3);
+    }
+
+    public static void openFile(Context context, File file) {
+        // TODO Auto-generated method stub
+        String cmd = "chmod 777 " + file;
+        try {
+            Runtime.getRuntime().exec(cmd);
+            Log.e("OpenFile", file.getName());
+            Intent intent = new Intent();
+            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            intent.setAction(android.content.Intent.ACTION_VIEW);
+            intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
+            context.startActivity(intent);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+    }
+
+    /**
+     * long转换成String时间
+     */
+    public static String getTime(int mss) {
+        int hours = (mss / (1000 * 60 * 60));
+        int minutes = (mss - hours * (1000 * 60 * 60)) / (1000 * 60);
+        int m = hours * 60 + minutes;
+        int seconds = (mss - hours * (1000 * 60 * 60) - minutes * (1000 * 60)) / 1000;
+        return String.format("%02d:%02d", m, seconds);
+    }
+
+    /**
+     * 得到宽高缩放比
+     */
+    public static float initDesignSize(Context context, int screenWidth, int screenHeight) {
+        int designWidth = 1280;
+        int designHeight = 720;
+        float ds = 1.0f * designWidth / designHeight;
+        float ts = 1.0f * screenWidth / screenHeight;
+        if (ds >= ts) {
+            int targetWidth = screenWidth;
+            float designScale = 1.0f * targetWidth / designWidth;
+            return designScale;
+        } else {
+            int targetHeight = screenHeight;
+            float designScale = 1.0f * targetHeight / designHeight;
+            return designScale;
+        }
+    }
+
+    /**
+     * 设置dpi缩放比
+     */
+    public 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();
+    }
+
+    public static String getMacAddress() {
+        String result = "";
+        String Mac = "";
+        result = callCmd("busybox ifconfig", "HWaddr");
+
+        if (result == null) {
+            return "网络出错,请检查网络";
+        }
+        if (result.length() > 0 && result.contains("HWaddr")) {
+            Mac = result.substring(result.indexOf("HWaddr") + 6, result.length() - 1);
+            if (Mac.length() > 1) {
+                result = Mac.toLowerCase();
+            }
+        }
+        return result.trim();
+    }
+
+    public static String getEthernetMac() {
+        String mac = null;
+        try {
+            Process p = Runtime.getRuntime().exec("cat /sys/class/net/eth0/address");
+            InputStream is = p.getInputStream();
+            InputStreamReader isr = new InputStreamReader(is);
+            BufferedReader bf = new BufferedReader(isr);
+            String line = null;
+            if ((line = bf.readLine()) != null) {
+                mac = line;
+            }
+            bf.close();
+            isr.close();
+            is.close();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return mac;
+    }
+
+    public static String callCmd(String cmd, String filter) {
+        String result = "";
+        String line = "";
+        try {
+            Process proc = Runtime.getRuntime().exec(cmd);
+            InputStreamReader is = new InputStreamReader(proc.getInputStream());
+            BufferedReader br = new BufferedReader(is);
+            // 执行命令cmd,只取结果中含有filter的这一行
+            while ((line = br.readLine()) != null && line.contains(filter) == false) {
+                // result += line;
+                Log.i("test", "line: " + line);
+            }
+            result = line;
+            Log.i("test", "result: " + result);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return result;
+
+    }
+
+
+    public static void runCmd(String cmd) {
+        Runtime mRuntime = Runtime.getRuntime();
+        try {
+            //Process中封装了返回的结果和执行错误的结果
+            Process mProcess = mRuntime.exec(cmd);
+            BufferedReader mReader = new BufferedReader(new InputStreamReader(mProcess.getInputStream()));
+            StringBuffer mRespBuff = new StringBuffer();
+            char[] buff = new char[1024];
+            int ch = 0;
+            while ((ch = mReader.read(buff)) != -1) {
+                mRespBuff.append(buff, 0, ch);
+            }
+            mReader.close();
+            Logger.DebugE(mRespBuff.toString());
+        } catch (IOException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 根据wifi信息获取本地mac
+     *
+     * @param context
+     * @return
+     */
+    public static String getLocalMacAddressFromWifiInfo(Context context) {
+        WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+        WifiInfo winfo = wifi.getConnectionInfo();
+        String mac = winfo.getMacAddress();
+        return mac;
+    }
+
+    // 有线ip得mac
+    public static String getLocalMacAddressFromIp(Context context) {
+        String mac_s = "";
+        String macAddress = "";
+        try {
+            byte[] mac;
+            NetworkInterface ne = NetworkInterface.getByInetAddress(InetAddress
+                    .getByName(getLocalIpAddress()));
+            mac = ne.getHardwareAddress();
+            mac_s = bytes2hex02(mac);
+
+            macAddress = mac_s.substring(0, 2) + ":" + mac_s.substring(2, 4) + ":"
+                    + mac_s.substring(4, 6) + ":" + mac_s.substring(6, 8) + ":"
+                    + mac_s.substring(8, 10) + ":" + mac_s.substring(10, 12);
+            return macAddress;
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return macAddress;
+
+    }
+
+    /**
+     * 二进制转十六进制
+     *
+     * @param
+     * @return
+     */
+    public static String bytes2hex02(byte[] bytes) {
+        StringBuilder sb = new StringBuilder();
+        String tmp = null;
+        for (byte b : bytes) {
+            // 将每个字节与0xFF进行与运算,然后转化为10进制,然后借助于Integer再转化为16进制
+            tmp = Integer.toHexString(0xFF & b);
+            if (tmp.length() == 1)// 每个字节8为,转为16进制标志,2个16进制位
+            {
+                tmp = "0" + tmp;
+            }
+            sb.append(tmp);
+        }
+
+        return sb.toString();
+
+    }
+
+    // 获得ip地址
+    public static String getLocalIpAddress() {
+        try {
+            for (Enumeration en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {
+                NetworkInterface intf = (NetworkInterface) en.nextElement();
+                for (Enumeration enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
+                    InetAddress inetAddress = (InetAddress) enumIpAddr.nextElement();
+                    if (!inetAddress.isLoopbackAddress()) {
+                        return inetAddress.getHostAddress().toString();
+                    }
+                }
+            }
+        } catch (SocketException ex) {
+            ex.printStackTrace();
+        }
+        return null;
+    }
+
+    /**
+     * 判断String是否为空
+     *
+     * @return boolean是否为空
+     */
+    public static Boolean isEmpty(String s) {
+        if (s == null || s.length() == 0) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    public static String getIP(String ip) {
+        StringBuffer s = new StringBuffer();
+        String ss = null;
+        Process p;
+        try {
+            p = Runtime.getRuntime().exec("/system/bin/ping " + ip);
+            BufferedReader buf = new BufferedReader(new InputStreamReader(p.getInputStream()));
+
+            String str = new String();
+
+            // 读出所有信息并显示
+            while ((str = buf.readLine()) != null && s.length() < 100) {
+                str = str + "\r\n";
+                s.append(str);
+            }
+            ss = EduFoundUtil.getTelnum(s.toString()).split(",")[0];
+        } catch (Exception e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+        return ss;
+    }
+
+    public static void saveIsHavePhone(Context context, boolean isHavephone) {
+        SharedPreferences preferences = context.getSharedPreferences("isHavePhone",
+                Context.MODE_PRIVATE);
+        Editor editor = preferences.edit();
+        editor.putBoolean("isHadPhone", isHavephone);
+        editor.commit();
+    }
+
+    public static boolean getIsHavePhone(Context context) {
+        SharedPreferences preferences = context.getSharedPreferences("isHavePhone",
+                Context.MODE_PRIVATE);
+        boolean isHave = preferences.getBoolean("isHadPhone", false);
+        return isHave;
+
+    }
+
+    public static boolean isMobile(String str) {
+        Pattern p = null;
+        Matcher m = null;
+        boolean b = false;
+        p = Pattern.compile("^[1][3,4,5,8][0-9]{9}$"); // 验证手机号
+        m = p.matcher(str);
+        b = m.matches();
+        return b;
+    }
+
+    public static String getTelnum(String sParam) {
+        if (sParam.length() <= 0)
+            return "";
+        // Pattern pattern = Pattern.compile("(1|[0-9])([0-9])\\d{9}$*");
+        // Pattern pattern =
+        // Pattern.compile("((13[0-9])|(14[7])|(15[0-9])|17[0-9]|(18[0-9]))\\d{8}$*");
+        Pattern pattern = Pattern
+                .compile("(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]).(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0).(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0).(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])$*");
+        Matcher matcher = pattern.matcher(sParam);
+        StringBuffer bf = new StringBuffer();
+        while (matcher.find()) {
+            bf.append(matcher.group()).append(",");
+        }
+        int len = bf.length();
+        if (len > 0) {
+            bf.deleteCharAt(len - 1);
+        }
+        return bf.toString();
+    }
+
+    public static String getSerial() {
+        String s;
+        if (EduFoundUtil.isEmpty(EduFoundUtil.getMacAddress())) {
+            s = "35" + Build.BOARD.length() + Build.BRAND.length() + Build.CPU_ABI.length()
+                    + Build.DEVICE.length() + Build.DISPLAY.length() + Build.HOST.length()
+                    + Build.ID.length() + Build.MANUFACTURER.length() + Build.MODEL.length()
+                    + Build.PRODUCT.length() + Build.TAGS.length() + Build.TYPE.length()
+                    + Build.USER.length() + EduFoundUtil.getEthernetMac();
+        } else {
+            s = "35" + Build.BOARD.length() + Build.BRAND.length() + Build.CPU_ABI.length()
+                    + Build.DEVICE.length() + Build.DISPLAY.length() + Build.HOST.length()
+                    + Build.ID.length() + Build.MANUFACTURER.length() + Build.MODEL.length()
+                    + Build.PRODUCT.length() + Build.TAGS.length() + Build.TYPE.length()
+                    + Build.USER.length() + EduFoundUtil.getMacAddress();
+        }
+
+        Logger.e("serial=======" + s);
+        return md5Encode(s);
+    }
+
+    // md5加密
+    public static String md5Encode(String inStr) {
+        MessageDigest md5 = null;
+        try {
+            md5 = MessageDigest.getInstance("MD5");
+        } catch (Exception e) {
+            System.out.println(e.toString());
+            e.printStackTrace();
+            return "";
+        }
+
+        byte[] byteArray = null;
+        try {
+            byteArray = inStr.getBytes("UTF-8");
+        } catch (UnsupportedEncodingException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+        byte[] md5Bytes = md5.digest(byteArray);
+        StringBuffer hexValue = new StringBuffer();
+        for (int i = 0; i < md5Bytes.length; i++) {
+            int val = ((int) md5Bytes[i]) & 0xff;
+            if (val < 16) {
+                hexValue.append("0");
+            }
+            hexValue.append(Integer.toHexString(val));
+        }
+        return hexValue.toString();
+    }
+
+    public static void savePlayMode(Context context, String value) {
+        SharedPreferences preferences = context.getSharedPreferences("PlayMode",
+                Context.MODE_PRIVATE);
+        Editor editor = preferences.edit();
+        editor.putString("playmode", value);
+        editor.commit();
+    }
+
+    public static String getPlayMode(Context context) {
+        SharedPreferences preferences = context.getSharedPreferences("PlayMode",
+                Context.MODE_PRIVATE);
+        String playMode = preferences.getString("playmode", "default");
+        return playMode;
+
+    }
+
+    public static void saveStuNo(Context context, String value) {
+        SharedPreferences preferences = context.getSharedPreferences("STUNO", Context.MODE_PRIVATE);
+        Editor editor = preferences.edit();
+        editor.putString("stu_no", value);
+        editor.commit();
+    }
+
+    public static String getStuNo(Context context) {
+        SharedPreferences preferences = context.getSharedPreferences("STUNO", Context.MODE_PRIVATE);
+        String stu_no = preferences.getString("stu_no", "");
+        return stu_no;
+
+    }
+
+    /**
+     * 银行卡四位加空格
+     *
+     * @param mEditText
+     */
+    public static void bankCardNumAddSpace(final EditText mEditText) {
+        mEditText.addTextChangedListener(new TextWatcher() {
+            int beforeTextLength = 0;
+            int onTextLength = 0;
+            boolean isChanged = false;
+
+            int location = 0;// 记录光标的位置
+            private char[] tempChar;
+            private StringBuffer buffer = new StringBuffer();
+            int konggeNumberB = 0;
+
+            @Override
+            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+                beforeTextLength = s.length();
+                if (buffer.length() > 0) {
+                    buffer.delete(0, buffer.length());
+                }
+                konggeNumberB = 0;
+                for (int i = 0; i < s.length(); i++) {
+                    if (s.charAt(i) == ' ') {
+                        konggeNumberB++;
+                    }
+                }
+            }
+
+            @Override
+            public void onTextChanged(CharSequence s, int start, int before, int count) {
+                onTextLength = s.length();
+                buffer.append(s.toString());
+                if (onTextLength == beforeTextLength || onTextLength <= 3 || isChanged) {
+                    isChanged = false;
+                    return;
+                }
+                isChanged = true;
+            }
+
+            @Override
+            public void afterTextChanged(Editable s) {
+                if (isChanged) {
+                    location = mEditText.getSelectionEnd();
+                    int index = 0;
+                    while (index < buffer.length()) {
+                        if (buffer.charAt(index) == ' ') {
+                            buffer.deleteCharAt(index);
+                        } else {
+                            index++;
+                        }
+                    }
+
+                    index = 0;
+                    int konggeNumberC = 0;
+                    while (index < buffer.length()) {
+                        if ((index == 4 || index == 9 || index == 14 || index == 19)) {
+                            buffer.insert(index, ' ');
+                            konggeNumberC++;
+                        }
+                        index++;
+                    }
+
+                    if (konggeNumberC > konggeNumberB) {
+                        location += (konggeNumberC - konggeNumberB);
+                    }
+
+                    tempChar = new char[buffer.length()];
+                    buffer.getChars(0, buffer.length(), tempChar, 0);
+                    String str = buffer.toString();
+                    if (location > str.length()) {
+                        location = str.length();
+                    } else if (location < 0) {
+                        location = 0;
+                    }
+
+                    mEditText.setText(str);
+                    Editable etable = mEditText.getText();
+                    Selection.setSelection(etable, location);
+                    isChanged = false;
+                }
+            }
+        });
+    }
+
+    public static Bitmap returnBitMap(String url) {
+
+        URL myFileUrl = null;
+        Bitmap bitmap = null;
+        try {
+            myFileUrl = new URL(url);
+        } catch (MalformedURLException e) {
+            e.printStackTrace();
+        }
+        try {
+            HttpURLConnection conn = (HttpURLConnection) myFileUrl.openConnection();
+            conn.setDoInput(true);
+            conn.connect();
+            InputStream is = conn.getInputStream();
+            bitmap = BitmapFactory.decodeStream(is);
+            is.close();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return bitmap;
+    }
+
+    public static void bankCardNumAddSpace1(final TextView mEditText) {
+        mEditText.addTextChangedListener(new TextWatcher() {
+            int beforeTextLength = 0;
+            int onTextLength = 0;
+            boolean isChanged = false;
+
+            int location = 0;// 记录光标的位置
+            private char[] tempChar;
+            private StringBuffer buffer = new StringBuffer();
+            int konggeNumberB = 0;
+
+            @Override
+            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+                beforeTextLength = s.length();
+                if (buffer.length() > 0) {
+                    buffer.delete(0, buffer.length());
+                }
+                konggeNumberB = 0;
+                for (int i = 0; i < s.length(); i++) {
+                    if (s.charAt(i) == ' ') {
+                        konggeNumberB++;
+                    }
+                }
+            }
+
+            @Override
+            public void onTextChanged(CharSequence s, int start, int before, int count) {
+                onTextLength = s.length();
+                buffer.append(s.toString());
+                if (onTextLength == beforeTextLength || onTextLength <= 3 || isChanged) {
+                    isChanged = false;
+                    return;
+                }
+                isChanged = true;
+            }
+
+            @Override
+            public void afterTextChanged(Editable s) {
+                if (isChanged) {
+                    location = mEditText.getSelectionEnd();
+                    int index = 0;
+                    while (index < buffer.length()) {
+                        if (buffer.charAt(index) == ' ') {
+                            buffer.deleteCharAt(index);
+                        } else {
+                            index++;
+                        }
+                    }
+
+                    index = 0;
+                    int konggeNumberC = 0;
+                    while (index < buffer.length()) {
+                        if ((index == 4 || index == 9 || index == 14 || index == 19)) {
+                            buffer.insert(index, ' ');
+                            konggeNumberC++;
+                        }
+                        index++;
+                    }
+
+                    if (konggeNumberC > konggeNumberB) {
+                        location += (konggeNumberC - konggeNumberB);
+                    }
+
+                    tempChar = new char[buffer.length()];
+                    buffer.getChars(0, buffer.length(), tempChar, 0);
+                    String str = buffer.toString();
+                    if (location > str.length()) {
+                        location = str.length();
+                    } else if (location < 0) {
+                        location = 0;
+                    }
+
+                    mEditText.setText(str);
+                    // Editable etable = mEditText.getText();
+                    // Selection.setSelection(etable, location);
+                    isChanged = false;
+                }
+            }
+        });
+    }
+
+
+    public static void restartApplication(Context context) {
+        Intent intent = context.getPackageManager()
+                .getLaunchIntentForPackage(context.getPackageName());
+        PendingIntent restartIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_ONE_SHOT);
+        AlarmManager mgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+        mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1000, restartIntent); // 1秒钟后重启应用
+        System.exit(0);
+    }
+
+    public static void setHideVirtualKey(Window window) {
+        //保持布局状态
+        int uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
+                //布局位于状态栏下方
+                View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
+                //全屏
+                View.SYSTEM_UI_FLAG_FULLSCREEN |
+                //隐藏导航栏
+                View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
+                View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
+        if (Build.VERSION.SDK_INT >= 19) {
+            uiOptions |= 0x00001000;
+        } else {
+            uiOptions |= View.SYSTEM_UI_FLAG_LOW_PROFILE;
+        }
+        window.getDecorView().setSystemUiVisibility(uiOptions);
+    }
+
+    public static void openFullScreenModel(Activity activity) {
+        activity.requestWindowFeature(Window.FEATURE_NO_TITLE);
+        WindowManager.LayoutParams lp = activity.getWindow().getAttributes();
+        lp.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
+        activity.getWindow().setAttributes(lp);
+        View decorView = activity.getWindow().getDecorView();
+        int systemUiVisibility = decorView.getSystemUiVisibility();
+        int flags = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+                | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
+                | View.SYSTEM_UI_FLAG_FULLSCREEN;
+        systemUiVisibility |= flags;
+        activity.getWindow().getDecorView().setSystemUiVisibility(systemUiVisibility);
+    }
+
+}

+ 151 - 0
app/src/main/java/com/edufound/mobile/util/LiuHaiScreenUtil.java

@@ -0,0 +1,151 @@
+package com.edufound.mobile.util;
+
+import android.app.Activity;
+import android.view.DisplayCutout;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowInsets;
+import android.view.WindowManager;
+
+public class LiuHaiScreenUtil {
+
+//    /**
+//     * 判断是否是刘海屏
+//     *
+//     * @return
+//     */
+//    public static boolean hasNotchScreen(Activity activity) {
+//        if (getInt("ro.miui.notch", activity) == 1 || hasNotchAtHuawei() || hasNotchAtOPPO()
+//                || hasNotchAtVivo() || isAndroidP(activity) != null) { //TODO 各种品牌
+//            return true;
+//        }
+//
+//        return false;
+//    }
+
+    /**
+     * Android P 刘海屏判断
+     *
+     * @param activity
+     * @return
+     */
+    public static DisplayCutout isAndroidP(Activity activity) {
+        View decorView = activity.getWindow().getDecorView();
+        if (decorView != null && android.os.Build.VERSION.SDK_INT >= 28) {
+            WindowInsets windowInsets = decorView.getRootWindowInsets();
+            if (windowInsets != null)
+                return windowInsets.getDisplayCutout();
+        }
+        return null;
+    }
+
+//    /**
+//     * 小米刘海屏判断.
+//     * @return 0 if it is not notch ; return 1 means notch
+//     * @throws IllegalArgumentException if the key exceeds 32 characters
+//     */
+//    public static int getInt(String key,Activity activity) {
+//        int result = 0;
+//        if (isXiaomi()){
+//            try {
+//                ClassLoader classLoader = activity.getClassLoader();
+//                @SuppressWarnings("rawtypes")
+//                Class SystemProperties = classLoader.loadClass("android.os.SystemProperties");
+//                //参数类型
+//                @SuppressWarnings("rawtypes")
+//                Class[] paramTypes = new Class[2];
+//                paramTypes[0] = String.class;
+//                paramTypes[1] = int.class;
+//                Method getInt = SystemProperties.getMethod("getInt", paramTypes);
+//                //参数
+//                Object[] params = new Object[2];
+//                params[0] = new String(key);
+//                params[1] = new Integer(0);
+//                result = (Integer) getInt.invoke(SystemProperties, params);
+//
+//            } catch (ClassNotFoundException e) {
+//                e.printStackTrace();
+//            } catch (NoSuchMethodException e) {
+//                e.printStackTrace();
+//            } catch (IllegalAccessException e) {
+//                e.printStackTrace();
+//            } catch (IllegalArgumentException e) {
+//                e.printStackTrace();
+//            } catch (InvocationTargetException e) {
+//                e.printStackTrace();
+//            }
+//        }
+//        return result;
+//    }
+
+//    /**
+//     * 华为刘海屏判断
+//     * @return
+//     */
+//    public static boolean hasNotchAtHuawei() {
+//        boolean ret = false;
+//        try {
+//            ClassLoader classLoader = StaticContext.CONTEXT.getClassLoader();
+//            Class HwNotchSizeUtil = classLoader.loadClass("com.huawei.android.util.HwNotchSizeUtil");
+//            Method get = HwNotchSizeUtil.getMethod("hasNotchInScreen");
+//            ret = (boolean) get.invoke(HwNotchSizeUtil);
+//        } catch (ClassNotFoundException e) {
+//            Logger.e("hasNotchAtHuawei ClassNotFoundException");
+//        } catch (NoSuchMethodException e) {
+//            Logger.e("hasNotchAtHuawei NoSuchMethodException");
+//        } catch (Exception e) {
+//            Logger.e( "hasNotchAtHuawei Exception");
+//        } finally {
+//            return ret;
+//        }
+//    }
+
+//    public static final int VIVO_NOTCH = 0x00000020;//是否有刘海
+//    public static final int VIVO_FILLET = 0x00000008;//是否有圆角
+
+//    /**
+//     * VIVO刘海屏判断
+//     * @return
+//     */
+//    public static boolean hasNotchAtVivo() {
+//        boolean ret = false;
+//        try {
+//            ClassLoader classLoader = StaticContext.CONTEXT.getClassLoader();
+//            Class FtFeature = classLoader.loadClass("android.util.FtFeature");
+//            Method method = FtFeature.getMethod("isFeatureSupport", int.class);
+//            ret = (boolean) method.invoke(FtFeature, VIVO_NOTCH);
+//        } catch (ClassNotFoundException e) {
+//            Logger.e( "hasNotchAtVivo ClassNotFoundException");
+//        } catch (NoSuchMethodException e) {
+//            Logger.e(  "hasNotchAtVivo NoSuchMethodException");
+//        } catch (Exception e) {
+//            Logger.e(  "hasNotchAtVivo Exception");
+//        } finally {
+//            return ret;
+//        }
+//    }
+
+
+//    /**
+//     * OPPO刘海屏判断
+//     * @return
+//     */
+//    public static boolean hasNotchAtOPPO() {
+//        return  StaticContext.CONTEXT.getPackageManager().hasSystemFeature("com.oppo.feature.screen.heteromorphism");
+//    }
+
+
+    public static void openFullScreenModel(Activity activity) {
+//        activity.requestWindowFeature(Window.FEATURE_NO_TITLE);
+        WindowManager.LayoutParams lp = activity.getWindow().getAttributes();
+        lp.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
+        activity.getWindow().setAttributes(lp);
+        View decorView = activity.getWindow().getDecorView();
+        int systemUiVisibility = decorView.getSystemUiVisibility();
+        int flags = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+                | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
+                | View.SYSTEM_UI_FLAG_FULLSCREEN;
+        systemUiVisibility |= flags;
+        activity.getWindow().getDecorView().setSystemUiVisibility(systemUiVisibility);
+    }
+}

+ 19 - 0
app/src/main/java/com/edufound/mobile/util/Logger.java

@@ -0,0 +1,19 @@
+package com.edufound.mobile.util;
+
+import android.util.Log;
+
+public class Logger {
+
+    static String TAG = "com.edufound.mobile";
+
+    public static void e(String message) {
+        Log.e(TAG, message);
+    }
+
+    public static void DebugE(String message) {
+        if (ContextUtil.isIsDebug()) {
+            Log.e(TAG, message);
+        }
+    }
+
+}

+ 142 - 0
app/src/main/java/com/edufound/mobile/util/NotificationUtil.java

@@ -0,0 +1,142 @@
+package com.edufound.mobile.util;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.AppOpsManager;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.net.Uri;
+import android.os.Build;
+import android.support.annotation.RequiresApi;
+import android.support.v4.app.NotificationManagerCompat;
+import android.view.View;
+import android.widget.TextView;
+
+import com.edufound.mobile.R;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+public class NotificationUtil {
+
+
+    public static void choseNotification(Activity activity) {
+        //如果是新应用,查询权限并且询问
+        if (SPutil.getPrefInt(activity, SPutil.notificationType, 0) == 0) {
+            if (NotificationUtil.areNotificationsEnabled(activity)) {
+                //有权限
+                SPutil.setPrefInt(activity, SPutil.notificationType, SPutil.NOTIFICATION_OPEN);
+            } else {
+                //没权限
+                SPutil.setPrefInt(activity, SPutil.notificationType, SPutil.NOTIFICATION_CLOSE);
+                NotificationUtil.showDialog(activity);
+            }
+        } else {
+            //不是第一次新应用,如果设置了有权限,就设置系统默认的权限,不提示
+            if (NotificationUtil.areNotificationsEnabled(activity)) {
+                //有权限
+                SPutil.setPrefInt(activity, SPutil.notificationType, SPutil.NOTIFICATION_OPEN);
+            } else {
+                //没权限
+                SPutil.setPrefInt(activity, SPutil.notificationType, SPutil.NOTIFICATION_CLOSE);
+            }
+        }
+    }
+
+
+    private static boolean areNotificationsEnabled(Context context) {
+        NotificationManagerCompat.from(context).areNotificationsEnabled();
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
+            return true;
+        }
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
+            return isEnableV19(context);
+        } else {
+            return isEnableV26(context);
+        }
+    }
+
+
+    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
+    private static boolean isEnableV19(Context context) {
+        final String CHECK_OP_NO_THROW = "checkOpNoThrow";
+        final String OP_POST_NOTIFICATION = "OP_POST_NOTIFICATION";
+        AppOpsManager mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
+        ApplicationInfo appInfo = context.getApplicationInfo();
+        String pkg = context.getApplicationContext().getPackageName();
+        int uid = appInfo.uid;
+        Class appOpsClass = null; /* Context.APP_OPS_MANAGER */
+        try {
+            appOpsClass = Class.forName(AppOpsManager.class.getName());
+            Method checkOpNoThrowMethod = appOpsClass.getMethod(CHECK_OP_NO_THROW, Integer.TYPE, Integer.TYPE, String.class);
+            Field opPostNotificationValue = appOpsClass.getDeclaredField(OP_POST_NOTIFICATION);
+            int value = (int) opPostNotificationValue.get(Integer.class);
+            return ((int) checkOpNoThrowMethod.invoke(mAppOps, value, uid, pkg) == AppOpsManager.MODE_ALLOWED);
+        } catch (ClassNotFoundException e) {
+        } catch (NoSuchMethodException e) {
+        } catch (NoSuchFieldException e) {
+        } catch (InvocationTargetException e) {
+        } catch (IllegalAccessException e) {
+        } catch (Exception e) {
+        }
+        return false;
+    }
+
+
+    private static boolean isEnableV26(Context context) {
+        ApplicationInfo appInfo = context.getApplicationInfo();
+        String pkg = context.getApplicationContext().getPackageName();
+        int uid = appInfo.uid;
+        try {
+            NotificationManager notificationManager = (NotificationManager)
+                    context.getSystemService(Context.NOTIFICATION_SERVICE);
+            Method sServiceField = notificationManager.getClass().getDeclaredMethod("getService");
+            sServiceField.setAccessible(true);
+            Object sService = sServiceField.invoke(notificationManager);
+
+            Method method = sService.getClass().getDeclaredMethod("areNotificationsEnabledForPackage"
+                    , String.class, Integer.TYPE);
+            method.setAccessible(true);
+            return (boolean) method.invoke(sService, pkg, uid);
+        } catch (Exception e) {
+            return true;
+        }
+    }
+
+
+    private static void showDialog(final Activity act) {
+        AlertDialog.Builder builder = new AlertDialog.Builder(act)
+//                .setIcon(R.mipmap.ic_launcher)
+                .setTitle("提示")
+                .setMessage("检测到您没有打开通知权限,是否去打开")
+                .setPositiveButton("确定", new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialogInterface, int i) {
+                        dialogInterface.cancel();
+                        Intent localIntent = new Intent();
+                        localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                        if (Build.VERSION.SDK_INT >= 9) {
+                            localIntent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
+                            localIntent.setData(Uri.fromParts("package", act.getPackageName(), null));
+                        } else if (Build.VERSION.SDK_INT <= 8) {
+                            localIntent.setAction(Intent.ACTION_VIEW);
+                            localIntent.setClassName("com.android.settings",
+                                    "com.android.settings.InstalledAppDetails");
+                            localIntent.putExtra("com.android.settings.ApplicationPkgName",
+                                    act.getPackageName());
+                        }
+                        act.startActivity(localIntent);
+                    }
+                }).setNegativeButton("取消", new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int i) {
+                        dialog.cancel();
+                    }
+                });
+        builder.create().show();
+    }
+}

+ 147 - 0
app/src/main/java/com/edufound/mobile/util/OKHttpUtil.java

@@ -0,0 +1,147 @@
+package com.edufound.mobile.util;
+
+import org.apache.http.conn.ssl.SSLSocketFactory;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.net.UnknownHostException;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.X509Certificate;
+import java.util.concurrent.TimeUnit;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+
+import okhttp3.Call;
+import okhttp3.Callback;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+
+
+/**
+ * Http网络工具,基于OkHttp
+ * Created by Cheny on 2017/04/29.
+ */
+
+public class OKHttpUtil {
+    private OkHttpClient mOkHttpClient;
+    private static OKHttpUtil mInstance;
+    private final static long CONNECT_TIMEOUT = 60;//超时时间,秒
+    private final static long READ_TIMEOUT = 60;//读取时间,秒
+    private final static long WRITE_TIMEOUT = 60;//写入时间,秒
+
+    /**
+     * @param url        下载链接
+     * @param startIndex 下载起始位置
+     * @param endIndex   结束为止
+     * @param callback   回调
+     * @throws IOException
+     */
+    public void downloadFileByRange(String url, long startIndex, long endIndex, Callback callback) throws IOException {
+        // 创建一个Request
+        // 设置分段下载的头信息。 Range:做分段数据请求,断点续传指示下载的区间。格式: Range bytes=0-1024或者bytes:0-1024
+        Request request = new Request.Builder().header("RANGE", "bytes=" + startIndex + "-" + endIndex)
+                .url(url)
+                .build();
+        doAsync(request, callback);
+    }
+
+    public void getContentLength(String url, Callback callback) throws IOException {
+        // 创建一个Request
+        Request request = new Request.Builder()
+                .url(url)
+                .build();
+        doAsync(request, callback);
+    }
+
+    /**
+     * 异步请求
+     */
+    public void doAsync(Request request, Callback callback) throws IOException {
+        //创建请求会话
+        Call call = mOkHttpClient.newCall(request);
+        //同步执行会话请求
+        call.enqueue(callback);
+    }
+
+    /**
+     * 同步请求
+     */
+    public Response doSync(Request request) throws IOException {
+
+        //创建请求会话
+        Call call = mOkHttpClient.newCall(request);
+        //同步执行会话请求
+        return call.execute();
+    }
+
+
+    /**
+     * @return HttpUtil实例对象
+     */
+    public static OKHttpUtil getInstance() {
+        if (null == mInstance) {
+            synchronized (OKHttpUtil.class) {
+                if (null == mInstance) {
+                    mInstance = new OKHttpUtil();
+                }
+            }
+        }
+        return mInstance;
+    }
+
+    /**
+     * 构造方法,配置OkHttpClient
+     */
+    public OKHttpUtil() {
+        //创建okHttpClient对象
+        OkHttpClient.Builder builder = new OkHttpClient.Builder()
+                .connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS)
+                .writeTimeout(READ_TIMEOUT, TimeUnit.SECONDS)
+                .readTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS);
+        mOkHttpClient = builder.build();
+    }
+
+
+    private static class SSLSocketFactoryEx extends SSLSocketFactory {
+
+        SSLContext sslContext = SSLContext.getInstance("TLS");
+
+        public SSLSocketFactoryEx(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException {
+            super(truststore);
+
+            TrustManager tm = new X509TrustManager() {
+
+                public X509Certificate[] getAcceptedIssuers() {
+                    return null;
+                }
+
+                @Override
+                public void checkClientTrusted(X509Certificate[] chain, String authType) throws java.security.cert.CertificateException {
+                }
+
+                @Override
+                public void checkServerTrusted(X509Certificate[] chain, String authType) throws java.security.cert.CertificateException {
+                }
+            };
+
+            sslContext.init(null, new TrustManager[]{tm}, null);
+        }
+
+        @Override
+        public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {
+            return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
+        }
+
+        @Override
+        public Socket createSocket() throws IOException {
+            return sslContext.getSocketFactory().createSocket();
+        }
+    }
+}

+ 230 - 0
app/src/main/java/com/edufound/mobile/util/PlayerGestureListener.java

@@ -0,0 +1,230 @@
+package com.edufound.mobile.util;
+
+import android.content.Context;
+import android.util.DisplayMetrics;
+import android.view.GestureDetector;
+import android.view.MotionEvent;
+import android.view.ViewConfiguration;
+import android.view.WindowManager;
+
+import java.lang.ref.WeakReference;
+
+/**
+ * 播放器常用手势监听:单击、双击、横向滑动、左右两边边竖向滑动(亮度和声音)
+ */
+
+public class PlayerGestureListener extends GestureDetector.SimpleOnGestureListener {
+    private WeakReference<VideoGestureListener> listener;
+    private int screenWidth, centerW;
+    //播放器View的长宽DP
+    private float dpVideoWidth, dpVideoHeight;
+    private ScrollMode scrollMode = ScrollMode.NONE;
+    private long timeStamp;
+    private int mTouchSlop;
+    private int scrollRatio = 1;    //快进的比率,速度越快,值越大
+    private int preDpVideoDuration = 0;     //每一dp,快进的时长,ms
+    private float density;
+    private int totalDuration = 0;      //单次快进快退累计值
+    private float leftTBValue = 0;      //单次左边累计值(一般是亮度)
+    private float rightTBValue = 0;     //单次右边累计值(一般是声音)
+
+    public PlayerGestureListener(VideoGestureListener listener, Context context) {
+        this.listener = new WeakReference<>(listener);
+        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+        DisplayMetrics outMetrics = new DisplayMetrics();
+        wm.getDefaultDisplay().getMetrics(outMetrics);
+
+        screenWidth = outMetrics.widthPixels;
+        centerW = screenWidth / 2;
+        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
+
+        density = context.getResources().getDisplayMetrics().density;
+    }
+
+    //设置播放器SurfaceView的宽高
+    public void setVideoWH(int w, int h) {
+        dpVideoWidth = w / density;
+        dpVideoHeight = h / density;
+        //默认基础总共2分钟,代表的意义:从屏幕一边滑动到另一边,总共可以快进2分钟
+        preDpVideoDuration = (int) (2 * 60 * 1000 / dpVideoWidth);
+    }
+
+    @Override
+    public boolean onDown(MotionEvent e) {
+        scrollMode = ScrollMode.NONE;
+        timeStamp = System.currentTimeMillis();
+        totalDuration = 0;
+//        leftTBValue = 0;
+//        rightTBValue = 0;
+        if (listener.get() != null) {
+            listener.get().onGestureDown();
+        }
+        return true;
+    }
+
+    @Override
+    public boolean onSingleTapUp(MotionEvent e) {
+        return super.onSingleTapUp(e);
+    }
+
+    @Override
+    public void onShowPress(MotionEvent e) {
+        super.onShowPress(e);
+    }
+
+    @Override
+    public void onLongPress(MotionEvent e) {
+        super.onLongPress(e);
+    }
+
+    @Override
+    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
+        long time = System.currentTimeMillis();
+        distanceX = -distanceX;
+        distanceY = -distanceY;
+        float dpX = distanceX / density;
+        float dpY = distanceY / density;
+        updateScrollRatio(dpX, time - timeStamp);
+        timeStamp = time;
+        float xDiff = e2.getX() - e1.getX();
+        float yDiff = e2.getY() - e1.getY();
+        if (scrollMode == ScrollMode.NONE) {
+            //横向滑动
+            if (Math.abs(xDiff) > mTouchSlop) {
+                scrollMode = ScrollMode.HORIZONTAL_S;
+                updateVideoTime((int) (preDpVideoDuration * xDiff));
+            }
+            //纵向滑动
+            else if (Math.abs(yDiff) > mTouchSlop) {
+                if (e1.getX() < centerW) {
+                    scrollMode = ScrollMode.LEFT_TB;
+                } else {
+                    scrollMode = ScrollMode.RIGHT_TB;
+                }
+            }
+        }
+        //快进快退
+        else if (scrollMode == ScrollMode.HORIZONTAL_S) {
+            updateVideoTime((int) (preDpVideoDuration * scrollRatio * dpX));
+        } else if (scrollMode == ScrollMode.LEFT_TB) {
+            updateVideoLeftTB(dpY / dpVideoHeight);
+        } else if (scrollMode == ScrollMode.RIGHT_TB) {
+            updateVideoRightTB(dpY / dpVideoHeight);
+        }
+        return true;
+    }
+
+    @Override
+    public boolean onDoubleTap(MotionEvent e) {
+        if (listener.get() != null) {
+            listener.get().onGestureDoubleClick();
+        }
+        //双击事件
+        return super.onDoubleTap(e);
+    }
+
+    @Override
+    public boolean onDoubleTapEvent(MotionEvent e) {
+        return super.onDoubleTapEvent(e);
+    }
+
+    @Override
+    public boolean onSingleTapConfirmed(MotionEvent e) {
+        if (listener.get() != null) {
+            listener.get().onGestureSingleClick();
+        }
+        //单击事件,在双击事件发生时不会产生这个事件,所以用这个回调作为播放器单击事件
+        return super.onSingleTapConfirmed(e);
+    }
+
+    /***
+     * 根据滑动速度更新速度比率值,这样可以在滑动速率较快时,快进的速度也会变快,可以根据需要调整
+     * 根据实验,正常速度一般在10~40dp/s
+     * @param dpX:横向滑动距离 dp
+     * @param duration:时间间隔 ms
+     */
+    private void updateScrollRatio(float dpX, long duration) {
+        int ratio = (int) ((Math.abs(dpX) / duration) * 1000);
+        if (ratio < 20) {
+            scrollRatio = 1;
+        } else if (ratio < 40) {
+            scrollRatio = 3;
+        } else if (ratio < 70) {
+            scrollRatio = 7;
+        } else if (ratio < 100) {
+            scrollRatio = 13;
+        } else if (ratio < 300) {
+            scrollRatio = 18;
+        } else if (ratio < 500) {
+            scrollRatio = 24;
+        } else if (ratio < 800) {
+            scrollRatio = 31;
+        } else if (ratio < 1000) {
+            scrollRatio = 40;
+        } else {
+            scrollRatio = 60;
+        }
+    }
+
+    //累积快进进度,totalDuration:当前快进的总值,负值代表是要快退
+    private void updateVideoTime(int duration) {
+        totalDuration += duration;
+        if (listener.get() != null) {
+            listener.get().onGestureUpdateVideoTime(totalDuration);
+        }
+    }
+
+    //累积亮度
+    private void updateVideoLeftTB(float ratio) {
+        leftTBValue += ratio;
+        if (listener.get() != null) {
+            listener.get().onGestureLeftTB(leftTBValue);
+        }
+    }
+
+    //累积声音
+    private void updateVideoRightTB(float ratio) {
+        rightTBValue += ratio;
+        if (listener.get() != null) {
+            listener.get().onGestureRightTB(rightTBValue);
+        }
+    }
+
+    public interface VideoGestureListener {
+        /***
+         * 手指在Layout左半部上下滑动时候调用,一般是亮度手势
+         * 从View底部滑动到顶部,代表从0升到1
+         * @param ratio:0-1 之间,1代表最亮,0代表最暗
+         */
+        void onGestureLeftTB(float ratio);
+
+        /***
+         * 手指在Layout右半部上下滑动时候调用,一般是音量手势
+         * 从View底部滑动到顶部,代表从0升到1
+         * @param ratio:0-1 之间,1代表音量最大,0代表音量最低
+         */
+        void onGestureRightTB(float ratio);
+
+        /**
+         * @param duration :快进快退,大于0快进,小于0快退
+         */
+        void onGestureUpdateVideoTime(int duration);
+
+        //单击手势,确认是单击的时候调用
+        void onGestureSingleClick();
+
+        //双击手势,确认是双击的时候调用,可用于播放器暂停
+        void onGestureDoubleClick();
+
+        void onGestureDown();
+    }
+
+    private enum ScrollMode {
+        NONE,               //初始值
+        LEFT_TB,            //左边上下滑动(调节亮度)
+        RIGHT_TB,           //右边上下滑动(调节声音)
+        HORIZONTAL_S,       //横向滑动(快进快退)
+        SINGLE_CLICK,       //单击
+        DOUBLE_CLICK        //双击
+    }
+}

+ 122 - 0
app/src/main/java/com/edufound/mobile/util/SPutil.java

@@ -0,0 +1,122 @@
+package com.edufound.mobile.util;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+
+import java.util.List;
+
+/**
+ * 本地字符串缓存工具类
+ *
+ * @ClassName: SPutil
+ * @Description: TODO
+ */
+public class SPutil {
+
+    private static final String spName = "efunbox";
+    public static final String videoType = "video_type";
+    public static final String notificationType = "notification_type";
+    public static final int VIDEO_IJKPLAYER = 1;
+    public static final int VIDEO_VIDEOVIEW = 2;
+    public static final int NOTIFICATION_OPEN = 1;
+    public static final int NOTIFICATION_CLOSE = 2;
+
+
+    private static int model = Context.MODE_MULTI_PROCESS;
+
+    public static String getPrefString(Context context, String key, final String defaultValue) {
+        SharedPreferences sp = context.getSharedPreferences(spName, model);
+        return sp.getString(key, defaultValue);
+    }
+
+    public static void setPrefString(Context context, final String key, final String value) {
+        SharedPreferences sp = context.getSharedPreferences(spName, model);
+        sp.edit().putString(key, value).commit();
+    }
+
+    public static boolean getPrefBoolean(Context context, final String key, final boolean defaultValue) {
+
+        SharedPreferences sp = context.getSharedPreferences(spName, model);
+        return sp.getBoolean(key, defaultValue);
+    }
+
+    public static boolean hasKey(Context context, final String key) {
+        SharedPreferences sp = context.getSharedPreferences(spName, model);
+        return sp.contains(key);
+    }
+
+    public static void setPrefBoolean(Context context, final String key, final boolean value) {
+        SharedPreferences sp = context.getSharedPreferences(spName, model);
+        sp.edit().putBoolean(key, value).commit();
+    }
+
+    public static void setPrefInt(Context context, final String key, final int value) {
+        SharedPreferences sp = context.getSharedPreferences(spName, model);
+        sp.edit().putInt(key, value).commit();
+    }
+
+    public static int getPrefInt(Context context, final String key, final int defaultValue) {
+
+        SharedPreferences sp = context.getSharedPreferences(spName, model);
+        return sp.getInt(key, defaultValue);
+    }
+
+    public static void setPrefFloat(Context context, final String key, final float value) {
+        SharedPreferences sp = context.getSharedPreferences(spName, model);
+        sp.edit().putFloat(key, value).commit();
+    }
+
+    public static float getPrefFloat(Context context, final String key, final float defaultValue) {
+        SharedPreferences sp = context.getSharedPreferences(spName, model);
+        return sp.getFloat(key, defaultValue);
+    }
+
+    public static void setPrefLong(Context context, final String key, final long value) {
+        SharedPreferences sp = context.getSharedPreferences(spName, model);
+        sp.edit().putLong(key, value).commit();
+    }
+
+    public static long getPrefLong(Context context, final String key, final long defaultValue) {
+        SharedPreferences sp = context.getSharedPreferences(spName, model);
+        return sp.getLong(key, defaultValue);
+    }
+
+    public static void loadRecourdsArray(Context mContext, List<String> recourds, String name) {
+        SharedPreferences sp = mContext.getSharedPreferences(name, model);
+        recourds.clear();
+        int size = sp.getInt("recourds_size", 0);
+
+        for (int i = 0; i < size; i++) {
+            recourds.add(sp.getString("recourds_" + i, null));
+        }
+    }
+
+    public static boolean saveRecourdsArray(Context context, List<String> recourds, String name) {
+        SharedPreferences sp = context.getSharedPreferences(name, model);
+        Editor mEdit1 = sp.edit();
+        mEdit1.putInt("recourds_size", recourds.size()); /* sKey is an array */
+
+        for (int i = 0; i < recourds.size(); i++) {
+            mEdit1.remove("recourds_" + i);
+            mEdit1.putString("recourds_" + i, recourds.get(i));
+        }
+
+        return mEdit1.commit();
+    }
+
+    public static void clearRecourds(Context context, String name) {
+        SharedPreferences sp = context.getSharedPreferences(name, model);
+        Editor mEdit1 = sp.edit();
+        mEdit1.clear();
+        mEdit1.commit();
+    }
+
+    public static void removeByKey(Context context, String name, String key) {
+        SharedPreferences sp = context.getSharedPreferences(name, model);
+        Editor mEdit1 = sp.edit();
+        mEdit1.remove(key);
+        mEdit1.commit();
+    }
+
+}

+ 131 - 0
app/src/main/java/com/edufound/mobile/util/ShowDebugUrl.java

@@ -0,0 +1,131 @@
+package com.edufound.mobile.util;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.os.Handler;
+import android.os.Handler.Callback;
+import android.os.Message;
+import android.view.Display;
+import android.view.Gravity;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.Button;
+import android.widget.EditText;
+
+import com.edufound.mobile.R;
+import com.edufound.mobile.main.MainView;
+
+public final class ShowDebugUrl implements Callback {
+
+    private static final int MSG_SHOW_EFKEY = Integer.MIN_VALUE;
+    private Handler mHandlerUi = new Handler(this);
+    private Handler mHandlerBackground = new Handler(this);
+    private static final int[] EFKEY = {KeyEvent.KEYCODE_DPAD_UP, KeyEvent.KEYCODE_DPAD_DOWN,
+            KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.KEYCODE_DPAD_LEFT,
+            KeyEvent.KEYCODE_DPAD_UP, KeyEvent.KEYCODE_DPAD_DOWN,
+            KeyEvent.KEYCODE_DPAD_RIGHT, KeyEvent.KEYCODE_DPAD_RIGHT};
+    private static final int EFKEY_LENGTH = EFKEY.length;
+    private static final long INPUT_INTERVAL = 10 * 1000L;
+    private long mLastInputTime;
+    private int mIndex;
+    private static Activity mContext;
+    Dialog dialog;
+    static MainView mView;
+
+    private void input(int keyCode) {
+        if (System.currentTimeMillis() - mLastInputTime > INPUT_INTERVAL) {
+            mIndex = 0;
+        }
+        if (mIndex >= EFKEY_LENGTH || mIndex < 0) {
+            mIndex = 0;
+        }
+        if (EFKEY[mIndex] == keyCode) {
+            mLastInputTime = System.currentTimeMillis();
+            mIndex++;
+            if (mIndex == EFKEY_LENGTH) {
+                mHandlerUi.sendEmptyMessage(MSG_SHOW_EFKEY);
+            }
+        } else {
+            mLastInputTime = System.currentTimeMillis();
+            mIndex = 0;
+        }
+    }
+
+    public void show(MainView mview) {
+        mView = mview;
+        mContext = mView.getActivity();
+        Logger.e("ShowDebugUrl Dialog");
+        if (dialog == null) {
+            dialog = new Dialog(mContext);
+            dialog.setContentView(createView());
+            Window dialogWindow = dialog.getWindow();
+            dialogWindow.setGravity(Gravity.CENTER);
+            WindowManager m = mContext.getWindowManager();
+            Display d = m.getDefaultDisplay(); // 获取屏幕宽、高用
+            WindowManager.LayoutParams p = dialogWindow.getAttributes(); // 获取对话框当前的参数值
+            p.height = (int) (d.getHeight() * 0.6);
+            p.width = (int) (d.getWidth() * 0.8);
+            dialogWindow.setAttributes(p);
+            dialog.setTitle("设置");
+        }
+        dialog.show();
+    }
+
+    private View createView() {
+        View debugUrl = LayoutInflater.from(mContext).inflate(R.layout.window_debugurl, null);
+        final EditText editText = debugUrl.findViewById(R.id.window_debugurl_edit);
+        Button btn = debugUrl.findViewById(R.id.window_debugurl_btn);
+        btn.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                if (editText.getText() == null || editText.getText().equals("")) {
+                    return;
+                }
+                ToastUtil.showToast(editText.getText().toString());
+                mView.loadUrl(editText.getText().toString());
+            }
+        });
+        return debugUrl;
+    }
+
+    private static final ShowDebugUrl INSTANCE = new ShowDebugUrl();
+
+    public static void dispatchKeyEvent(KeyEvent e, MainView mainview) {
+        try {
+
+            mContext = mView.getActivity();
+            getInstance().dispathInput(e);
+        } catch (final Exception ex) {
+            ex.printStackTrace();
+        }
+    }
+
+    public static ShowDebugUrl getInstance() {
+        return INSTANCE;
+    }
+
+    private void dispathInput(final KeyEvent e) {
+        mHandlerBackground.sendEmptyMessage(e.getKeyCode());
+    }
+
+    @Override
+    public boolean handleMessage(Message msg) {
+        try {
+            switch (msg.what) {
+                case MSG_SHOW_EFKEY:
+//                    show();
+                    break;
+                default:
+                    input(msg.what);
+                    break;
+            }
+        } catch (final Exception ex) {
+            ex.printStackTrace();
+        }
+        return true;
+    }
+
+}

+ 142 - 0
app/src/main/java/com/edufound/mobile/util/ShowDevice.java

@@ -0,0 +1,142 @@
+package com.edufound.mobile.util;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.graphics.Color;
+import android.os.Handler;
+import android.os.Handler.Callback;
+import android.os.Message;
+import android.view.Display;
+import android.view.Gravity;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.TextView;
+
+import com.edufound.mobile.R;
+
+public final class ShowDevice implements Callback {
+
+    private static final int MSG_SHOW_EFKEY = Integer.MIN_VALUE;
+    private Handler mHandlerUi = new Handler(this);
+    private Handler mHandlerBackground = new Handler(this);
+    private static final int[] EFKEY = {KeyEvent.KEYCODE_DPAD_UP, KeyEvent.KEYCODE_DPAD_RIGHT,
+            KeyEvent.KEYCODE_DPAD_DOWN, KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.KEYCODE_DPAD_UP,
+            KeyEvent.KEYCODE_DPAD_RIGHT, KeyEvent.KEYCODE_DPAD_DOWN, KeyEvent.KEYCODE_DPAD_LEFT};
+    private static final int EFKEY_LENGTH = EFKEY.length;
+    private static final long INPUT_INTERVAL = 10 * 1000L;
+    private long mLastInputTime;
+    private int mIndex;
+    private static Activity mContext;
+    private DeviceUtil dUtil = new DeviceUtil();
+
+    private void input(int keyCode) {
+        if (System.currentTimeMillis() - mLastInputTime > INPUT_INTERVAL) {
+            mIndex = 0;
+        }
+        if (mIndex >= EFKEY_LENGTH || mIndex < 0) {
+            mIndex = 0;
+        }
+        if (EFKEY[mIndex] == keyCode) {
+            mLastInputTime = System.currentTimeMillis();
+            mIndex++;
+            if (mIndex == EFKEY_LENGTH) {
+                mHandlerUi.sendEmptyMessage(MSG_SHOW_EFKEY);
+            }
+        } else {
+
+            mLastInputTime = System.currentTimeMillis();
+            mIndex = 0;
+        }
+    }
+
+    public void show(Activity act) {
+        mContext = act;
+        Logger.e("show EfKey Dialog");
+        StringBuffer buffer = new StringBuffer();
+        buffer.append("\n\tSerialNumber:\t" + "\t" + dUtil.SerialNumber() + "\n");
+        buffer.append("\t自定义SerialNumber:\t" + "\t" + dUtil.getSerial() + "\n");
+        buffer.append("\tUUID:\t" + "\t" + DeviceUuidFactory.getUuid() + "\n");
+        buffer.append("\t厂商:\t" + "\t" + dUtil.getDeviceBrand() + "\n");
+        buffer.append("\t型号:\t" + "\t" + dUtil.getSystemModel() + "\n");
+        buffer.append("\t系统版本号:\t" + "\t" + dUtil.getSystemVersion() + "\n");
+        buffer.append("\t应用版本号:\t" + "\t" + dUtil.getVersionCode(mContext) + "\n");
+        buffer.append("\t应用版本号名称:\t" + "\t" + dUtil.getVersionName(mContext) + "\n");
+        buffer.append("\t屏幕宽度:\t\t" + dUtil.getWidth(mContext) + "\n");
+        buffer.append("\t屏幕高度:\t\t" + dUtil.getHeight(mContext) + "\n");
+        buffer.append("\t屏幕密度:\t\t" + dUtil.getDensity(mContext) + "\n");
+        buffer.append("\t屏幕DPI:\t\t" + dUtil.getDensityDpi(mContext) + "\n");
+        String playerName = "";
+        switch (SPutil.getPrefInt(mContext, SPutil.videoType, 0)) {
+            case SPutil.VIDEO_IJKPLAYER:
+                playerName = "IJKPlayer播放器";
+                break;
+            case SPutil.VIDEO_VIDEOVIEW:
+                playerName = "默认VideoView播放器";
+                break;
+        }
+        buffer.append("\t播放器类型:\t\t" + playerName + "\n");
+        String message = buffer.toString();
+        Dialog dialog = new Dialog(mContext);
+        dialog.setContentView(createView(message));
+        Window dialogWindow = dialog.getWindow();
+        dialogWindow.setGravity(Gravity.CENTER);
+        WindowManager m = mContext.getWindowManager();
+        Display d = m.getDefaultDisplay(); // 获取屏幕宽、高用
+        WindowManager.LayoutParams p = dialogWindow.getAttributes(); // 获取对话框当前的参数值
+        p.height = (int) (d.getHeight() * 0.6);
+        p.width = (int) (d.getWidth() * 0.8);
+        dialogWindow.setAttributes(p);
+        dialog.setTitle("Device信息");
+        dialog.show();
+    }
+
+    private View createView(String message) {
+        View infoView = LayoutInflater.from(mContext).inflate(R.layout.window_deviceinfo, null);
+        TextView text = (TextView) infoView.findViewById(R.id.deviceinfo);
+        text.setText(message);
+        text.setTextSize(20);
+        text.setTextColor(Color.RED);
+
+        return infoView;
+    }
+
+    private static final ShowDevice INSTANCE = new ShowDevice();
+
+    public static void dispatchKeyEvent(KeyEvent e, Activity context) {
+        try {
+            mContext = context;
+            getInstance().dispathInput(e);
+        } catch (final Exception ex) {
+            ex.printStackTrace();
+        }
+    }
+
+    public static ShowDevice getInstance() {
+        return INSTANCE;
+    }
+
+    private void dispathInput(final KeyEvent e) {
+        mHandlerBackground.sendEmptyMessage(e.getKeyCode());
+    }
+
+    @Override
+    public boolean handleMessage(Message msg) {
+        try {
+            switch (msg.what) {
+                case MSG_SHOW_EFKEY:
+//                    show();
+                    break;
+                default:
+                    input(msg.what);
+                    break;
+            }
+        } catch (final Exception ex) {
+            ex.printStackTrace();
+        }
+        return true;
+    }
+
+}

+ 140 - 0
app/src/main/java/com/edufound/mobile/util/ShowSetting.java

@@ -0,0 +1,140 @@
+package com.edufound.mobile.util;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.os.Handler;
+import android.os.Handler.Callback;
+import android.os.Message;
+import android.view.Display;
+import android.view.Gravity;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.RadioButton;
+import android.widget.RadioGroup;
+
+import com.edufound.mobile.R;
+
+public final class ShowSetting implements Callback {
+
+    private static final int MSG_SHOW_EFKEY = Integer.MIN_VALUE;
+    private Handler mHandlerUi = new Handler(this);
+    private Handler mHandlerBackground = new Handler(this);
+    private static final int[] EFKEY = {KeyEvent.KEYCODE_DPAD_UP, KeyEvent.KEYCODE_DPAD_LEFT,
+            KeyEvent.KEYCODE_DPAD_DOWN, KeyEvent.KEYCODE_DPAD_RIGHT, KeyEvent.KEYCODE_DPAD_UP,
+            KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.KEYCODE_DPAD_DOWN, KeyEvent.KEYCODE_DPAD_RIGHT};
+    private static final int EFKEY_LENGTH = EFKEY.length;
+    private static final long INPUT_INTERVAL = 10 * 1000L;
+    private long mLastInputTime;
+    private int mIndex;
+    private static Activity mContext;
+    private DeviceUtil dUtil = new DeviceUtil();
+
+    private void input(int keyCode) {
+        if (System.currentTimeMillis() - mLastInputTime > INPUT_INTERVAL) {
+            mIndex = 0;
+        }
+        if (mIndex >= EFKEY_LENGTH || mIndex < 0) {
+            mIndex = 0;
+        }
+        if (EFKEY[mIndex] == keyCode) {
+            mLastInputTime = System.currentTimeMillis();
+            mIndex++;
+            if (mIndex == EFKEY_LENGTH) {
+                mHandlerUi.sendEmptyMessage(MSG_SHOW_EFKEY);
+            }
+        } else {
+
+            mLastInputTime = System.currentTimeMillis();
+            mIndex = 0;
+        }
+    }
+
+    public void show(Activity act) {
+        mContext = act;
+        Logger.e("ShowSetting Dialog");
+        Dialog dialog = new Dialog(mContext);
+        dialog.setContentView(createView());
+        Window dialogWindow = dialog.getWindow();
+        dialogWindow.setGravity(Gravity.CENTER);
+        WindowManager m = mContext.getWindowManager();
+        Display d = m.getDefaultDisplay(); // 获取屏幕宽、高用
+        WindowManager.LayoutParams p = dialogWindow.getAttributes(); // 获取对话框当前的参数值
+        p.height = (int) (d.getHeight() * 0.6);
+        p.width = (int) (d.getWidth() * 0.8);
+        dialogWindow.setAttributes(p);
+        dialog.setTitle("设置");
+        dialog.show();
+    }
+
+    private View createView() {
+        View infoView = LayoutInflater.from(mContext).inflate(R.layout.window_setting, null);
+        RadioGroup rg = infoView.findViewById(R.id.setting_rg);
+        int selectid = SPutil.getPrefInt(ContextUtil.getContext(), SPutil.videoType, 0);
+        RadioButton moren = null;
+        if (selectid == SPutil.VIDEO_IJKPLAYER) {
+            moren = ((RadioButton) infoView.findViewById(R.id.setting_rg_ijk));
+        } else if (selectid == SPutil.VIDEO_VIDEOVIEW) {
+            moren = ((RadioButton) infoView.findViewById(R.id.setting_rg_video));
+        } else {
+            moren = ((RadioButton) infoView.findViewById(R.id.setting_rg_video));
+        }
+        moren.setChecked(true);
+        moren.requestFocus();
+        rg.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
+            @Override
+            public void onCheckedChanged(RadioGroup group, int checkedId) {
+                switch (checkedId) {
+                    case R.id.setting_rg_video:
+                        ToastUtil.showToast("已选择默认播放器");
+                        SPutil.setPrefInt(mContext, SPutil.videoType, SPutil.VIDEO_VIDEOVIEW);
+                        break;
+                    case R.id.setting_rg_ijk:
+                        ToastUtil.showToast("已选择IJKPlayer播放器");
+                        SPutil.setPrefInt(mContext, SPutil.videoType, SPutil.VIDEO_IJKPLAYER);
+                        break;
+                }
+            }
+        });
+        return infoView;
+    }
+
+    private static final ShowSetting INSTANCE = new ShowSetting();
+
+    public static void dispatchKeyEvent(KeyEvent e, Activity context) {
+        try {
+            mContext = context;
+            getInstance().dispathInput(e);
+        } catch (final Exception ex) {
+            ex.printStackTrace();
+        }
+    }
+
+    public static ShowSetting getInstance() {
+        return INSTANCE;
+    }
+
+    private void dispathInput(final KeyEvent e) {
+        mHandlerBackground.sendEmptyMessage(e.getKeyCode());
+    }
+
+    @Override
+    public boolean handleMessage(Message msg) {
+        try {
+            switch (msg.what) {
+                case MSG_SHOW_EFKEY:
+//                    show();
+                    break;
+                default:
+                    input(msg.what);
+                    break;
+            }
+        } catch (final Exception ex) {
+            ex.printStackTrace();
+        }
+        return true;
+    }
+
+}

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

@@ -0,0 +1,16 @@
+package com.edufound.mobile.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.getContext(), message, 5000);
+        } else {
+            toast.setText(message);
+        }
+        toast.show();
+    }
+}

+ 150 - 0
app/src/main/java/com/edufound/mobile/util/UpdateUtil.java

@@ -0,0 +1,150 @@
+package com.edufound.mobile.util;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.view.Display;
+import android.view.Gravity;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.FrameLayout;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.edufound.mobile.R;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.net.URLConnection;
+
+public class UpdateUtil {
+
+    String mNewAppFile;
+    int downLoadFileSize;
+    Activity mContext;
+    File mApkDir;
+    int fileSize;
+    ProgressBar pBar;
+    TextView tText;
+
+    public UpdateUtil(Activity context) {
+        mContext = context;
+        mApkDir = context.getDir("apk", Context.MODE_PRIVATE);
+        showWindow();
+    }
+
+    //显示对话框
+    private void showWindow() {
+        mDownHandler.sendEmptyMessage(0x2283);
+    }
+
+    // 下載文件
+    public void down_file(String url) throws IOException {
+        String filename = url.substring(url.lastIndexOf("/") + 1);
+        URL myURL = new URL(url);
+        URLConnection conn = myURL.openConnection();
+        conn.connect();
+        InputStream is = conn.getInputStream();
+        fileSize = conn.getContentLength();
+        if (fileSize <= 0)
+            throw new RuntimeException("filesize is 0");
+        if (is == null)
+            throw new RuntimeException("stream is null");
+        mNewAppFile = mApkDir.toString() + "/" + filename;
+        FileOutputStream fos = new FileOutputStream(mNewAppFile);
+
+        byte buf[] = new byte[1024];
+        downLoadFileSize = 0;
+        sendMsg(0);
+        do {
+            int numread = is.read(buf);
+            if (numread == -1) {
+                break;
+            }
+            fos.write(buf, 0, numread);
+            downLoadFileSize += numread;
+            sendMsg(1);//
+        } while (true);
+        sendMsg(2);//
+        try {
+            is.close();
+        } catch (Exception ex) {
+            Logger.DebugE("下载文件异常--" + ex.getMessage());
+        }
+    }
+
+    private void sendMsg(int flag) {
+        Message msg = new Message();
+        msg.what = flag;
+        mDownHandler.sendMessage(msg);
+    }
+
+    Dialog dialog;
+    // 更新下载
+    private Handler mDownHandler = new Handler(Looper.getMainLooper()) {
+        @Override
+        public void handleMessage(Message msg) {
+            if (!Thread.currentThread().isInterrupted()) {
+                switch (msg.what) {
+                    case 0x2283:
+                        FrameLayout frameLayout = (FrameLayout) LayoutInflater.from(mContext).inflate(R.layout.window_upgrade, null);
+                        pBar = (ProgressBar) frameLayout.findViewById(R.id.upgrade_progress);
+                        tText = (TextView) frameLayout.findViewById(R.id.upgrade_text);
+                        dialog = new Dialog(mContext);
+                        dialog.setOnKeyListener(new DialogInterface.OnKeyListener() {
+                            @Override
+                            public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
+                                if (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_ESCAPE) {
+                                    return true;
+                                }
+
+                                return false;
+                            }
+                        });
+                        dialog.setContentView(frameLayout);
+                        Window dialogWindow = dialog.getWindow();
+                        dialogWindow.setGravity(Gravity.CENTER);
+                        WindowManager m = mContext.getWindowManager();
+                        Display d = m.getDefaultDisplay(); // 获取屏幕宽、高用
+                        WindowManager.LayoutParams p = dialogWindow.getAttributes(); // 获取对话框当前的参数值
+                        p.height = (int) (d.getHeight() * 0.6);
+                        p.width = (int) (d.getWidth() * 0.8);
+                        dialogWindow.setAttributes(p);
+                        dialog.setTitle("升级中");
+                        dialog.setCanceledOnTouchOutside(false);
+                        dialog.show();
+                        break;
+                    case 0:
+                        pBar.setMax(fileSize);
+                    case 1:
+                        pBar.setProgress(downLoadFileSize);
+                        int result = downLoadFileSize * 100 / fileSize;
+                        tText.setText((downLoadFileSize / 1024 / 1024) + "MB/" + (fileSize / 1024 / 1024) + "MB");
+                        if (result == 100) {
+
+                        }
+                        break;
+                    case 2:
+                        dialog.dismiss();
+                        EduFoundUtil.openFile(mContext, new File(mNewAppFile));
+                        break;
+                    case -1:
+                        String error = msg.getData().getString("error");
+                        Toast.makeText(mContext, error, Toast.LENGTH_SHORT).show();
+                        break;
+                }
+            }
+            super.handleMessage(msg);
+        }
+    };
+}

+ 33 - 0
app/src/main/java/com/edufound/mobile/video/VideoAView.java

@@ -0,0 +1,33 @@
+package com.edufound.mobile.video;
+
+import android.net.Uri;
+
+import com.edufound.mobile.base.BaseView;
+
+import tv.danmaku.ijk.media.player.IMediaPlayer;
+
+
+public interface VideoAView extends BaseView {
+
+    void setVideoUri(Uri uri);
+
+    void start();
+
+    void pause();
+
+    void stop();
+
+    void releaseVideo();
+
+    void seek(int seek);
+
+    boolean isPlaying();
+
+    int getDuration();
+
+    int getCurrent();
+
+    void activityFinish();
+
+
+}

+ 15 - 0
app/src/main/java/com/edufound/mobile/video/VideoModel.java

@@ -0,0 +1,15 @@
+package com.edufound.mobile.video;
+
+import com.edufound.mobile.base.BaseModel;
+
+public class VideoModel implements BaseModel {
+
+    public VideoModel() {
+    }
+
+
+    @Override
+    public void LoadData(LoadDataBack callback) {
+
+    }
+}

+ 905 - 0
app/src/main/java/com/edufound/mobile/video/VideoPersenter.java

@@ -0,0 +1,905 @@
+package com.edufound.mobile.video;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Color;
+import android.graphics.drawable.AnimationDrawable;
+import android.graphics.drawable.Drawable;
+import android.media.AudioManager;
+import android.media.MediaPlayer;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.view.Display;
+import android.view.GestureDetector;
+import android.view.Gravity;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+import com.edufound.mobile.R;
+import com.edufound.mobile.application.EApplication;
+import com.edufound.mobile.base.BaseModel;
+import com.edufound.mobile.base.BasePersenter;
+import com.edufound.mobile.util.AesUtil;
+import com.edufound.mobile.util.ContextUtil;
+import com.edufound.mobile.util.DeviceUtil;
+import com.edufound.mobile.util.DrawableUtil;
+import com.edufound.mobile.util.EduFoundUtil;
+import com.edufound.mobile.util.Logger;
+import com.edufound.mobile.util.ToastUtil;
+import com.edufound.mobile.view.ErrorView;
+import com.google.gson.Gson;
+import com.warkiz.widget.IndicatorSeekBar;
+import com.warkiz.widget.TickMarkType;
+
+public class VideoPersenter implements VideoIPersenter, GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener {
+
+    private VideoPersenter mPersenter;
+    private VideoAView mView = null;
+    private VideoModel mModel = null;
+    private FrameLayout mFrameController;
+    private LinearLayout mPlayerController;
+    private FrameLayout mOtherFrame;
+    private ImageView mPlayerBack;
+    private ImageView mPlayerLoading;
+    public ImageView mPlayerStatus;
+    private Gson mGson;
+    private VideoJsonBean[] mVideoBean;
+    private TextView mVideoName;
+    private ImageView mLittleIcon;
+    private TextView mCurrent;
+    private SeekBar mSeekbar;
+    private int SEEK_COUNT = 1; //用来控制长按快进的seek_progress
+    final int SEEK_PROGRESS = 1000;
+    final int HIDE_CONTROLLER_TIME = 5000;
+    final int SET_INFO = 0x7891;
+    final int SHOW_CONTROLLER = 0x7892;
+    final int HIDE_CONTROLLER = 0x7893;
+    final int STATUS_PLAY = 0x8891;
+    final int STATUS_PAUSE = 0x8892;
+    final int STATUS_FORWARD = 0x8893;
+    final int STATUS_REWIND = 0x8894;
+    final int SHOW_STATUS_IMAGE = 0x8895;
+    final int HIDE_STATUS_IMAGE = 0x8896;
+    final int PLAY_NEXT = 0x8897;
+    final int DISCONNECT_NETWORK = 0x8898;
+    final int CONNECT_NETWORK = 0x9989;
+    final int SHOW_TOUCHVIEW = 0x8899;
+    final int HIDE_TOUCHVIEW = 0x8890;
+    //单独播放,播放完成直接关闭
+    final int TYPE_SEPARATELY_PLAY = 0;
+    //单独循环播放,一直循环
+    final int TYPE_SINGLECYCLE_PLAY = 1;
+    //列表播放,播放完列表关闭
+    final int TYPE_LIST_PLAY = 2;
+    AnimationDrawable mLoadingAnim;
+    private int mStatusCode;
+    Bitmap mStatusPlayBitmap;
+    Bitmap mLittleIconPlayBitmap;
+    Bitmap mLittleIconPauseBitmap;
+    int mPlayIndex;
+    int mPlayType;
+    String mPlayingId;
+    String mPlayNeedPost;
+    int mPlayStartTime;
+    String SINGLECYCLE_URL = "";
+    ErrorView mErrorView;
+    Dialog mErrorViewDialog;
+    int mPlayerBackTime;
+    String mPlayerModuleType;
+    int mNetWorkErrorTime;
+    boolean isPrepared = false;
+    boolean isControllerShow = true;
+    private GestureDetector gestureDetector;
+    DeviceUtil deviceUtil;
+    IndicatorSeekBar mTouchSeek;
+    FrameLayout mTouchView;
+    TextView mTouchText;
+    ImageView mTouchIcon;
+    boolean isSaveState = false;
+    int oneVolume = 0;
+
+    public VideoPersenter(VideoAView view) {
+        mPersenter = this;
+        mView = view;
+        mModel = new VideoModel();
+        mGson = new Gson();
+        audiomanager = (AudioManager) mView.getActivity().getSystemService(Context.AUDIO_SERVICE);
+        maxVolume = audiomanager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); // 获取系统最大音量
+        currentVolume = audiomanager.getStreamVolume(AudioManager.STREAM_MUSIC); // 获取当前值
+        oneVolume = maxVolume / 10;
+        deviceUtil = new DeviceUtil();
+        playerWidth = deviceUtil.getWidth(mView.getActivity());
+        gestureDetector = new GestureDetector(mView.getActivity(), this);
+        gestureDetector.setIsLongpressEnabled(true);
+        mFrameController = (FrameLayout) LayoutInflater.from(ContextUtil.getContext()).inflate(R.layout.player_controller, null);
+        mOtherFrame = mFrameController.findViewById(R.id.player_other_frame);
+        mPlayerController = mFrameController.findViewById(R.id.player_controller_layout);
+        mPlayerBack = mPlayerController.findViewById(R.id.player_back);
+        mVideoName = mFrameController.findViewById(R.id.player_name);
+        mLittleIcon = mFrameController.findViewById(R.id.player_little_icon);
+        mCurrent = mFrameController.findViewById(R.id.player_current);
+        mSeekbar = mFrameController.findViewById(R.id.player_seekbar);
+        Drawable drawable = DrawableUtil.getNewDrawable(mView.getActivity(), R.drawable.seekbar_thumb, 36 * 2, 60 * 2);
+        mSeekbar.setThumb(drawable);
+        mPlayerStatus = mFrameController.findViewById(R.id.player_status);
+        mPlayerLoading = mFrameController.findViewById(R.id.player_loading);
+        mLoadingAnim = (AnimationDrawable) mPlayerLoading.getBackground();
+        mLoadingAnim.start();
+        mSeekbar.setFocusable(true);
+        mStatusPlayBitmap = BitmapFactory.decodeResource(ContextUtil.getContext().getResources(), R.drawable.edufound_player_play);
+        mLittleIconPlayBitmap = BitmapFactory.decodeResource(ContextUtil.getContext().getResources(), R.drawable.player_little_icon_play);
+        mLittleIconPauseBitmap = BitmapFactory.decodeResource(ContextUtil.getContext().getResources(), R.drawable.player_little_icon_pause);
+        mTouchView = (FrameLayout) LayoutInflater.from(mView.getActivity()).inflate(R.layout.player_touch_view, null);
+        mTouchText = (TextView) mTouchView.findViewById(R.id.player_touch_text);
+        mTouchIcon = (ImageView) mTouchView.findViewById(R.id.player_touch_icon);
+        FrameLayout mTouchSeekFrame = (FrameLayout) mTouchView.findViewById(R.id.player_touch_seekbar_frame);
+        mTouchSeek = IndicatorSeekBar
+                .with(mView.getActivity())
+                .max(10)
+                .min(0)
+                .progress(0)
+                .tickCount(11)
+                .showTickMarksType(TickMarkType.DIVIDER)
+                .tickMarksColor(mView.getActivity().getResources().getColor(R.color.result_view))
+                .tickMarksSize(10)//dp
+                .tickMarksEndsHide(true)
+                .trackProgressColor(mView.getActivity().getResources().getColor(R.color.white))
+                .trackProgressSize(10)
+                .trackBackgroundColor(mView.getActivity().getResources().getColor(R.color.gray))
+                .trackBackgroundSize(10)
+                .thumbSize(0)
+                .build();
+        FrameLayout.LayoutParams touch_seek_params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+        touch_seek_params.gravity = Gravity.CENTER;
+        mTouchSeek.setLayoutParams(touch_seek_params);
+        FrameLayout.LayoutParams touch_params = new FrameLayout.LayoutParams(deviceUtil.getWidth(mView.getActivity()) / 4, deviceUtil.getHeight(mView.getActivity()) / 3);
+        touch_params.gravity = Gravity.CENTER;
+        mTouchView.setLayoutParams(touch_params);
+        mTouchSeekFrame.addView(mTouchSeek);
+        mOtherFrame.addView(mTouchView);
+        mTouchView.setVisibility(View.GONE);
+        setListener();
+    }
+
+    void setListener() {
+
+        mPlayerBack.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                removeHandler();
+                mView.activityFinish();
+            }
+        });
+        mLittleIcon.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                if (mView.isPlaying()) {
+                    mView.pause();
+                    checkStatus(STATUS_PLAY);
+                    mVideoHandler.sendEmptyMessage(SHOW_STATUS_IMAGE);
+                    mVideoHandler.sendEmptyMessage(SHOW_CONTROLLER);
+                } else {
+                    mView.start();
+                    checkStatus(STATUS_PAUSE);
+                    mPlayerStatus.setVisibility(View.INVISIBLE);
+                    mVideoHandler.sendEmptyMessage(SHOW_CONTROLLER);
+                }
+            }
+        });
+        mSeekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
+            @Override
+            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+                mVideoHandler.removeMessages(SET_INFO);
+                mCurrent.setText(EduFoundUtil.getTime(progress) + "/" + EduFoundUtil.getTime(mView.getDuration()));
+            }
+
+            @Override
+            public void onStartTrackingTouch(SeekBar seekBar) {
+                mVideoHandler.removeMessages(SHOW_CONTROLLER);
+                mVideoHandler.removeMessages(HIDE_CONTROLLER);
+            }
+
+            @Override
+            public void onStopTrackingTouch(SeekBar seekBar) {
+                if (seekBar.getProgress() >= mView.getDuration()) {
+                    playerCompletion();
+                    return;
+                }
+                mView.seek(seekBar.getProgress());
+                mCurrent.setText(EduFoundUtil.getTime(mView.getCurrent()) + "/" + EduFoundUtil.getTime(mView.getDuration()));
+                mVideoHandler.sendEmptyMessage(SET_INFO);
+                mVideoHandler.sendEmptyMessage(SHOW_CONTROLLER);
+            }
+        });
+        mPlayerStatus.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                mView.start();
+                checkStatus(STATUS_PAUSE);
+                mPlayerStatus.setVisibility(View.INVISIBLE);
+                mVideoHandler.sendEmptyMessage(SHOW_CONTROLLER);
+            }
+        });
+    }
+
+    @Override
+    public void loadData() {
+        mModel.LoadData(new BaseModel.LoadDataBack() {
+            @Override
+            public void success(String datajson) {
+                Logger.DebugE("datajson:" + datajson);
+                mView.showData(datajson);
+            }
+
+            @Override
+            public void failure() {
+                Logger.e("failure");
+            }
+        });
+    }
+
+    @Override
+    public void onDisConnNetWork() {
+//        ToastUtil.showToast("播放器界面断网了...");
+        mView.stop();
+        mNetWorkErrorTime = mSeekbar.getProgress();
+        mVideoHandler.sendEmptyMessage(DISCONNECT_NETWORK);
+    }
+
+    @Override
+    public void onConnNetWork() {
+        mVideoHandler.removeMessages(DISCONNECT_NETWORK);
+    }
+
+
+    @Override
+    public void loadVideo(Intent intent) {
+        try {
+            String play_jsons = intent.getStringExtra("play_jsons");
+            mPlayIndex = intent.getIntExtra("play_index", 0);
+            mPlayType = intent.getIntExtra("play_type", 0);
+            mPlayerModuleType = intent.getStringExtra("play_moduletype");
+            mVideoBean = mGson.fromJson(play_jsons, VideoJsonBean[].class);
+//            mVideoBean = mGson.fromJson(video_json, VideoJsonBean.class);
+            mPlayingId = mVideoBean[mPlayIndex].videoid;
+            mPlayNeedPost = mVideoBean[mPlayIndex].videoneedpost;
+            mPlayStartTime = Integer.valueOf(mVideoBean[mPlayIndex].videoplaytime);
+            if (mVideoBean[mPlayIndex].videourl == null || mVideoBean[mPlayIndex].videourl.equals("") || mVideoBean[mPlayIndex].videourl.length() == 0) {
+                ToastUtil.showToast("URL是空的");
+                mView.activityFinish();
+                return;
+            }
+//            Logger.DebugE("mVideoBean[mPlayIndex].videourl:" + mVideoBean[mPlayIndex].videourl);
+            String decrypt = AesUtil.Decrypt(mVideoBean[mPlayIndex].videourl);
+//            Logger.DebugE("解密:" + decrypt);
+            if (mPlayType == TYPE_SINGLECYCLE_PLAY) {
+                SINGLECYCLE_URL = decrypt;
+            }
+//            decrypt = "http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4";
+            if (decrypt == null || !decrypt.contains("http")) {
+                ToastUtil.showToast("视频格式出现问题");
+//                mView.activityFinish();
+                return;
+            }
+            mView.setVideoUri(Uri.parse(decrypt));
+            mVideoName.setText(mVideoBean[mPlayIndex].videoname);
+            mVideoHandler.sendEmptyMessage(SET_INFO);
+            if (mPlayStartTime > 0) {
+                mView.seek(mPlayStartTime);
+            }
+            mView.start();
+            mVideoHandler.sendEmptyMessageDelayed(HIDE_CONTROLLER, HIDE_CONTROLLER_TIME);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+    }
+
+    @Override
+    public boolean onKeyDown(int keycode, KeyEvent event) {
+        if (!isPrepared || (mView.getDuration() == 0) || mSeekbar.getMax() == 0) {
+            if (keycode == KeyEvent.KEYCODE_BACK || keycode == KeyEvent.KEYCODE_ESCAPE) {
+
+            }
+            return true;
+        }
+        switch (keycode) {
+            case KeyEvent.KEYCODE_BACK:
+            case KeyEvent.KEYCODE_ESCAPE:
+
+                return true;
+        }
+        return false;
+    }
+
+    @Override
+    public boolean onKeyUp(int keycode, KeyEvent event) {
+        if (!isPrepared || (mView.getDuration() == 0) || mSeekbar.getMax() == 0) {
+            if (keycode == KeyEvent.KEYCODE_BACK || keycode == KeyEvent.KEYCODE_ESCAPE) {
+                mView.activityFinish();
+            }
+            return true;
+        }
+        switch (keycode) {
+            case KeyEvent.KEYCODE_BACK:
+            case KeyEvent.KEYCODE_ESCAPE:
+                removeHandler();
+                mView.activityFinish();
+                return true;
+        }
+        return false;
+    }
+
+    @Override
+    public void removeHandler() {
+        mVideoHandler.removeMessages(SET_INFO);
+        mVideoHandler.removeMessages(SHOW_CONTROLLER);
+        mVideoHandler.removeMessages(HIDE_CONTROLLER);
+    }
+
+    @Override
+    public View getPlayerController() {
+        return mFrameController;
+    }
+
+    @Override
+    public void showController() {
+        mVideoHandler.sendEmptyMessage(SHOW_CONTROLLER);
+    }
+
+    @Override
+    public void hideController() {
+        mVideoHandler.sendEmptyMessage(HIDE_CONTROLLER);
+    }
+
+    @Override
+    public boolean isShowController() {
+        return isControllerShow;
+    }
+
+    @Override
+    public void onCompletion() {
+        playerCompletion();
+    }
+
+    @Override
+    public void onPrepared() {
+        mLoadingAnim.stop();
+        isPrepared = true;
+        mPlayerLoading.setVisibility(View.INVISIBLE);
+    }
+
+    @Override
+    public void onInfo(int what, int extra) {
+        switch (what) {
+            case MediaPlayer.MEDIA_INFO_BUFFERING_START:
+                mLoadingAnim.start();
+                mPlayerLoading.setVisibility(View.VISIBLE);
+
+                break;
+            case MediaPlayer.MEDIA_INFO_BUFFERING_END:
+                mLoadingAnim.stop();
+                mPlayerLoading.setVisibility(View.INVISIBLE);
+                break;
+        }
+    }
+
+    @Override
+    public boolean onError(int what, int extra) {
+        switch (what) {
+            case -10000:
+                mVideoHandler.sendEmptyMessage(DISCONNECT_NETWORK);
+                ToastUtil.showToast("网络出现异常");
+                break;
+            default:
+                mView.stop();
+                ToastUtil.showToast("视频异常--what:" + what + "--extra:" + extra);
+                mVideoHandler.postDelayed(new Runnable() {
+                    @Override
+                    public void run() {
+                        mView.activityFinish();
+                    }
+                }, 2000);
+                break;
+        }
+        return true;
+    }
+
+    @Override
+    public void destroy() {
+        NotificationWebPlayerTime();
+        if (mStatusPlayBitmap != null && !mStatusPlayBitmap.isRecycled()) {
+            // 回收并且置为null
+            mStatusPlayBitmap.recycle();
+            mLittleIconPauseBitmap.recycle();
+            mLittleIconPlayBitmap.recycle();
+            mStatusPlayBitmap = null;
+            mLittleIconPauseBitmap = null;
+            mLittleIconPlayBitmap = null;
+        }
+        System.gc();
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        if (event.getAction() == MotionEvent.ACTION_UP) {
+            GESTURE_FLAG = 0;// 手指离开屏幕后,重置调节音量或进度的标志
+            mVideoHandler.sendEmptyMessageDelayed(HIDE_TOUCHVIEW, 3000);
+        }
+        return gestureDetector.onTouchEvent(event);
+    }
+
+    @Override
+    public void onSaveInstanceState(Bundle outState) {
+        //保存
+//        removeHandler();
+        mView.pause();
+        isSaveState = true;
+        Logger.e("onSaveInstanceState");
+    }
+
+    @Override
+    public void onRestoreInstanceState(Bundle savedInstanceState) {
+        //重新读取
+    }
+
+    @Override
+    public void onResume() {
+        if (isSaveState && (mErrorViewDialog.isShowing() == false)) {
+            mView.start();
+            checkStatus(STATUS_PAUSE);
+            mPlayerStatus.setVisibility(View.INVISIBLE);
+            mVideoHandler.sendEmptyMessage(SHOW_CONTROLLER);
+        }
+    }
+
+    Handler mVideoHandler = new Handler(new Handler.Callback() {
+        @Override
+        public boolean handleMessage(Message msg) {
+            switch (msg.what) {
+                case SET_INFO:
+                    mPlayerBackTime = mView.getCurrent();
+                    mSeekbar.setProgress(mView.getCurrent());
+                    mSeekbar.setMax(mView.getDuration());
+                    mCurrent.setText(EduFoundUtil.getTime(mView.getCurrent()) + "/" + EduFoundUtil.getTime(mView.getDuration()));
+                    mVideoHandler.sendEmptyMessageDelayed(SET_INFO, 1000);
+                    break;
+                case SHOW_CONTROLLER:
+                    isControllerShow = true;
+                    mVideoHandler.removeMessages(HIDE_CONTROLLER);
+                    mPlayerController.setVisibility(View.VISIBLE);
+                    mVideoHandler.sendEmptyMessageDelayed(HIDE_CONTROLLER, HIDE_CONTROLLER_TIME);
+                    break;
+                case HIDE_CONTROLLER:
+                    isControllerShow = false;
+                    mPlayerController.setVisibility(View.INVISIBLE);
+                    break;
+                case SHOW_STATUS_IMAGE:
+                    mPlayerStatus.setVisibility(View.VISIBLE);
+                    break;
+                case HIDE_STATUS_IMAGE:
+                    mPlayerStatus.setVisibility(View.INVISIBLE);
+                    break;
+                case PLAY_NEXT:
+                    removeHandler();
+                    mPlayIndex++;
+                    if (mPlayIndex > mVideoBean.length - 1) {
+                        mView.activityFinish();
+                    } else {
+                        try {
+                            ToastUtil.showToast("即将为您播放下一个:" + mVideoBean[mPlayIndex].videoname);
+                            mVideoName.setText(mVideoBean[mPlayIndex].videoname);
+                            mPlayingId = mVideoBean[mPlayIndex].videoid;
+                            mPlayNeedPost = mVideoBean[mPlayIndex].videoneedpost;
+                            mPlayStartTime = Integer.valueOf(mVideoBean[mPlayIndex].videoplaytime);
+                            if (Uri.parse(AesUtil.Decrypt(mVideoBean[mPlayIndex].videourl)) == null || Uri.parse(AesUtil.Decrypt(mVideoBean[mPlayIndex].videourl)).equals("")) {
+                                //可能是没权限,直接退出
+                                mView.activityFinish();
+//                                return true;
+                            } else {
+                                mVideoHandler.sendEmptyMessage(SET_INFO);
+                                mView.setVideoUri(Uri.parse(AesUtil.Decrypt(mVideoBean[mPlayIndex].videourl)));
+                                mVideoHandler.sendEmptyMessage(SHOW_CONTROLLER);
+                                mVideoHandler.sendEmptyMessage(SHOW_STATUS_IMAGE);
+                                mVideoHandler.sendEmptyMessageDelayed(HIDE_STATUS_IMAGE, 500);
+                                mView.start();
+                            }
+
+                        } catch (Exception e) {
+                            e.printStackTrace();
+                            mView.activityFinish();
+                        }
+                    }
+                    break;
+                case DISCONNECT_NETWORK:
+                    mVideoHandler.post(new Runnable() {
+                        @Override
+                        public void run() {
+                            showDisConnNeWorkWindow();
+                        }
+                    });
+                    break;
+                case CONNECT_NETWORK:
+                    try {
+                        if (mErrorViewDialog != null) {
+                            mErrorViewDialog.dismiss();
+                        }
+                        mView.stop();
+                        mView.releaseVideo();
+                        mView.setVideoUri(Uri.parse(AesUtil.Decrypt(mVideoBean[mPlayIndex].videourl)));
+                        mErrorViewDialog.dismiss();
+                        mView.seek(mNetWorkErrorTime);
+                        mView.start();
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                    }
+                    break;
+                case SHOW_TOUCHVIEW:
+                    mTouchView.setVisibility(View.VISIBLE);
+                    break;
+                case HIDE_TOUCHVIEW:
+                    mTouchView.setVisibility(View.GONE);
+                    break;
+            }
+            return false;
+        }
+    });
+
+
+    /*
+     * 切换status图片
+     * */
+    void checkStatus(final int status) {
+        mLittleIcon.post(new Runnable() {
+            @Override
+            public void run() {
+                switch (status) {
+                    case STATUS_PLAY:
+                        if (mStatusCode != STATUS_PLAY) {
+                            mStatusCode = STATUS_PLAY;
+                            mPlayerStatus.setImageBitmap(mStatusPlayBitmap);
+                            mLittleIcon.setImageBitmap(mLittleIconPlayBitmap);
+                        }
+                        break;
+                    case STATUS_PAUSE:
+                        if (mStatusCode != STATUS_PAUSE) {
+                            mStatusCode = STATUS_PAUSE;
+                            mLittleIcon.setImageBitmap(mLittleIconPauseBitmap);
+                        }
+                        break;
+                    case STATUS_FORWARD:
+                        if (mStatusCode != STATUS_FORWARD) {
+                            mStatusCode = STATUS_FORWARD;
+                        }
+                        break;
+                    case STATUS_REWIND:
+                        if (mStatusCode != STATUS_REWIND) {
+                            mStatusCode = STATUS_REWIND;
+                        }
+                        break;
+                }
+            }
+        });
+
+    }
+
+    void showDisConnNeWorkWindow() {
+        if (mErrorView == null) {
+            mErrorViewDialog = new Dialog(mView.getActivity());
+            try {
+                int dividerID = mView.getActivity().getResources().getIdentifier("android:id/titleDivider", null, null);
+                View divider = mErrorViewDialog.findViewById(dividerID);
+                divider.setBackgroundColor(Color.TRANSPARENT);
+            } catch (Exception e) {
+                //上面的代码,是用来去除Holo主题的蓝色线条
+                e.printStackTrace();
+            }
+            mErrorView = new ErrorView(mView);
+            mErrorView.setBtnClickListener(new ErrorView.BtnClickListener() {
+                @Override
+                public void clickRelase() {
+//                    mView.start();
+                    try {
+                        if (ContextUtil.getNetWorkState()) {
+                            mView.stop();
+                            mView.releaseVideo();
+                            mView.setVideoUri(Uri.parse(AesUtil.Decrypt(mVideoBean[mPlayIndex].videourl)));
+                            mErrorViewDialog.dismiss();
+                            mView.seek(mNetWorkErrorTime);
+                            mView.start();
+                        } else {
+                            ToastUtil.showToast("请检查网络连接状况");
+                        }
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                    }
+                }
+
+                @Override
+                public void clickExit() {
+                    mErrorViewDialog.dismiss();
+                    EApplication.clearActivity();
+                    Intent intent_restart = new Intent(ContextUtil.CLOSE_ACTIVITY_MAIN);
+                    mView.getActivity().sendBroadcast(intent_restart);
+                    System.exit(0);
+                }
+            });
+            mErrorViewDialog.setCancelable(false);
+            mErrorViewDialog.setContentView(mErrorView);
+            Window dialogWindow = mErrorViewDialog.getWindow();
+            dialogWindow.setGravity(Gravity.CENTER);
+            dialogWindow.getDecorView().setPadding(0, 0, 0, 0);
+            dialogWindow.getDecorView().setBackgroundColor(Color.parseColor("#80000000"));
+            WindowManager m = mView.getActivity().getWindowManager();
+            Display d = m.getDefaultDisplay(); // 获取屏幕宽、高用
+            WindowManager.LayoutParams p = dialogWindow.getAttributes(); // 获取对话框当前的参数值
+            p.height = (int) (d.getHeight() * 1);
+            p.width = WindowManager.LayoutParams.MATCH_PARENT;
+            p.horizontalMargin = 0;
+            dialogWindow.setAttributes(p);
+        }
+        if (!mErrorViewDialog.isShowing()) {
+            mErrorViewDialog.show();
+        }
+    }
+
+
+    void playerCompletion() {
+        mPlayerBackTime = 0;
+        switch (mPlayType) {
+            case TYPE_SEPARATELY_PLAY:
+                ToastUtil.showToast("播放完成");
+                removeHandler();
+                mView.activityFinish();
+                break;
+            case TYPE_SINGLECYCLE_PLAY:
+                ToastUtil.showToast("重新播放");
+                removeHandler();
+                mVideoHandler.sendEmptyMessage(SET_INFO);
+                mView.seek(0);
+                mView.start();
+                return;
+            case TYPE_LIST_PLAY:
+                NotificationWebPlayerTime();
+                mVideoHandler.sendEmptyMessage(PLAY_NEXT);
+                return;
+        }
+    }
+
+
+    public void NotificationWebPlayerTime() {
+        Intent intent = new Intent(ContextUtil.NOTIFICATION_WEB_PLAYERTIME);
+        intent.putExtra("over_time", String.valueOf(mPlayerBackTime));
+        intent.putExtra("over_id", String.valueOf(mPlayingId));
+        intent.putExtra("over_neetpost", mPlayNeedPost);
+        intent.putExtra("over_moduletype", mPlayerModuleType);
+        mView.getActivity().sendBroadcast(intent);
+    }
+
+    private boolean firstScroll = false;
+    private int GESTURE_FLAG = 0;// 1,调节进度,2,调节音量,3.调节亮度
+    private static final int GESTURE_MODIFY_PROGRESS = 1;
+    private static final int GESTURE_MODIFY_VOLUME = 2;
+    private static final int GESTURE_MODIFY_BRIGHT = 3;
+    private int playerWidth;
+    private int maxVolume, currentVolume;
+    private AudioManager audiomanager;
+    private float mBrightness = -1f; // 亮度
+    private static final float STEP_PROGRESS = 3f;// 设定进度滑动时的步长,避免每次滑动都改变,导致改变过快
+    private static final float STEP_VOLUME = 3f;// 协调音量滑动时的步长,避免每次滑动都改变,导致改变过快
+
+    @Override
+    public boolean onDown(MotionEvent e) {
+        firstScroll = true;// 设定是触摸屏幕后第一次scroll的标志
+        return false;
+    }
+
+    @Override
+    public void onShowPress(MotionEvent e) {
+
+    }
+
+    @Override
+    public boolean onSingleTapUp(MotionEvent e) {
+        return true;
+    }
+
+
+    @Override
+    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
+        // TODO Auto-generated method stub
+        mVideoHandler.removeMessages(HIDE_TOUCHVIEW);
+        float mOldX = e1.getX(), mOldY = e1.getY();
+        int y = (int) e2.getRawY();
+        if (firstScroll) {// 以触摸屏幕后第一次滑动为标准,避免在屏幕上操作切换混乱
+            // 横向的距离变化大则调整进度,纵向的变化大则调整音量
+            if (Math.abs(distanceX) >= Math.abs(distanceY)) {
+                GESTURE_FLAG = GESTURE_MODIFY_PROGRESS;
+            } else {
+                if (mOldX > playerWidth / 2.0f) {// 音量
+                    GESTURE_FLAG = GESTURE_MODIFY_VOLUME;
+                } else if (mOldX < playerWidth / 2.0f) {// 亮度
+                    GESTURE_FLAG = GESTURE_MODIFY_BRIGHT;
+                }
+            }
+        }
+        // 如果每次触摸屏幕后第一次scroll是调节进度,那之后的scroll事件都处理音量进度,直到离开屏幕执行下一次操作
+        if (GESTURE_FLAG == GESTURE_MODIFY_PROGRESS) {
+
+        }
+        // 如果每次触摸屏幕后第一次scroll是调节音量,那之后的scroll事件都处理音量调节,直到离开屏幕执行下一次操作
+        else if (GESTURE_FLAG == GESTURE_MODIFY_VOLUME) {
+            currentVolume = audiomanager.getStreamVolume(AudioManager.STREAM_MUSIC); // 获取当前值
+            mTouchSeek.setProgress(currentVolume);
+            if (Math.abs(distanceY) > Math.abs(distanceX)) {// 纵向移动大于横向移动
+                if (distanceY >= dip2px(STEP_VOLUME)) {// 音量调大,注意横屏时的坐标体系,尽管左上角是原点,但横向向上滑动时distanceY为正
+                    if (currentVolume < maxVolume) {// 为避免调节过快,distanceY应大于一个设定值
+                        currentVolume = currentVolume + oneVolume;
+                    }
+//                    gesture_iv_player_volume.setImageResource(R.drawable.souhu_player_volume);
+                } else if (distanceY <= -dip2px(STEP_VOLUME)) {// 音量调小
+                    if (currentVolume > 0) {
+                        currentVolume = currentVolume - oneVolume;
+                        if (currentVolume == 0) {// 静音,设定静音独有的图片
+//                            gesture_iv_player_volume
+//                                    .setImageResource(R.drawable.souhu_player_silence);
+                        }
+                    }
+                }
+//                geture_tv_volume_percentage.setText(percentage + "%");
+                mTouchText.setText("音量");
+                mTouchIcon.setImageBitmap(BitmapFactory.decodeResource(mView.getActivity().getResources(), R.drawable.player_volume_icon));
+                mVideoHandler.sendEmptyMessage(SHOW_TOUCHVIEW);
+                mTouchSeek.setProgress((currentVolume));
+                audiomanager.setStreamVolume(AudioManager.STREAM_MUSIC, currentVolume, 0);
+            }
+        }
+        // 如果每次触摸屏幕后第一次scroll是调节亮度,那之后的scroll事件都处理亮度调节,直到离开屏幕执行下一次操作
+        else if (GESTURE_FLAG == GESTURE_MODIFY_BRIGHT) {
+            Logger.e("亮度....");
+            WindowManager.LayoutParams lpa = mView.getActivity().getWindow().getAttributes();
+//            gesture_iv_player_bright.setImageResource(R.drawable.souhu_player_bright);
+            mTouchSeek.setProgress(lpa.screenBrightness);
+            if (mBrightness < 0) {
+                mBrightness = mView.getActivity().getWindow().getAttributes().screenBrightness;
+                if (mBrightness <= 0.00f)
+                    mBrightness = 0.00f;
+            }
+            if (Math.abs(distanceY) > Math.abs(distanceX)) {// 纵向移动大于横向移动
+                if (distanceY >= dip2px(STEP_VOLUME)) {
+                    if (mBrightness < 1.0f) {// 为避免调节过快,distanceY应大于一个设定值
+                        mBrightness += 0.1f;
+                    }
+                } else if (distanceY <= -dip2px(STEP_VOLUME)) {
+                    if (mBrightness > 0) {
+                        mBrightness -= 0.1f;
+                    }
+                }
+            }
+            if (mBrightness > 1.0f) {
+                mBrightness = 1.0f;
+            } else if (mBrightness < 0.01f) {
+                mBrightness = 0.01f;
+            }
+            lpa.screenBrightness = mBrightness;
+            mTouchText.setText("亮度");
+            mTouchIcon.setImageBitmap(BitmapFactory.decodeResource(mView.getActivity().getResources(), R.drawable.player_brightness_icon));
+            mVideoHandler.sendEmptyMessage(SHOW_TOUCHVIEW);
+            mTouchSeek.setProgress((mBrightness * 10));
+            mView.getActivity().getWindow().setAttributes(lpa);
+//            geture_tv_bright_percentage.setText((int) (lpa.screenBrightness * 100) + "%");
+        }
+
+        firstScroll = false;// 第一次scroll执行完成,修改标志
+        return false;
+    }
+
+    public int dip2px(float dpValue) {
+        final float scale = mView.getActivity().getResources().getDisplayMetrics().density;
+        return (int) (dpValue * scale + 0.5f);
+    }
+
+    @Override
+    public void onLongPress(MotionEvent e) {
+
+    }
+
+    @Override
+    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
+        return false;
+    }
+
+    @Override
+    public boolean onSingleTapConfirmed(MotionEvent e) {
+        Logger.e("onSingleTapConfirmed");
+        if (mPersenter.isShowController()) {
+            mPersenter.hideController();
+        } else {
+            mPersenter.showController();
+        }
+        return false;
+    }
+
+    @Override
+    public boolean onDoubleTap(MotionEvent e) {
+        Logger.e("onDoubleTap");
+        if (mView.isPlaying()) {
+            mView.pause();
+            mPersenter.checkStatus(mPersenter.STATUS_PLAY);
+            mPersenter.mVideoHandler.sendEmptyMessage(mPersenter.SHOW_STATUS_IMAGE);
+            mPersenter.mVideoHandler.sendEmptyMessage(mPersenter.SHOW_CONTROLLER);
+        } else {
+            mView.start();
+            mPersenter.checkStatus(mPersenter.STATUS_PAUSE);
+            mPersenter.mPlayerStatus.setVisibility(View.INVISIBLE);
+            mPersenter.mVideoHandler.sendEmptyMessage(mPersenter.SHOW_CONTROLLER);
+        }
+        return false;
+    }
+
+    @Override
+    public boolean onDoubleTapEvent(MotionEvent e) {
+        return false;
+    }
+}
+
+
+interface VideoIPersenter extends BasePersenter {
+    void loadVideo(Intent intent);
+
+    boolean onKeyDown(int keycode, KeyEvent event);
+
+    boolean onKeyUp(int keycode, KeyEvent event);
+
+    void removeHandler();
+
+    View getPlayerController();
+
+    void showController();
+
+    void hideController();
+
+    boolean isShowController();
+
+    void onCompletion();
+
+    void onPrepared();
+
+    void onInfo(int what, int extra);
+
+    boolean onError(int what, int extra);
+
+    void destroy();
+
+    boolean onTouchEvent(MotionEvent event);
+
+    void onSaveInstanceState(Bundle outState);
+
+    void onRestoreInstanceState(Bundle savedInstanceState);
+
+    void onResume();
+
+}
+
+class VideoJsonBean {
+    public String videourl;
+    public String videoname;
+    public String videoid;
+    public String videoplaytime;
+    public String videoneedpost;
+}

+ 98 - 0
app/src/main/java/com/edufound/mobile/view/ErrorView.java

@@ -0,0 +1,98 @@
+package com.edufound.mobile.view;
+
+import android.content.Context;
+import android.graphics.Color;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.FrameLayout;
+import android.widget.TextView;
+
+import com.edufound.mobile.R;
+import com.edufound.mobile.base.BaseView;
+import com.edufound.mobile.util.ToastUtil;
+
+public class ErrorView extends FrameLayout {
+    BaseView mView;
+    View LayoutView;
+    BtnClickListener mListener;
+
+    public ErrorView(BaseView view) {
+        super(view.getActivity());
+        initView(view.getActivity());
+        mView = view;
+    }
+
+    void initView(Context context) {
+        LayoutView = LayoutInflater.from(context).inflate(R.layout.window_disconnect_network, null);
+        final TextView release = LayoutView.findViewById(R.id.window_disconnect_network_relase);
+        final TextView exit = LayoutView.findViewById(R.id.window_disconnect_network_exit);
+        release.setOnFocusChangeListener(errorViewFocus);
+        exit.setOnFocusChangeListener(errorViewFocus);
+        release.setOnClickListener(errorViewClick);
+        exit.setOnClickListener(errorViewClick);
+        addView(LayoutView);
+        release.postDelayed(new Runnable() {
+            @Override
+            public void run() {
+                release.requestFocus();
+            }
+        }, 500);
+    }
+
+    public void setViewBgColor(int color) {
+        LayoutView.setBackgroundColor(color);
+    }
+
+    public void setBtnClickListener(BtnClickListener listener) {
+        mListener = listener;
+    }
+
+    View.OnFocusChangeListener errorViewFocus = new View.OnFocusChangeListener() {
+        @Override
+        public void onFocusChange(View v, boolean hasFocus) {
+            switch (v.getId()) {
+                case R.id.window_disconnect_network_relase:
+                case R.id.window_disconnect_network_exit:
+                    if (hasFocus) {
+                        v.setBackgroundResource(R.drawable.window_disconnect_network_text_bgfocus);
+                        ((TextView) v).setTextColor(Color.WHITE);
+                    } else {
+                        v.setBackgroundResource(R.drawable.window_disconnect_network_text_bg);
+                        ((TextView) v).setTextColor(Color.parseColor("#ff767676"));
+                    }
+                    break;
+            }
+        }
+    };
+
+    //修改为通过发广播的方式,试试能不能退出什么的
+    View.OnClickListener errorViewClick = new View.OnClickListener() {
+        @Override
+        public void onClick(View v) {
+            switch (v.getId()) {
+                case R.id.window_disconnect_network_relase:
+                    if (mListener == null) {
+                        ToastUtil.showToast("未设置事件");
+                        return;
+                    }
+                    mListener.clickRelase();
+                    break;
+                case R.id.window_disconnect_network_exit:
+                    if (mListener == null) {
+                        ToastUtil.showToast("未设置事件");
+                        return;
+                    }
+                    mListener.clickExit();
+                    break;
+            }
+        }
+    };
+
+    public interface BtnClickListener {
+        void clickRelase();
+
+        void clickExit();
+    }
+}
+
+

+ 147 - 0
app/src/main/java/com/edufound/mobile/wxapi/WXEntryActivity.java

@@ -0,0 +1,147 @@
+package com.edufound.mobile.wxapi;
+
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.support.annotation.RequiresApi;
+import android.view.WindowManager;
+
+import com.edufound.mobile.base.BaseActivity;
+import com.edufound.mobile.main.MainPersenter;
+import com.edufound.mobile.pay.PayInit;
+import com.edufound.mobile.util.Logger;
+import com.edufound.mobile.util.OKHttpUtil;
+import com.tencent.mm.opensdk.constants.ConstantsAPI;
+import com.tencent.mm.opensdk.modelbase.BaseReq;
+import com.tencent.mm.opensdk.modelbase.BaseResp;
+import com.tencent.mm.opensdk.modelbiz.WXLaunchMiniProgram;
+import com.tencent.mm.opensdk.modelmsg.SendAuth;
+import com.tencent.mm.opensdk.openapi.IWXAPIEventHandler;
+import com.tencent.mm.opensdk.openapi.WXAPIFactory;
+
+import org.json.JSONException;
+
+import java.io.IOException;
+
+import okhttp3.Call;
+import okhttp3.Callback;
+import okhttp3.Response;
+
+
+public class WXEntryActivity extends BaseActivity implements IWXAPIEventHandler {
+
+
+    @RequiresApi(api = Build.VERSION_CODES.P)
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
+                WindowManager.LayoutParams.FLAG_FULLSCREEN);
+        PayInit.getInstance().WX_API = WXAPIFactory.createWXAPI(this, PayInit.getInstance().WX_APPID);
+        PayInit.getInstance().WX_API.handleIntent(getIntent(), this);
+
+
+    }
+
+    @Override
+    public void onReq(BaseReq baseReq) {
+    }
+
+    //请求回调结果处理
+    @Override
+    public void onResp(BaseResp baseResp) {
+        if (baseResp.getType() == ConstantsAPI.COMMAND_LAUNCH_WX_MINIPROGRAM) {
+//            WXLaunchMiniProgram.Resp launchMiniProResp = (WXLaunchMiniProgram.Resp) baseResp;
+//            String extraData = launchMiniProResp.extMsg; //对应小程序组件 <button open-type="launchApp"> 中的 app-parameter 属性
+//            MainActivity.mIntences.mWebView.loadUrl("javascript:appDispatch('" + extraData + "')");
+//            Intent intent = new Intent(mActivity, MainActivity.class);
+//            startActivity(intent);
+//            finish();
+        } else {
+            switch (baseResp.errCode) {
+                case BaseResp.ErrCode.ERR_OK:
+                    String code = ((SendAuth.Resp) baseResp).code;
+                    //获取用户信息
+                    getAccessToken(code);
+                    break;
+                case BaseResp.ErrCode.ERR_AUTH_DENIED://用户拒绝授权
+                    finish();
+                    break;
+                case BaseResp.ErrCode.ERR_USER_CANCEL://用户取消
+                    finish();
+                    break;
+                default:
+                    Logger.e("baseResp.errCode:" + baseResp.errCode);
+                    finish();
+                    break;
+            }
+        }
+
+    }
+
+    void getAccessToken(String code) {
+        StringBuffer loginUrl = new StringBuffer();
+        loginUrl.append("https://api.weixin.qq.com/sns/oauth2/access_token")
+                .append("?appid=")
+                .append(PayInit.getInstance().WX_APPID)
+                .append("&secret=")
+                .append(PayInit.getInstance().WX_SECRET)
+                .append("&code=")
+                .append(code)
+                .append("&grant_type=authorization_code");
+        try {
+            OKHttpUtil.getInstance().getContentLength(loginUrl.toString(), new Callback() {
+                @Override
+                public void onFailure(Call call, IOException e) {
+
+                }
+
+                @Override
+                public void onResponse(Call call, Response response) throws IOException {
+                    String access = null;
+                    String openId = null;
+                    try {
+                        String json = response.body().string();
+                        org.json.JSONObject jsonObj = new org.json.JSONObject(json);
+                        access = jsonObj.getString("access_token");
+                        openId = jsonObj.getString("openid");
+                    } catch (JSONException e) {
+                        e.printStackTrace();
+                    }
+                    String getUserInfo = "https://api.weixin.qq.com/sns/userinfo?access_token=" + access + "&openid=" + openId;
+                    OKHttpUtil.getInstance().getContentLength(getUserInfo, new Callback() {
+                        @Override
+                        public void onFailure(Call call, IOException e) {
+
+                        }
+
+                        @Override
+                        public void onResponse(Call call, Response response) throws IOException {
+                            try {
+                                String json = response.body().string();
+                                Message msg = new Message();
+                                msg.what = MainPersenter.WECHAT_LOGIN;
+                                msg.obj = json;
+                                MainPersenter.mPersenterHandler.sendMessage(msg);
+                                finish();
+                            } catch (Exception e) {
+                                e.printStackTrace();
+                            }
+                        }
+                    });
+                }
+            });
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Override
+    protected void onPause() {
+        overridePendingTransition(0, 0);
+        super.onPause();
+    }
+
+
+}

+ 68 - 0
app/src/main/java/com/edufound/mobile/wxapi/WXPayEntryActivity.java

@@ -0,0 +1,68 @@
+package com.edufound.mobile.wxapi;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Message;
+
+import com.edufound.mobile.R;
+import com.edufound.mobile.main.MainPersenter;
+import com.edufound.mobile.pay.PayInit;
+import com.edufound.mobile.util.ContextUtil;
+import com.tencent.mm.opensdk.constants.ConstantsAPI;
+import com.tencent.mm.opensdk.modelbase.BaseReq;
+import com.tencent.mm.opensdk.modelbase.BaseResp;
+import com.tencent.mm.opensdk.openapi.IWXAPI;
+import com.tencent.mm.opensdk.openapi.IWXAPIEventHandler;
+import com.tencent.mm.opensdk.openapi.WXAPIFactory;
+
+public class WXPayEntryActivity extends Activity implements IWXAPIEventHandler {
+
+    private static final String TAG = WXPayEntryActivity.class.getSimpleName();
+
+    private IWXAPI api;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.pay_result);
+        api = WXAPIFactory.createWXAPI(this, PayInit.getInstance().WX_APPID);
+        api.handleIntent(getIntent(), this);
+
+    }
+
+    @Override
+    protected void onNewIntent(Intent intent) {
+        super.onNewIntent(intent);
+        setIntent(intent);
+        api.handleIntent(intent, this);
+    }
+
+    @Override
+    public void onReq(BaseReq baseReq) {
+
+    }
+
+    @Override
+    public void onResp(BaseResp baseResp) {
+        if (baseResp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) {
+            Message msg = new Message();
+            msg.what = MainPersenter.PAY_RESULT;
+            msg.obj = baseResp.errCode;
+            MainPersenter.mPersenterHandler.sendMessage(msg);
+            Intent intent_restart = new Intent(ContextUtil.CLOSE_ACTIVITY_PAY);
+            sendBroadcast(intent_restart);
+            finish();
+//            if (baseResp.errCode == 0) {// 支付成功
+////                CustomToast.showToast(this, "支付成功", 3000);
+//                finish();
+//            } else if (baseResp.errCode == -2) {// 用户取消支付
+////                CustomToast.showToast(this, "支付已取消", 3000);
+//                finish();
+//            } else {// 支付失败
+////                CustomToast.showToast(this, "支付失败:" + baseResp.errCode + "--:baseResp.errStr" + baseResp.errStr, 3000);
+//                finish();
+//            }
+        }
+    }
+}

File diff suppressed because it is too large
+ 34 - 0
app/src/main/res/drawable-v24/ic_launcher_foreground.xml


+ 66 - 0
app/src/main/res/drawable/edufound_loading.xml

@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8"?>
+<animation-list xmlns:apk="http://schemas.android.com/apk/res/android"
+    apk:oneshot="false">
+    <item
+        apk:drawable="@drawable/loading1"
+        apk:duration="10" />
+    <item
+        apk:drawable="@drawable/loading2"
+        apk:duration="10" />
+    <item
+        apk:drawable="@drawable/loading3"
+        apk:duration="10" />
+    <item
+        apk:drawable="@drawable/loading4"
+        apk:duration="10" />
+    <item
+        apk:drawable="@drawable/loading5"
+        apk:duration="10" />
+    <item
+        apk:drawable="@drawable/loading6"
+        apk:duration="10" />
+    <item
+        apk:drawable="@drawable/loading7"
+        apk:duration="10" />
+    <item
+        apk:drawable="@drawable/loading8"
+        apk:duration="10" />
+    <item
+        apk:drawable="@drawable/loading9"
+        apk:duration="10" />
+    <item
+        apk:drawable="@drawable/loading10"
+        apk:duration="10" />
+    <item
+        apk:drawable="@drawable/loading11"
+        apk:duration="10" />
+    <item
+        apk:drawable="@drawable/loading12"
+        apk:duration="10" />
+    <item
+        apk:drawable="@drawable/loading13"
+        apk:duration="10" />
+    <item
+        apk:drawable="@drawable/loading14"
+        apk:duration="10" />
+    <item
+        apk:drawable="@drawable/loading15"
+        apk:duration="10" />
+    <item
+        apk:drawable="@drawable/loading16"
+        apk:duration="10" />
+    <item
+        apk:drawable="@drawable/loading17"
+        apk:duration="10" />
+    <item
+        apk:drawable="@drawable/loading18"
+        apk:duration="10" />
+    <item
+        apk:drawable="@drawable/loading19"
+        apk:duration="10" />
+    <item
+        apk:drawable="@drawable/loading20"
+        apk:duration="10" />
+
+
+</animation-list>

BIN
app/src/main/res/drawable/edufound_player_pause.png


BIN
app/src/main/res/drawable/edufound_player_play.png


BIN
app/src/main/res/drawable/efunbox_window_bg.jpg


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

BIN
app/src/main/res/drawable/icon_mobile_256_v8.png


BIN
app/src/main/res/drawable/loading1.png


BIN
app/src/main/res/drawable/loading10.png


BIN
app/src/main/res/drawable/loading11.png


BIN
app/src/main/res/drawable/loading12.png


BIN
app/src/main/res/drawable/loading13.png


BIN
app/src/main/res/drawable/loading14.png


BIN
app/src/main/res/drawable/loading15.png


BIN
app/src/main/res/drawable/loading16.png


BIN
app/src/main/res/drawable/loading17.png


BIN
app/src/main/res/drawable/loading18.png


BIN
app/src/main/res/drawable/loading19.png


BIN
app/src/main/res/drawable/loading2.png


BIN
app/src/main/res/drawable/loading20.png


BIN
app/src/main/res/drawable/loading3.png


BIN
app/src/main/res/drawable/loading4.png


BIN
app/src/main/res/drawable/loading5.png


BIN
app/src/main/res/drawable/loading6.png


+ 0 - 0
app/src/main/res/drawable/loading7.png


Some files were not shown because too many files changed in this diff