Android--总结工具方法

本篇总结Android开发中可能会用到的一些工具方法,亲测可用,免得需要的时候搜方法试。

异步耗时操作的结果同步返回
  1. 使用Java并发包java.util.concurrent同步工具类CountDownLatch和Future将异步结果同步返回。

  2. 有几个异步任务就给CountDownLatch初始化为几,在线程池的线程执行异步耗时操作,每收到一个异步任务的结果就将结果保存下来,调用countDown()将计数-1,当CountDownLatch计数为0说明所有异步任务都执行结束,将结果返回,即赋值给future。

  3. CountDownLatch可以设置超时时间,在超时时间内计数未清零,则抛出超时Exception。future也可以设置超时时间,在超时时间内没拿到结果,也会抛出超时异常。

    // 假设 SDK 的回调接口
    public interface SdkCallback {
        void onSuccess(String result);
        void onFailure(Exception e);
    }

    // 假设 SDK 异步方法1
    public void asyncSdkCall1(SdkCallback callback) {
        new Thread(() -> {
            try {
                Thread.sleep(5000); // 模拟耗时操作
                callback.onSuccess("SDK1 Result");
            } catch (InterruptedException e) {
                callback.onFailure(e);
            }
        }).start();
    }

    // 假设 SDK 异步方法2
    public void asyncSdkCall2(SdkCallback callback) {
        new Thread(() -> {
            try {
                Thread.sleep(7000); // 模拟耗时操作
                callback.onSuccess("SDK2 Result");
            } catch (InterruptedException e) {
                callback.onFailure(e);
            }
        }).start();
    }

    /**
     * 同步调用方法
     */
    private String syncFun(){
        ExecutorService executor = Executors.newSingleThreadExecutor();
        Future<String> future = executor.submit(new Callable<String>() {
            @Override
            public String call() throws Exception {
                // 等待单个异步调用结果
//                final CountDownLatch latch = new CountDownLatch(2);
//                final String[] result = {null};
//                final String[] error = {null};
                // 等待多个异步调用结果
                final CountDownLatch latch = new CountDownLatch(2);
                final String[] result = new String[2];
                final String[] error = new String[2];

                asyncSdkCall1(new SdkCallback() {
                    @Override
                    public void onSuccess(String res) {
                        result[0] = res;
                        latch.countDown();
                    }

                    @Override
                    public void onFailure(Exception e) {
                        error[0] = "error";
                        latch.countDown();
                    }
                });

                asyncSdkCall2(new SdkCallback() {
                    @Override
                    public void onSuccess(String res) {
                        result[1] = res;
                        latch.countDown();
                    }

                    @Override
                    public void onFailure(Exception e) {
                        error[1] = "error";
                        latch.countDown();
                    }
                });

                try {
                    boolean completed = latch.await(10, TimeUnit.SECONDS);
                    if (!completed) {
                        throw new RuntimeException("SDK call timed out");
                    }
                    if (error[0] != null) {
                        return error[0];
                    }
                    return result[0];
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    throw new RuntimeException("Interrupted while waiting for SDK result");
                }

            }
        });

        try {
            return future.get(10, TimeUnit.SECONDS); // 阻塞等待
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new RuntimeException("Interrupted while waiting for SDK result");
        } catch (ExecutionException e) {
            throw new RuntimeException("SDK call failed: " + e.getCause().getMessage());
        } catch (TimeoutException e) {
            throw new RuntimeException("SDK call timed out");
        } finally {
            executor.shutdown();
        }
    }


方法调用:

        new Thread(new Runnable() {
            @Override
            public void run() {
                Log.d("========", "syncFun: " + syncCaptureCard());
            }
        }).start();
杀死APP
  1. 使用ActivityManager的隐藏API forceStopPackage ,需要通过反射调用。

adb shell ps 可以查看正在运行的进程,用来验证执行结果。

添加权限:<uses-permission android:name="android.permission.FORCE_STOP_PACKAGES " />

    /**
     * 杀死应用进程
     */
    public void killPackage(String packageName) {
        Log.d(TAG, "killPackage = " + packageName);
        // ActivityManager.forceStopPackage 杀死应用进程
        try {
            // 获取 ActivityManager
            ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
            if (activityManager != null) {
                // 使用反射调用 forceStopPackage 方法
                Class<?> activityManagerClass = Class.forName("android.app.ActivityManager");
                java.lang.reflect.Method forceStopPackageMethod = activityManagerClass.getDeclaredMethod("forceStopPackage", String.class);
                forceStopPackageMethod.setAccessible(true);
                forceStopPackageMethod.invoke(activityManager, packageName);
                Log.d(TAG, "Package " + packageName + " has been force stopped.");
            }
        } catch (Exception e) {
            Log.e(TAG, "Failed to force stop package: " + e.getMessage());
        }
    }
  1. 使用 Shell 命令杀死应用进程
    /**
     * 杀死应用进程
     */
    public void killPackage(String packageName) {
        try {
            // 使用 Shell 命令杀死应用进程
            Process process = Runtime.getRuntime().exec("am force-stop " + packageName);
            int exitCode = process.waitFor();
            if (exitCode == 0) {
                Log.d(TAG, "Package " + packageName + " has been force stopped.");
            } else {
                Log.e(TAG, "Failed to force stop package: " + packageName + ", exit code: " + exitCode);
            }
        } catch (Exception e) {
            Log.e(TAG, "Failed to force stop package: " + e.getMessage());
        }
    }
卸载APK

使用PackageManager的隐藏API deletePackage ,需要通过反射调用。

也有通过shell命令卸载APK的方法,但是测试执行失败了,后续再排查。

adb shell pm list packages -3 用来查看设备中的package,可以验证方法执行结果

添加权限:<uses-permission android:name="android.permission.DELETE_PACKAGES" />

    /**
     * 卸载 APK
     */
    public void uninstallPackage(String packageName) {
        // PackageManager.deletePackage 卸载应用进程
        try {
            // 获取 PackageManager
            PackageManager packageManager = getPackageManager();
            if (packageManager != null) {
                // 使用反射获取 IPackageDeleteObserver 类
                Class<?> ipackageDeleteObserverClass = Class.forName("android.content.pm.IPackageDeleteObserver");

                // 创建 IPackageDeleteObserver 的代理实例
                Object packageDeleteObserver = Proxy.newProxyInstance(
                        ipackageDeleteObserverClass.getClassLoader(),
                        new Class<?>[]{ipackageDeleteObserverClass},
                        new InvocationHandler() {
                            @Override
                            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                                if (method.getName().equals("packageDeleted")) {
                                    String pkgName = (String) args[0];
                                    int returnCode = (int) args[1];
                                    if (returnCode == 0) {
                                        Log.d(TAG, "Package " + pkgName + " has been successfully uninstalled.");
                                    } else {
                                        Log.e(TAG, "Failed to uninstall package: " + pkgName + ", returnCode: " + returnCode);
                                    }
                                }
                                return null;
                            }
                        });
                // 使用反射调用 deletePackage 方法
                Class<?> packageManagerClass = Class.forName("android.app.ApplicationPackageManager");
                Method deletePackageMethod = packageManagerClass.getDeclaredMethod("deletePackage", String.class, ipackageDeleteObserverClass, int.class);
                deletePackageMethod.setAccessible(true);

                // 调用 deletePackage 方法
                deletePackageMethod.invoke(packageManager, packageName, packageDeleteObserver, 0);
            }
        } catch (Exception e) {
            Log.e(TAG, "Failed to uninstall package: " + e.getMessage());
        }
    }

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容