android - 即使在我使用了 START_STICKY 之后,服务也不总是运行

标签 android service

问题

即使在我使用了 START_STICKY 之后,服务也并非始终运行。

有时我没有收到任何拨出电话的 Toast Action,这是否意味着服务会在一段时间后停止?

我的需求

每当用户从手机拨出电话时,应用程序都会显示 Toast。为此,我使用 BroadcastReceiver 来点击调用操作和服务(始终运行 Receiver)。一旦我开始这项 Activity ,它就会在拨出电话时开始显示 toast ..但并非总是如此。

完整代码如下-

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

最佳答案

你在这里得到了错误的方法,将一个简单的想法(如果正确完成会起作用)与更复杂的想法(不起作用)混合在一起。

请记住:服务不是“始终运行”的组件,即使在使用 START_STICKY 时也是如此。

如果 Android 系统在其他地方需要内存,它会毫不犹豫地终止您的服务。 START_STICKY 仅表示 Android 系统将在可能的情况下重新启动您的服务,并按指定调用 onStartCommand in the documentation .

如果您需要一项服务以真正坚持下去,那么您必须使用 foreground service .但这会对 UI(烦人的通知图标总是显示)和电池生命周期产生影响,您在这里不需要这样做。

现在这是魔术:您的应用程序不需要运行您的 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();
    }
}

没有 Activity (除了在 Android 6+ 上请求 PROCESS_OUTGOING_CALLS 权限),没有服务,什么都没有。简单且省电!

关于android - 即使在我使用了 START_STICKY 之后,服务也不总是运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35647788/

相关文章:

image - 将Redmine docker容器部署到应用服务

java - 清除最近任务时防止杀死服务

android - 如何根据点击的 recyclerview 项目打开新 Activity ?

java - 通过蓝牙服务名称连接

安卓服务生命周期

java - (Linux) 如果 ssh 关闭,如何取回 java 应用程序(等待输入)?

android - 选择 4 个网格位置之间的所有条目

android - C++ 中对构造函数的 undefined reference

android - 强制刷新UiThread android的MessageQueue

java - 如何将纬度和经度从数据库传递到 Google Maps Activity