当通过反射调用Android隐藏的API永久冻结调用线程时,我遇到一种非常不寻常的情况。我无法调试基础代码,因为它是Android本身的代码,通常不可见。我尝试在正常线程中的asynctask中运行代码,但也不用asynctask.cancel或thread.interrupt杀死线程,线程保持可见,我可以在调试时看到它。真的不可能运行封装的代码并最终将其彻底杀死吗? 此问题仅在Android O上且仅在某些设备上出现,这就是为什么我需要对其进行测试以查看其是否可以在当前设备上运行并能够激活相应功能。下面的代码,我真的没有找到解决方案:
Thread endCallThread;
Runnable myRunnable;
private void checkFeatureSupport(final Context context) {
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.CALL_PHONE) == PackageManager.PERMISSION_GRANTED) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
myRunnable = new Runnable() {
@Override
public void run() {
doInBackgroundWrapper();
if (getActivity() != null) {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
//handleResult();
}
});
}
}
};
endCallThread = new Thread(myRunnable, "endCallThread");
endCallThread.start();
new CountDownTimer(3000, 3000) {
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
Log.e("TESTAUTOMATION", "endCall did not finished in 3 seconds");
// stop async task if not in progress
if (endCallThread.isAlive()) {
try {
endCallThread.interrupt();
endCallThread = null;
myRunnable = null;
System.gc();
Log.e("TESTAUTOMATION", "endCallThread interrupted");
} catch (Exception ex) {
Log.e("TESTAUTOMATION", "endCallThread interrupted exception");
}
//handleResult();
}
}
}.start();
} else {
mEndCallSupported = true;
}
}
}
private void doInBackgroundWrapper() {
try {
if (getContext() == null) {
return;
}
final TelephonyManager telMan = (TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE);
if (telMan == null) {
return;
}
final Class<?> classTemp = Class.forName(telMan.getClass().getName());
final Method methodTemp = classTemp.getDeclaredMethod("getITelephony");
methodTemp.setAccessible(true);
ITelephony telephonyService = (ITelephony) methodTemp.invoke(telMan);
// If this call does not return a security exception we say the call principally works.
Log.d("TESTAUTOMATION", "endCall before");
// This call endCall may freeze depending on device, mostly seen on Nexus 5x with Android 8&8.1
telephonyService.endCall();
Log.d("TESTAUTOMATION", "endCall after");
mSupported = true;
} catch (Exception ex) {
ex.printStackTrace();
mSupported = false;
}
}
要重现此设备,最好不要插入SIM卡。
答案 0 :(得分:0)
Thread.interrupt()
通常不会停止线程,它只是将特定的布尔字段(isInterrupted
)标记为true
。如果开发人员想要在某个时刻停止线程的工作(在调用Thread.interrupt()
之后),则可以在he is implementing some work in a separate thread时依靠此布尔值Thread.isInterrupted()
来实现。
因此,我想在反射的隐藏方法中没有进行此类检查。
要停止您的线程,您可以尝试弃用Thread.stop()
,但它是a really bad practice.