Переглянути джерело

1.增加全局异常弹窗处理
2.增加网络监听(不知道怎么处理断网后逻辑)

FailedToRead 3 роки тому
батько
коміт
ff099a4ab2

+ 5 - 0
.idea/jarRepositories.xml

@@ -26,5 +26,10 @@
       <option name="name" value="MavenRepo" />
       <option name="url" value="https://repo.maven.apache.org/maven2/" />
     </remote-repository>
+    <remote-repository>
+      <option name="id" value="maven" />
+      <option name="name" value="maven" />
+      <option name="url" value="https://oss.jfrog.org/libs-snapshot" />
+    </remote-repository>
   </component>
 </project>

+ 1 - 0
.idea/misc.xml

@@ -5,6 +5,7 @@
       <map>
         <entry key="..\:/WorkSpace/Git_WorkSpace/efunboxReader-android/efunboxReader-android-master/app/src/main/res/drawable/cusjzplayer_controller_seekbar.xml" value="0.2713541666666667" />
         <entry key="..\:/WorkSpace/Git_WorkSpace/efunboxReader-android/efunboxReader-android-master/app/src/main/res/drawable/player_seekbar_list.xml" value="0.2713541666666667" />
+        <entry key="..\:/WorkSpace/Git_WorkSpace/efunboxReader-android/efunboxReader-android-master/app/src/main/res/layout/activity_crash_dialog.xml" value="0.2" />
         <entry key="..\:/WorkSpace/Git_WorkSpace/efunboxReader-android/efunboxReader-android-master/app/src/main/res/layout/activity_main.xml" value="0.25" />
         <entry key="..\:/WorkSpace/Git_WorkSpace/efunboxReader-android/efunboxReader-android-master/app/src/main/res/layout/activity_video.xml" value="0.1331521739130435" />
         <entry key="..\:/WorkSpace/Git_WorkSpace/efunboxReader-android/efunboxReader-android-master/app/src/main/res/layout/adapter_item_slidevideo.xml" value="0.18177083333333333" />

+ 3 - 0
app/build.gradle

@@ -121,4 +121,7 @@ dependencies {
     //驰声
     implementation 'io.github.ChivoxSupport:vox-sdk:2.2.23+2.0.8.1'
 
+
+    //rxBind
+    implementation 'com.jakewharton.rxbinding4:rxbinding:4.0.0'
 }

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

@@ -6,6 +6,7 @@
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
     <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+    <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
     <uses-permission android:name="android.permission.READ_PHONE_STATE" />
     <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /><!-- 切换⽹络通道 -->
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><!-- 本地信息缓存 -->
@@ -55,6 +56,14 @@
                 android:screenOrientation="landscape"
                 android:theme="@style/Theme.AppCompat.Light.NoActionBar.FullScreen"
                 android:windowSoftInputMode="adjustNothing|stateHidden"></activity>
+        <activity
+                android:name="com.edufound.reader.activity.CrashDialogActivity"
+                android:configChanges="screenLayout|screenSize|keyboardHidden|keyboard|orientation"
+                android:maxAspectRatio="2.1"
+                android:resizeableActivity="true"
+                android:screenOrientation="landscape"
+                android:theme="@style/Theme.AppCompat.Light.NoActionBar.FullScreen"
+                android:windowSoftInputMode="adjustNothing|stateHidden"></activity>
         <!--友盟start-->
         <meta-data
                 android:name="UMENG_APPKEY"

+ 81 - 0
app/src/main/java/com/edufound/reader/activity/CrashDialogActivity.java

@@ -0,0 +1,81 @@
+package com.edufound.reader.activity;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.os.Bundle;
+
+import com.edufound.reader.R;
+import com.edufound.reader.application.EApplication;
+import com.edufound.reader.base.BaseMvpActivity;
+import com.edufound.reader.contract.CrashDialogContract;
+import com.edufound.reader.contract.MainContract;
+import com.edufound.reader.presenter.CrashDialogPresenter;
+import com.edufound.reader.presenter.VideoPresenter;
+
+import androidx.annotation.Nullable;
+
+public class CrashDialogActivity extends BaseMvpActivity<CrashDialogPresenter> implements CrashDialogContract.View {
+
+    Activity mActivity;
+
+
+    @Override
+    public int getLayoutId() {
+        return R.layout.activity_crash_dialog;
+    }
+
+    @Override
+    public void initView() {
+        mPresenter = new CrashDialogPresenter();
+        mPresenter.attachView(this);
+        mActivity = this;
+        AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
+        builder.setTitle("error");
+        builder.setIcon(R.drawable.icon);
+        builder.setMessage("出现异常");
+        builder.setNegativeButton("退出", new DialogInterface.OnClickListener() {
+            @Override
+            public void onClick(DialogInterface dialogInterface, int i) {
+                dialogInterface.dismiss();
+                EApplication.killAppProcess(mActivity);
+            }
+        });
+        builder.create().show();
+    }
+
+    @Override
+    public void onDisconnect() {
+
+    }
+
+    @Override
+    public void onMobileConnect() {
+
+    }
+
+    @Override
+    public void onWifiConnect() {
+
+    }
+
+    @Override
+    public void showLoading() {
+
+    }
+
+    @Override
+    public void hideLoading() {
+
+    }
+
+    @Override
+    public void onError(String errMessage) {
+
+    }
+
+    @Override
+    public Activity getActivity() {
+        return mActivity;
+    }
+}

+ 51 - 20
app/src/main/java/com/edufound/reader/activity/MainActivity.java

@@ -1,6 +1,8 @@
 package com.edufound.reader.activity;
 
+import android.annotation.SuppressLint;
 import android.app.Activity;
+import android.view.KeyEvent;
 import android.view.View;
 import android.widget.Button;
 
@@ -9,10 +11,19 @@ import com.edufound.reader.annotation.BindView;
 import com.edufound.reader.base.BaseMvpActivity;
 import com.edufound.reader.contract.MainContract;
 import com.edufound.reader.presenter.MainPresenter;
+import com.jakewharton.rxbinding4.view.RxView;
+import com.orhanobut.logger.Logger;
+
+import java.util.concurrent.TimeUnit;
 
 import androidx.recyclerview.widget.RecyclerView;
 import cn.jzvd.Jzvd;
 import cn.jzvd.JzvdStd;
+import io.reactivex.rxjava3.annotations.NonNull;
+import io.reactivex.rxjava3.core.Observer;
+import io.reactivex.rxjava3.disposables.Disposable;
+import io.reactivex.rxjava3.functions.Consumer;
+import kotlin.Unit;
 
 public class MainActivity extends BaseMvpActivity<MainPresenter> implements MainContract.View {
 
@@ -38,39 +49,49 @@ public class MainActivity extends BaseMvpActivity<MainPresenter> implements Main
         return R.layout.activity_main;
     }
 
+    @SuppressLint("AutoDispose")
     @Override
     public void initView() {
         mPresenter = new MainPresenter();
         mPresenter.attachView(this);
         mActivity = this;
 //        GlideUtils.loadImageSizeKipMemoryCache(this, "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic1.zhimg.com%2F50%2Fv2-a96199f59f76eef6698e572c19944e40_hd.jpg&refer=http%3A%2F%2Fpic1.zhimg.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1640338680&t=511cd171a44a99e646ce6063b751c78f", mImage);
-
         mPresenter.bindRecordServices();
-        btn_main_initrecord.setOnClickListener(new View.OnClickListener() {
-            @Override
-            public void onClick(View view) {
-                mPresenter.startRecord("123", "1234567");
-            }
-        });
-
-        main_stoprecord.setOnClickListener(new View.OnClickListener() {
-            @Override
-            public void onClick(View view) {
-                mPresenter.stopRecord();
-            }
-        });
-        main_playrecord.setOnClickListener(new View.OnClickListener() {
-            @Override
-            public void onClick(View view) {
-                mPresenter.rePlayRecord();
-            }
-        });
+        addDisposable(RxView.clicks(btn_main_initrecord).throttleFirst(2, TimeUnit.SECONDS)
+                .subscribe(o -> {
+                    mPresenter.startRecord("123", "1234567");
+                }));
+
+        addDisposable(RxView.clicks(main_stoprecord).throttleFirst(2, TimeUnit.SECONDS)
+                .subscribe(o -> {
+                    mPresenter.stopRecord();
+                }));
+
+        addDisposable(RxView.clicks(main_playrecord).throttleFirst(2, TimeUnit.SECONDS)
+                .subscribe(o -> {
+                    mPresenter.rePlayRecord();
+                }));
 
         mPresenter.initVideoList(mRecyclerView);
 
     }
 
     @Override
+    public void onDisconnect() {
+        
+    }
+
+    @Override
+    public void onMobileConnect() {
+
+    }
+
+    @Override
+    public void onWifiConnect() {
+
+    }
+
+    @Override
     public void showLoading() {
 
     }
@@ -111,4 +132,14 @@ public class MainActivity extends BaseMvpActivity<MainPresenter> implements Main
         JzvdStd.goOnPlayOnResume();
     }
 
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        mPresenter.activityDestroy();
+    }
+
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        return mPresenter.onKeyDown(keyCode, event);
+    }
 }

+ 15 - 0
app/src/main/java/com/edufound/reader/activity/VideoActivity.java

@@ -37,6 +37,21 @@ public class VideoActivity extends BaseMvpActivity<VideoPresenter> implements Vi
     }
 
     @Override
+    public void onDisconnect() {
+        
+    }
+
+    @Override
+    public void onMobileConnect() {
+
+    }
+
+    @Override
+    public void onWifiConnect() {
+
+    }
+
+    @Override
     public void showLoading() {
 
     }

+ 82 - 0
app/src/main/java/com/edufound/reader/application/EApplication.java

@@ -1,9 +1,16 @@
 package com.edufound.reader.application;
 
+import android.app.Activity;
+import android.app.ActivityManager;
 import android.app.Application;
+import android.content.Context;
+import android.os.Build;
+import android.os.Bundle;
 import android.os.Environment;
+import android.os.Process;
 
 import com.edufound.reader.util.Consts;
+import com.edufound.reader.util.CrashHandler;
 import com.edufound.reader.util.HttpInterceptor;
 import com.okhttplib.OkHttpUtil;
 import com.okhttplib.annotation.CacheType;
@@ -22,13 +29,25 @@ import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlPullParserFactory;
 
 import java.io.File;
+import java.util.List;
+
+import okhttp3.Request;
 
 public class EApplication extends Application {
+
+    private int activityAount = 0;
+    public boolean isForeground = false;
+    public static long APP_START_TIME = 0;
+
     @Override
     public void onCreate() {
         super.onCreate();
         try {
             Consts.setmApplicAtion(this);
+
+            //初始化异常监听
+            CrashHandler.getInstance().init(this);
+
             XmlPullParserFactory.newInstance().setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
             //初始化OKHTTP
             String downloadFileDir = Environment.getExternalStorageDirectory().getPath() + "/okHttp_download/";
@@ -66,10 +85,73 @@ public class EApplication extends Application {
             UMConfigure.init(this, UMConfigure.DEVICE_TYPE_PHONE, "");
             //初始化MMKV
             MMKV.initialize(this);
+
+            //初始化activity监听
+//            registerActivityLifecycleCallbacks(activityLifecycleCallbacks);
         } catch (XmlPullParserException e) {
             e.printStackTrace();
         }
 
 
     }
+
+
+    public static void killAppProcess(Context context) {
+        //注意:不能先杀掉主进程,否则逻辑代码无法继续执行,需先杀掉相关进程最后杀掉主进程
+        ActivityManager mActivityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+        List<ActivityManager.RunningAppProcessInfo> mList = mActivityManager.getRunningAppProcesses();
+        for (ActivityManager.RunningAppProcessInfo runningAppProcessInfo : mList) {
+            if (runningAppProcessInfo.pid != android.os.Process.myPid()) {
+                android.os.Process.killProcess(runningAppProcessInfo.pid);
+            }
+        }
+        android.os.Process.killProcess(android.os.Process.myPid());
+        System.exit(0);
+    }
+
+    ActivityLifecycleCallbacks activityLifecycleCallbacks = new ActivityLifecycleCallbacks() {
+        @Override
+        public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
+        }
+
+        @Override
+        public void onActivityStarted(Activity activity) {
+            if (activityAount == 0) {
+                //app回到前台
+                isForeground = true;
+//                ToastUtil.showToast("app回到前台了");
+                Logger.e("app回到前台了");
+
+                APP_START_TIME = System.currentTimeMillis();
+            }
+            activityAount++;
+        }
+
+        @Override
+        public void onActivityResumed(Activity activity) {
+        }
+
+        @Override
+        public void onActivityPaused(Activity activity) {
+        }
+
+        @Override
+        public void onActivityStopped(Activity activity) {
+            activityAount--;
+            if (activityAount == 0) {
+                isForeground = false;
+//                ToastUtil.showToast("app后台了");
+                Logger.e("app后台了");
+                killAppProcess(Consts.getmApplicAtion());
+            }
+        }
+
+        @Override
+        public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
+        }
+
+        @Override
+        public void onActivityDestroyed(Activity activity) {
+        }
+    };
 }

+ 71 - 4
app/src/main/java/com/edufound/reader/base/BaseActivity.java

@@ -1,12 +1,16 @@
 package com.edufound.reader.base;
 
 import android.app.Activity;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.os.Build;
 import android.os.Bundle;
 import android.util.DisplayMetrics;
 import android.view.WindowManager;
 
 import com.edufound.reader.annotation.BindView;
+import com.edufound.reader.receiver.HomeKeyEventReceiver;
+import com.edufound.reader.receiver.NetworkChangeReceiver;
 import com.edufound.reader.util.Consts;
 import com.edufound.reader.util.EfunboxUtil;
 import com.edufound.reader.util.LiuHaiScreenUtil;
@@ -18,20 +22,30 @@ import java.lang.reflect.Method;
 
 import androidx.appcompat.app.AppCompatActivity;
 import io.reactivex.rxjava3.annotations.Nullable;
+import io.reactivex.rxjava3.disposables.CompositeDisposable;
+import io.reactivex.rxjava3.disposables.Disposable;
 
 public abstract class BaseActivity extends AppCompatActivity {
 
+    public CompositeDisposable mCompositeDisposable;
+    //按home键的receiver
+    HomeKeyEventReceiver mHomeReceiver;
 
     @Override
     protected void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         EfunboxUtil.setCustomDensity(this, Consts.getmApplicAtion());
         setContentView(this.getLayoutId());
+        initBase();
+        bindViews(this);
+        initView();
+    }
+
+    void initBase() {
         getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
             LiuHaiScreenUtil.openFullScreenModel(this);
         }
-
         //获取录音权限
         PermissionsUtil.verifyAudioPermissions(this);
         if (Consts.getScreenSize() == null) {
@@ -42,14 +56,19 @@ public abstract class BaseActivity extends AppCompatActivity {
             int arr[] = {widthPixels, heightPixels};
             Consts.setScreenSize(arr);
         }
-
-        bindViews(this);
-        initView();
+        mCompositeDisposable = new CompositeDisposable();
+        mHomeReceiver = new HomeKeyEventReceiver();
+        registerReceiver(mHomeReceiver, new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
+        // 注册
+        NetworkChangeReceiver.registerObserver(NetStateChangeObserver);
     }
 
+
     @Override
     protected void onDestroy() {
         super.onDestroy();
+        unregisterReceiver(mHomeReceiver);
+        NetworkChangeReceiver.unRegisterReceiver(this);
     }
 
     /**
@@ -99,4 +118,52 @@ public abstract class BaseActivity extends AppCompatActivity {
             }
         }
     }
+
+
+    /**
+     * 添加订阅
+     */
+    public void addDisposable(Disposable mDisposable) {
+        if (mCompositeDisposable == null) {
+            mCompositeDisposable = new CompositeDisposable();
+        }
+        mCompositeDisposable.add(mDisposable);
+    }
+
+    /**
+     * 取消所有订阅
+     */
+    public void clearDisposable() {
+        if (mCompositeDisposable != null) {
+            mCompositeDisposable.clear();
+        }
+    }
+
+    public abstract void onDisconnect();
+
+    public abstract void onMobileConnect();
+
+    public abstract void onWifiConnect();
+
+    NetworkChangeReceiver.NetStateChangeObserver NetStateChangeObserver = new NetworkChangeReceiver.NetStateChangeObserver() {
+        @Override
+        public void onDisconnect() {
+            //断网了
+            onDisconnect();
+        }
+
+        @Override
+        public void onMobileConnect() {
+            //有网了(移动网络)
+            onMobileConnect();
+        }
+
+        @Override
+        public void onWifiConnect() {
+            //有网了(wifi)
+            onWifiConnect();
+        }
+    };
+
+
 }

+ 14 - 0
app/src/main/java/com/edufound/reader/contract/CrashDialogContract.java

@@ -0,0 +1,14 @@
+package com.edufound.reader.contract;
+
+import com.edufound.reader.base.BaseView;
+
+public interface CrashDialogContract {
+    interface Model {
+    }
+
+    interface View extends BaseView {
+    }
+
+    interface Presenter {
+    }
+}

+ 6 - 0
app/src/main/java/com/edufound/reader/model/CrashDialogModel.java

@@ -0,0 +1,6 @@
+package com.edufound.reader.model;
+
+import com.edufound.reader.contract.CrashDialogContract;
+
+public class CrashDialogModel implements CrashDialogContract.Model {
+}

+ 7 - 0
app/src/main/java/com/edufound/reader/presenter/CrashDialogPresenter.java

@@ -0,0 +1,7 @@
+package com.edufound.reader.presenter;
+
+import com.edufound.reader.base.BasePresenter;
+import com.edufound.reader.contract.CrashDialogContract;
+
+public class CrashDialogPresenter extends BasePresenter implements CrashDialogContract.Presenter {
+}

+ 17 - 2
app/src/main/java/com/edufound/reader/presenter/MainPresenter.java

@@ -5,12 +5,14 @@ import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
 import android.os.IBinder;
+import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
 
 import com.chivox.aiengine.EvalResult;
 import com.edufound.reader.R;
 import com.edufound.reader.adapter.SlideVideoAdapter;
+import com.edufound.reader.application.EApplication;
 import com.edufound.reader.base.BasePresenter;
 import com.edufound.reader.bean.SlideVideoBean;
 import com.edufound.reader.contract.MainContract;
@@ -34,7 +36,7 @@ public class MainPresenter extends BasePresenter<MainContract.View> implements M
     MainModel mModel;
     private ViewPagerLayoutManager mViewPagerLayoutManager;
     private int mCurrentPosition = -1;
-
+    RecordServices mRecordServices;
 
     /*
      * 测试数据
@@ -158,7 +160,6 @@ public class MainPresenter extends BasePresenter<MainContract.View> implements M
         }
     }
 
-    RecordServices mRecordServices;
 
     @Override
     public void bindRecordServices() {
@@ -187,6 +188,9 @@ public class MainPresenter extends BasePresenter<MainContract.View> implements M
     @Override
     public void activityDestroy() {
         mRecordServices.unbindService(recordServicesConn);
+        if (mRecordServices != null) {
+            mView.getActivity().unbindService(recordServicesConn);
+        }
     }
 
     @Override
@@ -229,4 +233,15 @@ public class MainPresenter extends BasePresenter<MainContract.View> implements M
     };
 
 
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        switch (keyCode) {
+            case KeyEvent.KEYCODE_BACK:
+            case KeyEvent.KEYCODE_ESCAPE:
+                EApplication.killAppProcess(mView.getActivity());
+                return true;
+        }
+
+        return true;
+    }
+
 }

+ 34 - 0
app/src/main/java/com/edufound/reader/receiver/HomeKeyEventReceiver.java

@@ -0,0 +1,34 @@
+package com.edufound.reader.receiver;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.text.TextUtils;
+
+import com.edufound.reader.application.EApplication;
+import com.orhanobut.logger.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.e("click home SYSTEM_HOME_KEY");
+                EApplication.killAppProcess(context);
+//                android.os.Process.killProcess(android.os.Process.myPid());
+            } else if (TextUtils.equals(reason, SYSTEM_DIALOG_REASON_RECENT_APPS)) {
+                Logger.e("click home SYSTEM_DIALOG_REASON_RECENT_APPS");
+                EApplication.killAppProcess(context);
+            }
+        }
+    }
+
+}

+ 93 - 0
app/src/main/java/com/edufound/reader/receiver/NetworkChangeReceiver.java

@@ -0,0 +1,93 @@
+package com.edufound.reader.receiver;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.ConnectivityManager;
+
+import com.edufound.reader.util.NetworkUtil;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class NetworkChangeReceiver extends BroadcastReceiver {
+
+    private List<NetStateChangeObserver> mObservers = new ArrayList<>();
+    private int mType = -1;
+    private static boolean isRegister = false;
+
+    private static class InstanceHolder {
+        private static final NetworkChangeReceiver INSTANCE = new NetworkChangeReceiver();
+    }
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
+            int connectivityStatus = NetworkUtil.getConnectivityStatus(context);
+            notifyObservers(connectivityStatus);
+        }
+
+    }
+
+    public static void registerReceiver(Context context) {
+        IntentFilter intentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
+        context.registerReceiver(InstanceHolder.INSTANCE, intentFilter);
+        isRegister = true;
+    }
+
+    public static void unRegisterReceiver(Context context) {
+        if (isRegister) {
+            context.unregisterReceiver(InstanceHolder.INSTANCE);
+        }
+    }
+
+    public static void registerObserver(NetStateChangeObserver observer) {
+        if (observer == null) {
+            return;
+        }
+        if (!InstanceHolder.INSTANCE.mObservers.contains(observer)) {
+            InstanceHolder.INSTANCE.mObservers.add(observer);
+        }
+    }
+
+    public static void unRegisterObserver(NetStateChangeObserver observer) {
+        if (observer == null) {
+            return;
+        }
+        if (InstanceHolder.INSTANCE.mObservers == null) {
+            return;
+        }
+        InstanceHolder.INSTANCE.mObservers.remove(observer);
+    }
+
+    private void notifyObservers(int networkType) {
+        if (mType == networkType) {
+            return;
+        }
+        mType = networkType;
+        if (networkType == NetworkUtil.TYPE_MOBILE) {
+            for (NetStateChangeObserver observer : mObservers) {
+                observer.onMobileConnect();
+            }
+        } else if (networkType == NetworkUtil.TYPE_WIFI) {
+            for (NetStateChangeObserver observer : mObservers) {
+                observer.onWifiConnect();
+            }
+        } else {
+            for (NetStateChangeObserver observer : mObservers) {
+                observer.onDisconnect();
+            }
+        }
+        ;
+    }
+
+    public interface NetStateChangeObserver {
+
+        void onDisconnect();
+
+        void onMobileConnect();
+
+        void onWifiConnect();
+    }
+}

+ 96 - 136
app/src/main/java/com/edufound/reader/util/CrashHandler.java

@@ -1,44 +1,45 @@
 package com.edufound.reader.util;
 
-
+import android.app.ActivityManager;
 import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.os.Environment;
 import android.os.Looper;
-import android.os.Process;
 import android.widget.Toast;
 
+import com.edufound.reader.activity.CrashDialogActivity;
 import com.orhanobut.logger.Logger;
 
-import java.lang.Thread.UncaughtExceptionHandler;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.lang.reflect.Field;
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
 
+public class CrashHandler implements Thread.UncaughtExceptionHandler {
 
-/**
- * UncaughtException处理类,当程序发生Uncaught异常的时候,有该类来接管程序,并记录发送错误报告.
- *
- * @author user
- */
-public class CrashHandler implements UncaughtExceptionHandler {
+    private String LOG_PATH = Environment.getExternalStorageDirectory().getPath() + File.separator + "efunbox_crash";
 
-    // 系统默认的UncaughtException处理类
-    private UncaughtExceptionHandler mDefaultHandler;
-    // CrashHandler实例
+    //系统默认的UncaughtException处理类
+    private Thread.UncaughtExceptionHandler mDefaultHandler;
+    //CrashHandler实例
     private static CrashHandler INSTANCE = new CrashHandler();
-    // 程序的Context对象
+    //程序的Context对象
     private Context mContext;
-    // 用来存储设备信息和异常信息
+    //用来存储设备信息和异常信息
     private Map<String, String> infos = new HashMap<String, String>();
-
-    // 用于格式化日期,作为日志文件名的一部分
-    private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
-
-    private DateFormat formatterWeb = new SimpleDateFormat("yyyyMMdd");
-
-    private DateFormat newFormatter = new SimpleDateFormat("yyyyMMdd_HHmmss");
-
+    //用于格式化日期,作为日志文件名的一部分
+    DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
 
     /**
      * 保证只有一个CrashHandler实例
@@ -60,9 +61,9 @@ public class CrashHandler implements UncaughtExceptionHandler {
      */
     public void init(Context context) {
         mContext = context;
-        // 获取系统默认的UncaughtException处理器
+        //获取系统默认的UncaughtException处理器
         mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
-        // 设置该CrashHandler为程序的默认处理器
+        //设置该CrashHandler为程序的默认处理器
         Thread.setDefaultUncaughtExceptionHandler(this);
     }
 
@@ -72,17 +73,14 @@ public class CrashHandler implements UncaughtExceptionHandler {
     @Override
     public void uncaughtException(Thread thread, Throwable ex) {
         if (!handleException(ex) && mDefaultHandler != null) {
-            // 如果用户没有处理则让系统默认的异常处理器来处
+            // 如果用户没有处理则让系统默认的异常处理器来处
             mDefaultHandler.uncaughtException(thread, ex);
         } else {
-            try {
-                Thread.sleep(4000);
-            } catch (InterruptedException e) {
-                Logger.e(e.getMessage());
-            }
-            // 退出程序
-//            android.os.Process.killProcess(android.os.Process.myPid());
-//            System.exit(1);
+            // 跳转到崩溃提示Activity
+            Intent intent = new Intent(mContext, CrashDialogActivity.class);
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            mContext.startActivity(intent);
+            System.exit(0);// 关闭已奔溃的app进程
         }
     }
 
@@ -96,46 +94,18 @@ public class CrashHandler implements UncaughtExceptionHandler {
         if (ex == null) {
             return false;
         }
-        // 收集设备参数信息
-        collectDeviceInfo(mContext);
-        // 保存日志文件
-        final String fileName = saveCrashInfo2File(ex);
-        String date = formatterWeb.format(new Date());
-//        //上传到服务器
-//        final String url = "/logs/android/";
-//        String stu = "";
-//        Logger.e("url:" + url);
-//        if (!EduFoundUtil.isEmpty(Consts.mUserData.userInfo.getStu_no())) {
-//            stu = Consts.mUserData.userInfo.getStu_no();
-//        } else {
-//            stu = newFormatter.format(new Date());
-//        }
-//        final String finalStu = date + "_" + Consts.APP_CODE + "_" + stu + ".log";
-//        new Thread() {
-//            @Override
-//            public void run() {
-//                FtpUtil.ftpUpload(url, finalStu, Consts.LOG_URL + fileName, new FtpUtil.upLoadListrner() {
-//                    @Override
-//                    public void onLoadOver() {
-//                        android.os.Process.killProcess(android.os.Process.myPid());
-//                        System.exit(1);
-//                    }
-//                });
-//            }
-//        }.start();
-//
-//        // 使用Toast来显示异常信息
         new Thread() {
             @Override
             public void run() {
                 Looper.prepare();
-                Toast.makeText(mContext, "很抱歉,程序出现异常.", Toast.LENGTH_SHORT).show();
+//                Toast.makeText(mContext, "很抱歉,出现异常.", Toast.LENGTH_LONG).show();
                 Looper.loop();
-                Process.killProcess(Process.myPid());
-                System.exit(1);
             }
         }.start();
-
+        //收集设备参数信息
+//        collectDeviceInfo(mContext);
+        //保存日志文件
+//        saveCrashInfo2File(ex);
         return true;
     }
 
@@ -145,32 +115,27 @@ public class CrashHandler implements UncaughtExceptionHandler {
      * @param ctx
      */
     public void collectDeviceInfo(Context ctx) {
-//        try {
-//            PackageManager pm = ctx.getPackageManager();
-//            PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(), PackageManager.GET_ACTIVITIES);
-//            if (pi != null) {
-//                String versionName = pi.versionName == null ? "null" : pi.versionName;
-//                String versionCode = pi.versionCode + "";
-//                infos.put("versionName", versionName);
-//                infos.put("versionCode", versionCode);
-////                infos.put("APP_ID", Consts.APP_CODE);
-////                infos.put("STU_ID", Consts.mUserData.userInfo.getStu_no());
-////                infos.put("UUID", Consts.mUserData.userInfo.getUid());
-//
-//            }
-//        } catch (NameNotFoundException e) {
-//            Logger.e("an error occured when collect package info" + e);
-//        }
-//        Field[] fields = Build.class.getDeclaredFields();
-//        for (Field field : fields) {
-//            try {
-//                field.setAccessible(true);
-//                infos.put(field.getName(), field.get(null).toString());
-//                Logger.e(field.getName() + " : " + field.get(null));
-//            } catch (Exception e) {
-//                Logger.e("an error occured when collect crash info", e);
-//            }
-//        }
+        try {
+            PackageManager pm = ctx.getPackageManager();
+            PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(), PackageManager.GET_ACTIVITIES);
+            if (pi != null) {
+                String versionName = pi.versionName == null ? "null" : pi.versionName;
+                String versionCode = pi.versionCode + "";
+                infos.put("versionName", versionName);
+                infos.put("versionCode", versionCode);
+            }
+        } catch (PackageManager.NameNotFoundException e) {
+            Logger.e(e.getMessage());
+        }
+        Field[] fields = Build.class.getDeclaredFields();
+        for (Field field : fields) {
+            try {
+                field.setAccessible(true);
+                infos.put(field.getName(), field.get(null).toString());
+            } catch (Exception e) {
+                Logger.e(e.getMessage());
+            }
+        }
     }
 
     /**
@@ -180,49 +145,44 @@ public class CrashHandler implements UncaughtExceptionHandler {
      * @return 返回文件名称, 便于将文件传送到服务器
      */
     private String saveCrashInfo2File(Throwable ex) {
-//        File file = new File(Consts.LOG_URL);
-//        if (!file.exists()) {
-//            file.mkdirs();
-//        }
-//        StringBuffer sb = new StringBuffer();
-//        for (Map.Entry<String, String> entry : infos.entrySet()) {
-//            String key = entry.getKey();
-//            String value = entry.getValue();
-//            sb.append(key + "=" + value + "\n");
-//            sb.append("----------------------------------------" + "\n");
-//        }
-//
-//
-//        Writer writer = new StringWriter();
-//        PrintWriter printWriter = new PrintWriter(writer);
-//        ex.printStackTrace(printWriter);
-//        Throwable cause = ex.getCause();
-//        while (cause != null) {
-//            cause.printStackTrace(printWriter);
-//            cause = cause.getCause();
-//        }
-//        printWriter.close();
-//        String result = writer.toString();
-//        sb.append(result);
-//        try {
-//            long timestamp = System.currentTimeMillis();
-//            String mSaveDate = formatter.format(new Date());
-//            String stu = "";
-//            if (!EduFoundUtil.isEmpty(Consts.mUserData.userInfo.getStu_no())) {
-//                stu = Consts.mUserData.userInfo.getStu_no();
-//            }
-//            String fileName = stu + "" + mSaveDate + "--" + timestamp + ".log";
-//            if (Environment.getExternalStorageState().equals(
-//                    Environment.MEDIA_MOUNTED)) {
-//                FileOutputStream fos = new FileOutputStream(
-//                        Consts.LOG_URL + fileName);
-//                fos.write(sb.toString().getBytes());
-//                fos.close();
-//            }
-//            return fileName;
-//        } catch (Exception e) {
-//            Logger.e("an error occured while writing file...", e);
-//        }
+
+        StringBuffer sb = new StringBuffer();
+        for (Map.Entry<String, String> entry : infos.entrySet()) {
+            String key = entry.getKey();
+            String value = entry.getValue();
+            sb.append(key + "=" + value + "\n");
+        }
+
+        Writer writer = new StringWriter();
+        PrintWriter printWriter = new PrintWriter(writer);
+        ex.printStackTrace(printWriter);
+        Throwable cause = ex.getCause();
+        while (cause != null) {
+            cause.printStackTrace(printWriter);
+            cause = cause.getCause();
+        }
+        printWriter.close();
+        String result = writer.toString();
+        sb.append(result);
+        try {
+            long timestamp = System.currentTimeMillis();
+            String time = formatter.format(new Date());
+            String fileName = "log-" + time + "-" + timestamp + ".txt";
+            if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+                //日志存放路径
+                String path = LOG_PATH;
+                File dir = new File(path);
+                dir.mkdirs();
+                FileOutputStream fos = new FileOutputStream(path + "/" + fileName);
+                fos.write(sb.toString().getBytes());
+                fos.close();
+            }
+            return fileName;
+        } catch (Exception e) {
+            Logger.e(e.getMessage());
+        } finally {
+            System.exit(0);
+        }
         return null;
     }
-}
+}

+ 27 - 0
app/src/main/java/com/edufound/reader/util/NetworkUtil.java

@@ -0,0 +1,27 @@
+package com.edufound.reader.util;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+
+public class NetworkUtil {
+    public static final int TYPE_WIFI = 1;
+    public static final int TYPE_MOBILE = 2;
+    public static final int TYPE_NOT_CONNECTED = 0;
+
+
+    public static int getConnectivityStatus(Context context) {
+        ConnectivityManager cm = (ConnectivityManager) context
+                .getSystemService(Context.CONNECTIVITY_SERVICE);
+
+        NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
+        if (null != activeNetwork) {
+            if (activeNetwork.getType() == ConnectivityManager.TYPE_WIFI)
+                return TYPE_WIFI;
+
+            if (activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE)
+                return TYPE_MOBILE;
+        }
+        return TYPE_NOT_CONNECTED;
+    }
+}

+ 1 - 1
app/src/main/res/drawable/cusjzplayer_controller_seekbar.xml

@@ -11,7 +11,7 @@
         <clip>
             <shape>
                 <solid android:color="#a5ffffff" />
-                <size android:height="3dp" />
+                <size android:height="10dp" />
                 <corners android:radius="0dp" />
             </shape>
         </clip>

+ 6 - 0
app/src/main/res/layout/activity_crash_dialog.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+</FrameLayout>

+ 1 - 0
build.gradle

@@ -18,6 +18,7 @@ allprojects {
         google()
         jcenter()
         mavenCentral()
+        maven { url "https://oss.jfrog.org/libs-snapshot" }
     }
 }