服务无法从BroadcastReceiver运行? - Android

时间:2012-07-10 22:31:59

标签: android broadcastreceiver android-service

我正试图在我的手机上有拨出电话时运行我的服务。但由于某种原因,当发生这种情况时我的服务不会运行。我知道“CallReceiver”的代码执行,因为我使用了Toast消息来显示它是否运行。我可以通过我的主要活动来运行服务,但这意味着无论是否拨打电话都会运行....

以下是我的代码:

接收方:

package com.example.hiworld;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;

public class CallReceiver extends BroadcastReceiver{

    @Override
    public void onReceive(Context context, Intent intent) {
        context.startService(new Intent(context, CallService.class));

        Toast.makeText(context, "Call Receiver started",
                Toast.LENGTH_LONG).show();

        Log.d("Calling Someone", "onReceived");

    }


}

服务:

package com.example.hiworld;


import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.telephony.TelephonyManager;
import android.widget.Toast;

public class CallService extends IntentService  {

    public long StartTime=0;
    public long EndTime =0; 
    public long TotalTime = 0; 
    public long NumFreeMins = 0;


    public CallService() {
          super("CallService");
      }

    @Override
    protected void onHandleIntent(Intent intent) {


        StartTime = (System.currentTimeMillis())/60;

        TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);




            if(tm.getCallState()==0) //getting the time whenever the phone is off 
            {

                EndTime = (System.currentTimeMillis())/60;
                TotalTime = EndTime-StartTime;
                 NumFreeMins = 300-TotalTime; 

                 //notify user
                 this.displaymsg();

            }   



    }

public void displaymsg()
{
    Toast toast = Toast.makeText(getApplicationContext(), ""+NumFreeMins, Toast.LENGTH_SHORT);
    toast.show();
}
}

我见过有人使用这条线:

context.startService(new Intent(this, CallService.class));

而不是:

context.startService(new Intent(context, CallService.class));

但后者对我不起作用......

2 个答案:

答案 0 :(得分:1)

尝试在清单中为特定“操作”的<intent-filter>指定IntentService。实施例...

<service
    android:name=".CallService" >
    <intent-filter>
        <action android:name="com.example.hiworld.intent.DO_SOMETHING" />
    </intent-filter>
</service>

然后在您onReceive(...)的{​​{1}}方法中执行以下操作...

BroadcastReceiver

修改

我根据您发布到pasrebin的代码构建了一个简单的测试应用程序。我为清单,接收器和服务保留了相同的代码,只需添加一个默认的Intent callReceiverIntent = new Intent("com.example.hiworld.intent.DO_SOMETHING"); // Put the Intent received by the BroadcastReceiver as extras so the // IntentService can process it... callReceiverIntent.putExtras(intent); context.startService(callReceiverIntent); 即可运行它。

我可以从日食的DDMS视角监视logcat,Activity成功收到CallReceiver NEW_OUTGOING_CALL,并且确实启动了Intent。< / p>

然而,问题是尝试显示来自CallService的{​​{1}}导致由于“泄露的处理程序”而导致异常并且无声地崩溃。

这背后的原因是Toast使用后台线程来执行其工作并尝试从非UI线程显示IntentService(即,UI元素)因为应用程序没有运行UI组件。因此,无论您使用的是本地IntentService变量还是Toast,都没有用于关联context的UI上下文。

getApplicationContext()启动Toast时它起作用的原因显然是因为CallService提供了Activity可以使用的UI上下文。简而言之,似乎尝试使用Activity中的Toast并不是一个好主意,除非Toast 始终由UI组件启动并且即便如此,拥有后台线程创建UI元素(例如IntentService)可能会导致问题。

使用当前模型的唯一方法是将IntentService更改为Toast。默认情况下,IntentService的代码执行是在主(UI)线程上完成的,Service显示Service是完全合法的,无论是否有任何应用程序Service显示与否。实际上,我修改了代码以使用Toast并将Activities中的代码放在Service中,我可以在拨打电话时看到onHandleIntent

答案 1 :(得分:0)

尝试

context.startService(new Intent(context.getApplicationContext(), CallService.class));