我正试图在我的手机上有拨出电话时运行我的服务。但由于某种原因,当发生这种情况时我的服务不会运行。我知道“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));
但后者对我不起作用......
答案 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));