即使在使用START_STICKY之后,服务也不会始终运行

时间:2016-02-26 09:21:44

标签: android service

问题

即使我使用了START_STICKY,服务也不会一直运行。

有时候我没有得到任何Togoing Action for Outgoing,这是否意味着服务在一段时间后停止了?

我的要求

只要用户通过电话拨打电话,应用就会显示Toast。为此,我使用BroadcastReceiver来点击调用操作和服务(始终运行Receiver)。一旦我开始这项活动,它就会在拨打电话时开始显示吐司..但不是总是。

以下是完整的代码 -

MainActivity.class

public class MainActivity extends Activity 
{
    CallNotifierService m_service;
    boolean isBound = false;

    private ServiceConnection m_serviceConnection = new ServiceConnection() 
    {
        @Override
        public void onServiceConnected(ComponentName className, IBinder service) 
        {
            m_service = ((CallNotifierService.MyBinder)service).getService();
            Toast.makeText(MainActivity.this, "Service Connected", Toast.LENGTH_LONG).show();
            isBound = true;
            Intent intent = new Intent(MainActivity.this, CallNotifierService.class);
            startService(intent);
        }

        @Override
        public void onServiceDisconnected(ComponentName className) 
        {
            m_service = null;
            isBound = false;
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Intent intent = new Intent(this, CallNotifierService.class);
        bindService(intent, m_serviceConnection, Context.BIND_AUTO_CREATE);
    }
    .
    .
    .
}

CallNotifierService.class

public class CallNotifierService extends Service 
{
    private final IBinder myBinder = new MyBinder();
    private static final String ACTION_OUTGOING_CALL = "android.intent.action.NEW_OUTGOING_CALL";

    private CallBr br_call;

    @Override
    public IBinder onBind(Intent arg0) 
    {
        return myBinder;
    }

    @Override
    public void onDestroy() 
    {
        Log.d("service", "destroy");
        this.unregisterReceiver(this.br_call);
        Toast.makeText(CallNotifierService.this, "Receiver Un-Registered", Toast.LENGTH_LONG).show();
        super.onDestroy();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId)
    {
        final IntentFilter filter = new IntentFilter();
        filter.addAction(ACTION_OUTGOING_CALL);
        this.br_call = new CallBr();
        this.registerReceiver(this.br_call, filter);
        Toast.makeText(CallNotifierService.this, "onStartCommand Called", Toast.LENGTH_LONG).show();
        return START_STICKY;
    }

    public class MyBinder extends Binder 
    {
        CallNotifierService getService() 
        {
            return CallNotifierService.this;
        }
    }

    public class CallBr extends BroadcastReceiver 
    {
        public CallBr() {}

        @Override
        public void onReceive(Context context, Intent intent) 
        {
            Toast.makeText(context, "Action:"+intent.getAction(), Toast.LENGTH_LONG).show();
        }
    }
}

2 个答案:

答案 0 :(得分:5)

你在这里得到了错误的方法,通过混合一个简单的想法(如果做得正确可以工作)和更复杂的想法(这是行不通的)。

请记住:服务不是"始终在运行"组件,即使使用START_STICKY。

Android系统会毫不犹豫地杀死你的服务,如果它需要其他地方的内存。 START_STICKY仅表示Android系统会尽可能重新启动您的服务,并按指定的in the documentation调用onStartCommand。

如果您需要真正的服务,那么您必须使用foreground service。但它会对用户界面造成影响(恼人的通知图标总是显示)和电池寿命,你不需要这里。

现在,这是一个神奇的伎俩:您的应用无需为了您的BroadcastReceiver工作而运行。您需要做的就是使用正确的intent-filter在AndroidManifest.xml中注册它:

<receiver android:name=".broadcastreceivers.CallBroadcastReceiver">
    <intent-filter>
        <action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
    </intent-filter>
</receiver>

(同时确保您的应用具有所需的权限,即PROCESS_OUTGOING_CALLS。)

然后您在代码中所需要的只是:

public class CallBroadcastReceiver extends BroadcastReceiver 
{
    @Override
    public void onReceive(Context context, Intent intent) 
    {
        Toast.makeText(context, "Action: " + intent.getAction(), Toast.LENGTH_LONG).show();
    }
}

没有活动(除了要求Android 6+上的PROCESS_OUTGOING_CALLS权限),没有服务,没有。简单且省电!

答案 1 :(得分:0)

服务会重新创建,而不是未重新启动。 如果您覆盖onCreate并执行Log.d或Toast,您将看到在应用程序销毁后将被调用。

因此,在重新创建它后使其保持运行的诀窍是在onCreate方法上执行代码,并使用onStartCommand仅返回START_STICKY。