我正在尝试运行以下代码。T代码的目的是检测调用并立即终止它。它包括:
1) 一个主服务类,其中包含用于与我使用的新线程进行通信的处理程序和一个具有要运行的代码的可运行对象。它还具有其他功能的基本实现。
2)另一个类扩展了侦听器所需的 PhoneStateListener。
我已经尝试了单个组件并加入了它们,但我是作为活动的一部分进行的。它们都工作正常,但现在我正在尝试通过使用运行单独线程的服务在后台完成所有这些工作。启动服务时,应用程序将中断。
public class Call_Message_Service extends Service {
Thread serviceThread;
CallStateListener callStateListener;
//Handler to allow communication with main thread to display some toasts.
public Handler serviceHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
Bundle bundle = msg.getData();
String string = bundle.getString("KEY");
Toast.makeText(Call_Message_Service.this, string, Toast.LENGTH_SHORT).show();
}
};
//Main runnable
Runnable serviceRunnable = new Runnable() {
@Override
public void run() {
TelephonyManager telephonyManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
Log.d(Constants.LOGTAG, "HERE_1");
callStateListener = new CallStateListener(serviceHandler);
//Register PhoneStateListener
telephonyManager.listen(callStateListener, PhoneStateListener.LISTEN_CALL_STATE);
}
};
@Override
public void onCreate() {
Toast.makeText(this,"Service Created", Toast.LENGTH_SHORT).show();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
serviceThread = new Thread (serviceRunnable);
serviceThread.start();
return START_STICKY;
}
@Override
public void onDestroy() {
Toast.makeText(this,"Service Destroyed", Toast.LENGTH_SHORT).show();
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
class CallStateListener extends PhoneStateListener{
String number;
Handler extraHandler;
public CallStateListener(Handler handler) {
Log.d(Constants.LOGTAG, "HERE_2");
extraHandler = handler;
}
@Override
public void onCallStateChanged(int state, String incomingNumber) {
//Store is number of the incoming call
number = incomingNumber;
//If phone is ringing
if (state == TelephonyManager.CALL_STATE_RINGING) {
Message msg = extraHandler.obtainMessage();
Bundle bundle = new Bundle();
String string = "Phone is Ringing";
bundle.putString("KEY",string);
disconnectCallAndroid();
}
//If incoming call received
if (state == TelephonyManager.CALL_STATE_OFFHOOK) {
Message msg = extraHandler.obtainMessage();
Bundle bundle = new Bundle();
String string = "Phone is Currently in a call";
bundle.putString("KEY",string);
}
//If not ringing or idle
if (state == TelephonyManager.CALL_STATE_IDLE) {
Message msg = extraHandler.obtainMessage();
Bundle bundle = new Bundle();
String string = "Phone is neither Ringing nor in a call";
bundle.putString("KEY",string);
}
}
//Function to disconnect call
public int disconnectCallAndroid()
{
Runtime runtime = Runtime.getRuntime();
int nResp = 0;
try
{
Log.d(Constants.LOGTAG, "service call phone 5 n");
runtime.exec("service call phone 5 n");
}catch(Exception exc)
{
Log.e(Constants.LOGTAG, exc.getMessage());
exc.printStackTrace();
}
return nResp;
}
}
至少这是代码应该做的。我认为问题在于尝试从可运行的侦听器注册侦听器,但我很确定还有更多问题。如果有人能指出代码的所有错误,那就太好了。
主要活动非常简单,只是一个按钮,按下时启动服务。服务启动,执行一直到第一个日志,但之后中断,出现错误"java.lang.RuntimeException:无法在未调用 Looper.prepare()的线程中创建处理程序"
以下是正在发生的事情:
要传递给CallStateListener
的serviceHandler
正在单独的Thread
上执行的Runnable
中使用。
当Handler
用于新Thread
时,它需要附加到Thread
的Looper
上。Looper
负责管理该特定Thread
的MessageQueue
。如果没有附加Looper
,则Handler
无法处理Messages
(或Runnables
)。
您可能会问,为什么我不需要将主Thread
连接到Looper
呢?
Android 在Application
启动时将主Thread
附加到其Looper
。此交互由 ActivityThread
管理。如果你看一下ActivityThread
的来源,你会看到有一个对Looper.prepareMainLooper();
的调用。