package me.wcy.music.application; import android.app.Activity; import android.app.Application; import android.content.Context; import android.os.Bundle; import android.support.v4.util.LongSparseArray; import android.util.Log; import com.amap.api.location.AMapLocalWeatherLive; import java.util.ArrayList; import java.util.List; import me.wcy.music.executor.DownloadMusicInfo; import me.wcy.music.model.Music; import me.wcy.music.model.SheetInfo; import me.wcy.music.utils.CoverLoader; import me.wcy.music.storage.preference.Preferences; import me.wcy.music.utils.ScreenUtils; import me.wcy.music.utils.ToastUtils; public class AppCache { private Context mContext; private final List<Music> mLocalMusicList = new ArrayList<>(); private final List<SheetInfo> mSheetList = new ArrayList<>(); private final List<Activity> mActivityStack = new ArrayList<>(); private final LongSparseArray<DownloadMusicInfo> mDownloadList = new LongSparseArray<>(); private AMapLocalWeatherLive mAMapLocalWeatherLive; private AppCache() { } private static class SingletonHolder { private static AppCache instance = new AppCache(); } public static AppCache get() { return SingletonHolder.instance; } public void init(Application application) { mContext = application.getApplicationContext(); ToastUtils.init(mContext); Preferences.init(mContext); ScreenUtils.init(mContext); CrashHandler.getInstance().init(); CoverLoader.get().init(mContext); application.registerActivityLifecycleCallbacks(new ActivityLifecycle()); } public Context getContext() { return mContext; } public List<Music> getLocalMusicList() { return mLocalMusicList; } public List<SheetInfo> getSheetList() { return mSheetList; } public void clearStack() { List<Activity> activityStack = mActivityStack; for (int i = activityStack.size() - 1; i >= 0; i--) { Activity activity = activityStack.get(i); if (!activity.isFinishing()) { activity.finish(); } } activityStack.clear(); } public LongSparseArray<DownloadMusicInfo> getDownloadList() { return mDownloadList; } public AMapLocalWeatherLive getAMapLocalWeatherLive() { return mAMapLocalWeatherLive; } public void setAMapLocalWeatherLive(AMapLocalWeatherLive aMapLocalWeatherLive) { mAMapLocalWeatherLive = aMapLocalWeatherLive; } private class ActivityLifecycle implements Application.ActivityLifecycleCallbacks { private static final String TAG = "Activity"; @Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) { Log.i(TAG, "onCreate: " + activity.getClass().getSimpleName()); mActivityStack.add(activity); } @Override public void onActivityStarted(Activity activity) { } @Override public void onActivityResumed(Activity activity) { } @Override public void onActivityPaused(Activity activity) { } @Override public void onActivityStopped(Activity activity) { } @Override public void onActivitySaveInstanceState(Activity activity, Bundle outState) { } @Override public void onActivityDestroyed(Activity activity) { Log.i(TAG, "onDestroy: " + activity.getClass().getSimpleName()); mActivityStack.remove(activity); } } }
package me.wcy.music.application; import android.os.Build; import android.util.Log; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; import me.wcy.music.BuildConfig; import me.wcy.music.utils.FileUtils; /** * 异常捕获 * Created by hzwangchenyan on 2016/1/25. */ public class CrashHandler implements Thread.UncaughtExceptionHandler { private static SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("MM-dd HH:mm:ss.SSS", Locale.getDefault()); private Thread.UncaughtExceptionHandler mDefaultHandler; public static CrashHandler getInstance() { return SingletonHolder.instance; } private static class SingletonHolder { private static CrashHandler instance = new CrashHandler(); } public void init() { mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler(); Thread.setDefaultUncaughtExceptionHandler(this); } @Override public void uncaughtException(Thread thread, Throwable ex) { saveCrashInfo(ex); mDefaultHandler.uncaughtException(thread, ex); } private void saveCrashInfo(Throwable ex) { String stackTrace = Log.getStackTraceString(ex); String filePath = FileUtils.getLogDir() + "crash.log"; try { BufferedWriter bw = new BufferedWriter(new FileWriter(filePath, true)); bw.write("*** crash *** "); bw.write(getInfo()); bw.write(stackTrace); bw.newLine(); bw.newLine(); bw.flush(); bw.close(); } catch (IOException e) { e.printStackTrace(); } } private String getInfo() { String time = TIME_FORMAT.format(new Date()); String version = BuildConfig.VERSION_NAME + "/" + BuildConfig.VERSION_CODE; String device = Build.MANUFACTURER + "/" + Build.MODEL + "/" + Build.VERSION.RELEASE; StringBuilder sb = new StringBuilder(); sb.append("*** time: ").append(time).append(" ***").append(" "); sb.append("*** version: ").append(version).append(" ***").append(" "); sb.append("*** device: ").append(device).append(" ***").append(" "); return sb.toString(); } }
package me.wcy.music.application; import android.app.Activity; import android.app.Application; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.util.Log; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * Created by hzwangchenyan on 2017/9/20. */ public class ForegroundObserver implements Application.ActivityLifecycleCallbacks { private static final String TAG = "ForegroundObserver"; private static final long CHECK_TASK_DELAY = 500; private List<Observer> observerList; private Handler handler; private boolean isForeground; private int resumeActivityCount; public interface Observer { /** * 进入前台 * * @param activity 当前处于栈顶的Activity */ void onForeground(Activity activity); /** * 进入后台 * * @param activity 当前处于栈顶的Activity */ void onBackground(Activity activity); } public static void init(Application application) { application.registerActivityLifecycleCallbacks(getInstance()); } private static ForegroundObserver getInstance() { return SingletonHolder.sInstance; } private static class SingletonHolder { private static ForegroundObserver sInstance = new ForegroundObserver(); } private ForegroundObserver() { observerList = Collections.synchronizedList(new ArrayList<Observer>()); handler = new Handler(Looper.getMainLooper()); } public static void addObserver(Observer observer) { if (observer == null) { return; } if (getInstance().observerList.contains(observer)) { return; } getInstance().observerList.add(observer); } public static void removeObserver(Observer observer) { if (observer == null) { return; } getInstance().observerList.remove(observer); } @Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) { } @Override public void onActivityStarted(Activity activity) { } @Override public void onActivityResumed(Activity activity) { resumeActivityCount++; if (!isForeground && resumeActivityCount > 0) { isForeground = true; // 从后台进入前台 Log.i(TAG, "app in foreground"); notify(activity, true); } } @Override public void onActivityPaused(final Activity activity) { resumeActivityCount--; handler.postDelayed(new Runnable() { @Override public void run() { if (isForeground && resumeActivityCount == 0) { isForeground = false; // 从前台进入后台 Log.i(TAG, "app in background"); ForegroundObserver.this.notify(activity, false); } } }, CHECK_TASK_DELAY); } private void notify(Activity activity, boolean foreground) { for (Observer observer : observerList) { if (foreground) { observer.onForeground(activity); } else { observer.onBackground(activity); } } } @Override public void onActivityStopped(Activity activity) { } @Override public void onActivitySaveInstanceState(Activity activity, Bundle outState) { } @Override public void onActivityDestroyed(Activity activity) { } }