栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Android 杀掉App所有相关的进程,并退出应用程序(彻底杀死App)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Android 杀掉App所有相关的进程,并退出应用程序(彻底杀死App)

        我们先介绍一下Android 对进程和内存的管理

        如果内存足够,Android不会杀掉任何进程,如果内存不足就是进程随时可能会被杀掉。

        而Android会在内存充足的时候,重启被杀掉的进程。

        也就是说静态变量的值,如果不做处理,是不可靠的,可以说内存中的一切都不可靠。

        如果要可靠,还是得保存到文件中去,在重启的时候恢复回来。

        Android Application其实是一个单例对象,也是放在内存中的,当进程被杀掉,缓存数据就全清空了,只不过Android系统会帮重建Application,而我们存放在Application的缓存数据自然就没有了,还是得自己处理。

        不过我们可以在Application被销毁时直接退出程序,其实Application都被销毁了,程序就应该退出的。

        看完之后是不是感觉都要晕了,Android 你杀死进程就杀死嘛,干嘛又要重启。。。重启之后,再用一些缓存数据(Application里的数据,静态变量数据等等),就容易造成一些问题(比如:NullPointerException),为了避免这些问题,我们要在内存不足的时候彻底杀死App。

1.写一个Activity的管理类。

package com.phone.common_library.manager;

import android.app.Activity;
import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
import android.text.TextUtils;

import java.util.List;
import java.util.Stack;
import java.util.concurrent.atomic.AtomicBoolean;



public class ActivityPageManager {

    private static final String TAG = "ActivityPageManager";
    
    private static ActivityPageManager mActivityPageManager;
    
    private Stack mActivityStack = new Stack<>();

    
    private Stack mActivityAliveStack = new Stack<>();

    
    private AtomicBoolean isLastAliveActivity = new AtomicBoolean(false);

    
    private ActivityPageManager() {
    }

    
    public static ActivityPageManager getInstance() {
        if (mActivityPageManager == null) {
            synchronized (ActivityPageManager.class) {
                if (mActivityPageManager == null) {
                    mActivityPageManager = new ActivityPageManager();
                }
            }
        }
        return mActivityPageManager;
    }

    
    public void addActivity(Activity activity) {
        mActivityStack.add(activity);
    }

    
    public void removeActivity(Activity activity) {
        if (activity != null && mActivityStack.contains(activity)) {
            mActivityStack.remove(activity);
        }
    }

    
    public Activity getCurrentActivity() {
        return mActivityStack.lastElement();
    }

    
    public Activity getActivity(Class cls) {
        if (mActivityStack != null)
            for (Activity activity : mActivityStack) {
                if (activity.getClass().equals(cls)) {
                    return activity;
                }
            }
        return null;
    }

    
    public void finishCurrentActivity() {
        Activity activity = mActivityStack.lastElement();
        finishActivity(activity);
    }

    
    public void finishActivity(Activity activity) {
        if (activity != null && mActivityStack.contains(activity)) {
            mActivityStack.remove(activity);
            LogManager.i(TAG, "finishActivity");
            activity.finish();
        }
    }

    
    public void finishAliveActivity(Activity activity) {
        if (activity != null && mActivityAliveStack.contains(activity)) {
            mActivityAliveStack.remove(activity);
            LogManager.i(TAG, "finishActivity");
            activity.finish();
        }
    }

    
    public void finishActivity(Class clazz) {
        for (Activity activity : mActivityStack) {
            if (activity.getClass().equals(clazz)) {
                finishActivity(activity);
                break;
            }
        }
    }

    
    public void finishAllActivity() {
        mActivityAliveStack.clear();
        for (int i = mActivityStack.size() - 1; i >= 0; i--) {
            if (mActivityStack.get(i) != null) {
                mActivityAliveStack.add(mActivityStack.get(i));
            }
        }
        for (int i = mActivityAliveStack.size() - 1; i >= 0; i--) {
            if (i == 0) {
                isLastAliveActivity.set(true);
                LogManager.i(TAG, "isLastAliveActivity.set(true)");
            }
            finishAliveActivity(mActivityAliveStack.get(i));
        }
        mActivityAliveStack.clear();
        mActivityStack.clear();
    }

    public AtomicBoolean isLastAliveActivity() {
        return isLastAliveActivity;
    }

    
    public void finishAllActivityExcept(Class clazz) {
        for (int i = mActivityStack.size() - 1; i >= 0; i--) {

            if (mActivityStack.get(i) != null && !mActivityStack.get(i).getClass().equals(clazz)) {
                finishActivity(mActivityStack.get(i));
            }
        }
    }

    
    public void exitApp() {
        try {
            finishAllActivity();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            System.exit(0);
        }
    }

    
    public void exitApp2() {
        try {
            LogManager.i(TAG, "exitApp2");
            finishAllActivity();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    
    public static boolean isForeground(Context context, String className) {
        if (context == null || TextUtils.isEmpty(className)) {
            return false;
        }

        ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        List list = am.getRunningTasks(1);
        if (list != null && list.size() > 0) {
            ComponentName cpn = list.get(0).topActivity;
            if (className.equals(cpn.getClassName())) {
                return true;
            }
        }
        return false;
    }

}

2.写一个基础Activity(只要在自己的Activity加上和ActivityPageManager关联的方法,还有killAppProcess方法就行了)。

package com.phone.common_library.base;

import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
import android.os.Looper;
import android.view.Gravity;
import android.widget.FrameLayout;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.Nullable;

import com.gyf.immersionbar.ImmersionBar;
import com.phone.common_library.BaseApplication;
import com.phone.common_library.R;
import com.phone.common_library.manager.ActivityPageManager;
import com.phone.common_library.manager.CrashHandlerManager;
import com.phone.common_library.manager.LogManager;
import com.phone.common_library.manager.ToolbarManager;
import com.trello.rxlifecycle3.components.support.RxAppCompatActivity;

import java.util.List;
import java.util.Map;

public abstract class BaseRxAppActivity extends RxAppCompatActivity {

    private static final String TAG = "BaseRxAppActivity";
    //	protected QMUILoadingView          loadView;
//	protected FrameLayout.LayoutParams layoutParams;
    protected Intent intent;
    protected Bundle bundle;
    protected RxAppCompatActivity rxAppCompatActivity;
    protected BaseApplication baseApplication;
    private ActivityPageManager activityPageManager;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        rxAppCompatActivity = this;
        baseApplication = (BaseApplication) getApplication();
        activityPageManager = ActivityPageManager.getInstance();
        activityPageManager.addActivity(rxAppCompatActivity);

        setContentView(initLayoutId());

//		loadView = new QMUILoadingView(rxAppCompatActivity);
//		loadView.setVisibility(View.GONE);
//		loadView.setSize(100);
//		loadView.setColor(getResources().getColor(R.color.color_80000000));
//		layoutParams = new FrameLayout.LayoutParams(
//			FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);
//		layoutParams.gravity = Gravity.CENTER;

        //        setToolbar();
        initData();
        initViews();
        initLoadData();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        //非默认值
        if (newConfig.fontScale != 1) {
            getResources();
        }
        super.onConfigurationChanged(newConfig);
    }

    @Override
    public Resources getResources() {//还原字体大小
        Resources res = super.getResources();
        //非默认值
        if (res.getConfiguration().fontScale != 1) {
            Configuration newConfig = new Configuration();
            newConfig.setToDefaults();//设置默认
            res.updateConfiguration(newConfig, res.getDisplayMetrics());
        }
        return res;
    }

    protected abstract int initLayoutId();

    protected void setToolbar(boolean isDarkFont) {
        if (isDarkFont) {
            ImmersionBar.with(rxAppCompatActivity) //原理:如果当前设备支持状态栏字体变色,会设置状态栏字体为黑色,如果当前设备不支持状态栏字体变色,会使当前状态栏加上透明度,否则不执行透明度
                    .statusBarDarkFont(isDarkFont)
                    .statusBarColor(R.color.color_FFFFFFFF)     //状态栏颜色,不写默认透明色
                    //                    .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
                    .keyboardEnable(true)
                    .init();
        } else {
            ImmersionBar.with(rxAppCompatActivity)
                    .statusBarDarkFont(isDarkFont)
                    .statusBarColor(R.color.color_FF198CFF)     //状态栏颜色,不写默认透明色
                    //                    .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
                    .keyboardEnable(true)
                    .init();
        }

        ToolbarManager.assistActivity(findViewById(android.R.id.content));
    }

    protected void setToolbar(boolean isDarkFont, boolean isResizeChildOfContent) {
        if (isDarkFont) {
            ImmersionBar.with(rxAppCompatActivity) //原理:如果当前设备支持状态栏字体变色,会设置状态栏字体为黑色,如果当前设备不支持状态栏字体变色,会使当前状态栏加上透明度,否则不执行透明度
                    .statusBarDarkFont(isDarkFont)
                    .statusBarColor(R.color.color_FFFFFFFF)     //状态栏颜色,不写默认透明色
                    //                    .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
                    .keyboardEnable(true)
                    .init();
        } else {
            ImmersionBar.with(rxAppCompatActivity)
                    .statusBarDarkFont(isDarkFont)
                    .statusBarColor(R.color.color_FF198CFF)     //状态栏颜色,不写默认透明色
                    //                    .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
                    .keyboardEnable(true)
                    .init();
        }

        if (isResizeChildOfContent) {
            ToolbarManager.assistActivity(findViewById(android.R.id.content));
        }
    }

    protected void setToolbar(boolean isDarkFont, int color) {
        if (isDarkFont) {
            ImmersionBar.with(rxAppCompatActivity) //原理:如果当前设备支持状态栏字体变色,会设置状态栏字体为黑色,如果当前设备不支持状态栏字体变色,会使当前状态栏加上透明度,否则不执行透明度
                    .statusBarDarkFont(isDarkFont)
                    .statusBarColor(color)     //状态栏颜色,不写默认透明色
                    //                    .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
                    .init();
        } else {
            ImmersionBar.with(rxAppCompatActivity)
                    .statusBarDarkFont(isDarkFont)
                    .statusBarColor(color)     //状态栏颜色,不写默认透明色
                    //                    .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
                    .init();
        }

        ToolbarManager.assistActivity(findViewById(android.R.id.content));
    }

    protected void setToolbar(boolean isDarkFont, int color, boolean isResizeChildOfContent) {
        if (isDarkFont) {
            ImmersionBar.with(rxAppCompatActivity) //原理:如果当前设备支持状态栏字体变色,会设置状态栏字体为黑色,如果当前设备不支持状态栏字体变色,会使当前状态栏加上透明度,否则不执行透明度
                    .statusBarDarkFont(isDarkFont)
                    .statusBarColor(color)     //状态栏颜色,不写默认透明色
                    //                    .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
                    .init();
        } else {
            ImmersionBar.with(rxAppCompatActivity)
                    .statusBarDarkFont(isDarkFont)
                    .statusBarColor(color)     //状态栏颜色,不写默认透明色
                    //                    .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
                    .init();
        }

        if (isResizeChildOfContent) {
            ToolbarManager.assistActivity(findViewById(android.R.id.content));
        }
    }

    
    protected void initImmersionBar() {
        //设置共同沉浸式样式
        ImmersionBar.with(rxAppCompatActivity).navigationBarColor(R.color.color_FFE066FF).init();
    }

    protected abstract void initData();

    protected abstract void initViews();

    protected abstract void initLoadData();

    protected void showToast(String message, boolean isLongToast) {
        //        Toast.makeText(rxAppCompatActivity, message, Toast.LENGTH_LONG).show();
        if (!rxAppCompatActivity.isFinishing()) {
            Toast toast;
            int duration;
            if (isLongToast) {
                duration = Toast.LENGTH_LONG;
            } else {
                duration = Toast.LENGTH_SHORT;
            }
            toast = Toast.makeText(rxAppCompatActivity, message, duration);
            toast.setGravity(Gravity.CENTER, 0, 0);
            toast.show();
        }
    }

    protected void showCustomToast(int left, int right,
                                   int textSize, int textColor,
                                   int bgColor, int height,
                                   int roundRadius, String message) {
        FrameLayout frameLayout = new FrameLayout(rxAppCompatActivity);
        FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
        frameLayout.setLayoutParams(layoutParams);
        TextView textView = new TextView(rxAppCompatActivity);
        FrameLayout.LayoutParams layoutParams1 = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, height);
        textView.setLayoutParams(layoutParams1);
        textView.setPadding(left, 0, right, 0);
        textView.setTextSize(textSize);
        textView.setTextColor(textColor);
        textView.setGravity(Gravity.CENTER);
        textView.setIncludeFontPadding(false);
        GradientDrawable gradientDrawable = new GradientDrawable();//创建drawable
        gradientDrawable.setColor(bgColor);
        gradientDrawable.setCornerRadius(roundRadius);
        textView.setBackground(gradientDrawable);
        textView.setText(message);
        frameLayout.addView(textView);

        Toast toast = new Toast(rxAppCompatActivity);
        toast.setView(frameLayout);
        toast.setDuration(Toast.LENGTH_LONG);
        toast.show();
    }

    public boolean isOnMainThread() {
        return Looper.getMainLooper().getThread().getId() == Thread.currentThread().getId();
    }

    protected void startActivity(Class cls) {
        intent = new Intent(rxAppCompatActivity, cls);
        startActivity(intent);
    }

    protected void startActivityCarryParams(Class cls, Map params) {
        intent = new Intent(rxAppCompatActivity, cls);
        bundle = new Bundle();

        if (params != null && params.size() > 0) {
            for (String key : params.keySet()) {
                if (params.get(key) != null) {//如果参数不是null,才把参数传给后台
                    bundle.putString(key, params.get(key));
                }
            }
            intent.putExtras(bundle);
        }
        startActivity(intent);
    }

    protected void startActivityForResult(Class cls, int requestCode) {
        intent = new Intent(rxAppCompatActivity, cls);
        startActivityForResult(intent, requestCode);
    }

    protected void startActivityForResultCarryParams(Class cls, Map params, int requestCode) {
        intent = new Intent(rxAppCompatActivity, cls);
        bundle = new Bundle();

        if (params != null && params.size() > 0) {
            for (String key : params.keySet()) {
                if (params.get(key) != null) {//如果参数不是null,才把参数传给后台
                    bundle.putString(key, params.get(key));
                }
            }
            intent.putExtras(bundle);
        }
        startActivityForResult(intent, requestCode);
    }

    protected boolean isEmpty(String dataStr) {
        if (dataStr != null && !"".equals(dataStr)) {
            return false;
        } else {
            return true;
        }
    }

    private void killAppProcess(Context context) {
        LogManager.i(TAG, "killAppProcess");
        ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        List processInfos = manager.getRunningAppProcesses();
        // 先杀掉相关进程,最后再杀掉主进程
        for (ActivityManager.RunningAppProcessInfo runningAppProcessInfo : processInfos) {
            if (runningAppProcessInfo.pid != android.os.Process.myPid()) {
                android.os.Process.killProcess(runningAppProcessInfo.pid);
            }
        }

        LogManager.i(TAG, "执行killAppProcess,應用開始自殺");
        CrashHandlerManager crashHandlerManager = CrashHandlerManager.getInstance(context);
        crashHandlerManager.saveTrimMemoryInfoToFile("执行killAppProcess,應用開始自殺");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            LogManager.i(TAG, "error");
        }

        android.os.Process.killProcess(android.os.Process.myPid());
        // 正常退出程序,也就是结束当前正在运行的 java 虚拟机
        System.exit(0);
    }

    @Override
    protected void onDestroy() {
        if (activityPageManager != null) {
            if (activityPageManager.isLastAliveActivity().get()) {
                killAppProcess(baseApplication);
            }
            activityPageManager.removeActivity(rxAppCompatActivity);
        }
        super.onDestroy();
    }
}

3.写一个基础Application(只要在自己的Application加上和ActivityPageManager关联的方法,还有onTrimMemory方法就行了)。

package com.phone.common_library;

import android.content.Context;
import android.content.SharedPreferences;

import androidx.multidex.MultiDex;
import androidx.multidex.MultiDexApplication;

import com.alibaba.android.arouter.launcher.ARouter;
import com.phone.common_library.manager.ActivityPageManager;
import com.phone.common_library.manager.CrashHandlerManager;
import com.phone.common_library.manager.LogManager;
import com.phone.common_library.manager.RetrofitManager;

public class BaseApplication extends MultiDexApplication {

    private static final String TAG = "BaseApplication";
    //声明 初始化
    protected SharedPreferences sp;
    protected SharedPreferences.Editor editor;
    protected static final int MODE = Context.MODE_PRIVATE;
    private boolean isLogin;
    private String accessToken;
    private String systemId;

    protected static BaseApplication baseApplication;
    private ActivityPageManager activityPageManager;

    @Override
    public void onCreate() {
        super.onCreate();
        baseApplication = this;

        //文件为mySp  存放在/data/data//shared_prefs/目录下的
        sp = getSharedPreferences("app", MODE);
        editor = sp.edit();

        //初始化retrofit
        RetrofitManager.getInstance();
        activityPageManager = ActivityPageManager.getInstance();

        CrashHandlerManager crashHandlerManager = CrashHandlerManager.getInstance(this);
        crashHandlerManager.sendPreviousReportsToServer();
        crashHandlerManager.init();

        if (true) {
            ARouter.openLog();
            ARouter.openDebug();
        }
        ARouter.init(this);

        //		RxJavaPlugins.setErrorHandler(new Consumer() {
        //			@Override
        //			public void accept(Throwable throwable) {
        //				//异常处理
        //				LogManager.i(TAG, "throwable*****" + throwable.toString());
        //				LogManager.i(TAG, "throwable message*****" + throwable.getMessage());
        //			}
        //		});
    }

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        MultiDex.install(this);
    }

    public static BaseApplication getInstance() {
        return baseApplication;
    }

    public boolean isLogin() {
        isLogin = sp.getBoolean("isLogin", false);
        LogManager.i(TAG, "isLogin***" + isLogin);
        return isLogin;
    }

    public void setLogin(boolean isLogin) {
        LogManager.i(TAG, "setLogin***" + isLogin);
        editor.putBoolean("isLogin", isLogin);
        editor.commit();
        if (!isLogin) {
            setLogout();
        }
    }

    public String getAccessToken() {
        accessToken = sp.getString("accessToken", "");
        return accessToken;
    }

    public void setAccessToken(String accessToken) {
        LogManager.i(TAG, "setAccessToken***" + accessToken);
        editor.putString("accessToken", accessToken);
        editor.commit();
    }

    public String getSystemId() {
        systemId = sp.getString("systemId", "");
        return systemId;
    }

    public void setSystemId(String systemId) {
        LogManager.i(TAG, "setSystemId***" + systemId);
        editor.putString("systemId", systemId);
        editor.commit();
    }

    public void setLogout() {
        LogManager.i(TAG, "setLogout***");
        //        editor.clear();
        editor.remove("accessToken");
        editor.remove("isLogin");
        editor.commit();
    }

    @Override
    public void onTrimMemory(int level) {
        super.onTrimMemory(level);
        if (level == TRIM_MEMORY_MODERATE) {
            //App开始自杀,清理掉所有的activity(最後一個存活的Activity退出的时候(onDestroy)做了退出應用程序處理)
            activityPageManager.exitApp2();
        }
    }
}

        因内存不足进程被杀掉,而Android会在内存充足的时候,重启被杀掉的进程,然后再用一些缓存数据(Application里的数据,静态变量数据等等),就容易造成一些问题(比如:NullPointerException)。

这样就可以在内存不足的时候彻底杀死App,这样就会避免因以上原因造成的问题了。

如对此有疑问,请联系qq1164688204。

推荐Android开源项目

项目功能介绍:RxJava2和Retrofit2项目,添加自动管理token功能,添加RxJava2生命周期管理,使用App架构设计是MVP模式和MVVM模式,同时使用组件化,部分代码使用Kotlin,此项目持续维护中。

项目地址:https://gitee.com/urasaki/RxJava2AndRetrofit2

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/936525.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号