本篇总结Android开发中可能会用到的一些工具方法,亲测可用,免得需要的时候搜方法试。
异步耗时操作的结果同步返回
使用Java并发包java.util.concurrent同步工具类CountDownLatch和Future将异步结果同步返回。
有几个异步任务就给CountDownLatch初始化为几,在线程池的线程执行异步耗时操作,每收到一个异步任务的结果就将结果保存下来,调用countDown()将计数-1,当CountDownLatch计数为0说明所有异步任务都执行结束,将结果返回,即赋值给future。
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
- 使用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());
}
}
- 使用 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());
}
}