admin 管理员组

文章数量: 887021

360悬浮加速小火箭,内存清理,加速缓存

关于我

最近时间都比较的紧,处理不同项目的BUG,今天偷得半日闲,把剩下项目的一部分扔给了组长。有个问题没解决,做了两天也没完成,实在是没有办法了。也很感谢,旅行途中遇到很多有趣的人,希望他们越来越顺利。

废话少说,接入今天的主题。

需求文档

1、在主界面 显示 一个悬浮图标或者入口,点击后展示如下界面,直接开始清理,清理完成后,弹个toast提示(已清理多少空间),就退出界面了

2、【手机加速】一键加速,让你的手机顷刻间享受飞一般的速度
杀进程,杀掉除了我们自己应用必备的其他进程
3、【缓存清理】清除无用的垃圾,释放手机内存

任务分析

简单描述就是:点击桌面的小火箭(悬浮按钮)进入上面的清理界面,然后自动扫瞄文件,以及正在运行进程。扫瞄完成之后自动清理缓存,清理进程。清理完成之后,返回清理Toast,点击清理界面,自动消失,小火箭又重新出现。

开始执行代码

1、悬浮小火箭
我在项目中开启一个Service,用于时刻吸附屏幕两边、以及拖拉效果、时刻悬浮在其他应用之上。

MainActivity
我在入口里直接开始一个Service,用于管理悬浮小火箭,和悬浮窗口(就是清理界面)

public void startService(View view){
        Intent intent=new Intent(this, MyFloatService.class);
        startService(intent);
        finish();
    }
}

MyFloatService

/**
 * @description 创建 service 方便管理悬浮小火箭 、悬浮窗口
 * @date: 2020/4/14
 * @author: a */
public class MyFloatService extends Service {
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        //用来开启FloatViewManager
        FloatViewManager manager= FloatViewManager.getInstance(this);
        manager.showFloatCircleView();
        super.onCreate();
    }

}

此处开启一个浮窗管理类FloatViewManager ,获取实例之后,直接显示桌面小火箭manager.showFloatCircleView()。

FloatViewManager

/**
 * @description 悬浮管理类
 * @date: 2020/4/14
 * @author: a */
public class FloatViewManager {
    //浮窗管理类用来管理悬浮窗的显示和隐藏。
    private Context context;
    private static FloatViewManager inStance;
    private  WindowManager wm;//通過WindowManager 來操控浮窗的顯示和隱藏。
    private FloatCircleView circleView;

    //初始的位置
    private float startX;
    private float startY;
    //按下的位置
    private float downX;
    private float downY;

    //移动后的位置
    private float moveX;
    private float moveY;


    private WindowManager.LayoutParams params;

    private FloatMenuView floatMenuView;
    private GarbageClearView garbageClearView;

    //小火箭circleView设置touch监听。
    private View.OnTouchListener circleViewOnTouchListener=new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction()){
                case MotionEvent.ACTION_DOWN:
                    //最后按下时的坐标。看ACTION_MOVE就会理解。
                    startX = event.getRawX();
                    startY = event.getRawY();

                    //按下时的坐标。
                    downX = event.getRawX();
                    downY = event.getRawY();

                    break;
                case MotionEvent.ACTION_MOVE:
                    circleView.setDrageState(true);
                      moveX = event.getRawX();
                      moveY=event.getRawY();

                    float dx = moveX -startX;
                    float dy=moveY-startY;
                    params.x+=dx;
                    params.y+=dy;

                    wm.updateViewLayout(circleView,params);
                    startX=moveX;
                    startY=moveY;

                    break;
                case MotionEvent.ACTION_UP:
                    float upx=event.getRawX();
                    if (upx>getScreenWidth()/2){
                        params.x=getScreenWidth()-circleView.width;
                    }else {
                        params.x=0;
                    }
                    circleView.setDrageState(false);
                   wm.updateViewLayout(circleView, params);

                    if (Math.abs(moveX-downX)>10){
                        return true;
                    }else {
                        return false;
                    }
                default:
                    break;
            }
            return false;
        }
    };


    private int getScreenWidth() {


      return wm.getDefaultDisplay().getWidth();

    }

    //得到屏幕的高度。
    private int getScreenHeigth() {

        return wm.getDefaultDisplay().getHeight();
    }

    //得到状态栏的高度。
    private int getStatusHeight(){
        Class<?> clazz = null;
         Object object;
        try {
            clazz = Class.forName("com.android.internal.R$dimen");
            object = clazz.newInstance();
            int x = Integer.parseInt(clazz.getField("status_bar_height")
                    .get(object).toString());
            return context.getResources().getDimensionPixelSize(x);
        } catch (Exception e) {
            return 0;
        }

    }


    private FloatViewManager( Context context){
        this.context=context;
        wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        circleView =new FloatCircleView(context);
        circleView.setOnTouchListener(circleViewOnTouchListener);
        circleView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //Toast.makeText(, "onclick", Toast.LENGTH_SHORT).show();
                //隱藏circleView,顯示菜单栏。
                wm.removeView(circleView);
                showFloatMenuView();
                garbageClearView.startAnimation();//进入悬浮框 直接清理
                floatMenuView.startAnimation();//进入悬浮框 动画
            }
        });
        floatMenuView = new FloatMenuView(context);
        garbageClearView = new GarbageClearView( context );


    }

    private void showFloatMenuView() {
       WindowManager.LayoutParams params = new WindowManager.LayoutParams();
        params.width=getScreenWidth();
        params.height=getScreenHeigth()-getStatusHeight();
        params.gravity= Gravity.BOTTOM|Gravity.LEFT;
        params.x=0;
        params.y=0;
        params.type=WindowManager.LayoutParams.TYPE_TOAST;
        params.flags= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
        params.format= PixelFormat.RGBA_8888;


        wm.addView(floatMenuView, params);

    }

    public static FloatViewManager getInstance(Context context){
        if (inStance==null){
            synchronized(FloatViewManager.class){
                if (inStance==null){
                    inStance=new FloatViewManager(context);
                }
            }
        }
        return inStance;
    }



    /**
     * 展示浮窗
     */
    public void showFloatCircleView(){
        //参数设置
        if (params==null){
            params = new WindowManager.LayoutParams();
            params.width=circleView.width;
            params.height=circleView.heigth;
            params.gravity= Gravity.TOP|Gravity.LEFT;
            params.x=0;
            params.y=0;
            params.type=WindowManager.LayoutParams.TYPE_TOAST;
            params.flags= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
            params.format= PixelFormat.RGBA_8888;
        }
        //先清除、防止重复创建、然后将小火箭加入窗体中。
//        wm.removeView( circleView );
            wm.addView(circleView, params);
    }
    public void hideFloatMenuView(){
        wm.removeView(floatMenuView);


    }

}

剩下的就是自定义View了,代码可以在文章末尾前往github白票

另外需要注意的两个点:
1、获取正在运行的进程由于google之前的ActivityManager不能适配高版本,在高版本时候只能获取前台界面(一般只能获取一个进程,就是自身)。可以使用AndroidProcesses,使用方法:
添加权限:

    <!--杀死进程-->
    <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />

添加依赖库:

//获取运行进程
    implementation 'com.jaredrummler:android-processes:1.0.9'

同步之后,使用如下获取正在运行List

List<AndroidAppProcess> mProcess = AndroidProcesses.getRunningAppProcesses();

然后遍历要杀死的进程

for ( AndroidAppProcess amProcess :mProcess ){
	//获取缓存
	if ( amProcess.name.contains(  "com.www" ) || amProcess.name.startsWith( "system" ) ) {
		Log.d( TAG, "扫描不杀的进程:" + amProcess.name );
		continue;
	}
	android.os.Debug.MemoryInfo[] memoryInfo = am
			                                           .getProcessMemoryInfo(new int[] { amProcess.pid });
	int memory = memoryInfo[0].getTotalPrivateDirty();
	AllMemorySize = AllMemorySize + memory;
	Log.d( TAG, "扫描要杀的进程:" + amProcess.name );
	
	
}

2、清理内存
需要使用系统隐藏api

然后使用以下方法:

/**
	 * 使用反射方法调用系统隐藏api: deleteApplicationCacheFiles 返回清除是否成功
	 * */
	private boolean deleteApplicationCacheFiles(String packageName) {
		isCleanCacheSucceed = false;

		try {
			Method method = PackageManager.class.getMethod(
					"deleteApplicationCacheFiles", new Class[] { String.class,
							IPackageDataObserver.class });
			method.invoke(pm, packageName, new IPackageDataObserver.Stub() {
				@Override
				public void onRemoveCompleted(String packageName,
				                              boolean succeeded) throws RemoteException {
					if(succeeded){
						Log.d("DYP", "deleteApplicationCacheFiles -->> succeeded "+succeeded);
						Log.d("DYP", "deleteApplicationCacheFiles -->> packageName "+packageName);
					}
					isCleanCacheSucceed = succeeded;
				}
			});
		} catch (Exception e) {
			// e.printStackTrace();
			Log.d("DYP", "deleteApplicationCacheFiles -->> catch ");
		}
		return isCleanCacheSucceed;
	}

实现效果

本文标签: 缓存 火箭 内存