在runnable中注册监听器

时间:2015-01-01 20:40:03

标签: android multithreading service runnable

我正在尝试运行以下代码。 Ť 他的目的是检测一个呼叫并立即终止它。它包括:

1)一个主服务类,它包含与我使用的新线程进行通信的处理程序和一个运行代码的runnable。它还具有其他功能的基本实现。

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;
}
}

至少这是代码应该做的事情。我认为问题在于尝试从runnable注册一个监听器,但我很确定还有更多的问题。 如果有人能指出代码中的所有错误,那就太好了。

主要活动非常简单,只需按一下按钮即可启动服务。服务启动并执行到第一个Log,但在那之后出现错误" java.lang.RuntimeException:无法在未调用Looper.prepare()&的线程内创建处理程序#34;

1 个答案:

答案 0 :(得分:1)

以下是发生的事情:

您传递给serviceHandler的{​​{1}}正在CallStateListener内使用Runnable

如果在新Thread上使用Handler,则需要将其附加到Thread ThreadLooper负责管理该Looper的{​​{1}}。如果没有MessageQueue附加,则Thread无法处理Looper(或Handler)。

您可能会问,为什么我不需要将主Messages附加到Runnables,然后呢?

Thread开始时,

Android会将主Looper附加到Thread。此互动由Looper管理。如果您查看Application的来源,您会看到有ActivityThread的来电。