Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/353.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如果从recents中删除应用程序,则不会调用Receiver_Java_Android_Broadcastreceiver - Fatal编程技术网

Java 如果从recents中删除应用程序,则不会调用Receiver

Java 如果从recents中删除应用程序,则不会调用Receiver,java,android,broadcastreceiver,Java,Android,Broadcastreceiver,我正在开发的应用程序,发送短信的活动通话结束 Manifest.xml <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="xxx.xxxx.xxxx.xxxx"> <uses-permission android:name="android.permission.RECEIVE_BO

我正在开发的应用程序,发送短信的活动通话结束

Manifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="xxx.xxxx.xxxx.xxxx">

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.WRITE_SMS" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:theme="@style/AppTheme.NoActionBar">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

    <service
        android:name=".MonitorService"
        android:enabled="true"
        android:exported="true" />
    <service
        android:name=".SendText"
        android:exported="false" />

    <receiver
        android:name=".BootReceiver"
        android:enabled="true"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>
</application>

</manifest>
实现的接收器运行时为:

public class MonitorService extends Service
{
// Notification variables

private BroadcastReceiver mCallBroadcastReceiver = new BroadcastReceiver()
{
    @Override
    public void onReceive(Context context, Intent intent)
    {
        String action = intent.getAction();

        if (action.equalsIgnoreCase("android.intent.action.PHONE_STATE"))
        {
            if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_RINGING))
            {
                Log.d("RECEIVER X: ", "INCOMING CALL...");
            }
            if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_IDLE))
            {
                Log.d("RECEIVER X: ", "CALL ENDS HERE...");
                Intent Dispatcher = new Intent(context, SendText.class);
                startService(Dispatcher);
            }
            if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_OFFHOOK))
            {
                Log.d("RECEIVER X: ", "ACTIVE CALL GOING ON...");
            }
        }
    }
};

public MonitorService() { }

@Override
public void onCreate()
{
    super.onCreate();

    // created notification here
    // also registered broadcast receiver here

    mBuilder.setChannelId(NOTIFICATION_CHANNEL_ID);
    startForeground(17, mBuilder.build());
}

@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
    Log.d("WatchMan : ", "\nmCallBroadcastReceiver Listening....");

    //return super.onStartCommand(intent, flags, startId);

    return START_STICKY;
}

@Override
public void onDestroy()
{
    this.unregisterReceiver(mCallBroadcastReceiver);
    Log.d("WatchMan : ", "\nDestroyed....");
    Log.d("WatchMan : ", "\nWill be created again....");
}

@Override
public IBinder onBind(Intent intent)
{
    // TODO: Return the communication channel to the service.
    throw new UnsupportedOperationException("Not yet implemented");
}
}
  • Broadcastreceiver
    在服务级别上工作正常;即使应用程序从最近的应用程序列表中删除,但如果从最近的应用程序列表中删除,则在下一次
    boot\u complete
    时,它也不会再次呼叫接收器。如果应用程序未从最近删除。。。然后在每次启动时,它都会被触发,广播接收器工作正常。我尝试过android:从最近的事件中排除,但这不是实现它的方法
有人能帮我解决这个问题吗。谢谢

更新2

我研究了github上的
Firebase JobDispatcher
文档,并将其用作以下内容:

  • 在gradle项目文件中实现依赖性
  • 然后同步成功
  • 创建了一个JobService
  • 创建了一个作业并计划了它
  • 它也在启动完成时被触发



  • 我应该如何安排它只在重新启动/引导完成时运行一次
  • 我只想重复一次停止..:SetRecurtive(false),false可以吗?true应该是true吗
  • setLifetime(Lifetime.UNTIL_下次启动)将其设置为FOREVER这没关系
  • setTrigger(Trigger.executionWindow(0,60))未获取此
  • setReplaceCurrent(false)是可以
  • 使用指数回退重试这是什么

  • 如何将这些标记设置为在启动/重新启动时启动,并且只启动一次,如果启动失败,请尝试,不要再次启动。在每次启动后使用FirebaseJobDispatcher重新启动您的服务。有关JobDispatcher的更多信息,请参阅。

    • 如果应用程序是由用户第一次安装的或强制停止的,
      广播接收器
      将不会运行,直到用户至少手动运行一次应用程序

    • 根据&

      • 请注意,应用程序的停止状态与
        活动的停止状态不同。系统分别管理这两种停止状态

      • 当应用程序首次安装但尚未启动时,以及当应用程序手动运行时,应用程序处于停止状态 用户已停止(在管理应用程序中)。(他们的意思是力量 停止应用程序

    • Htc设备从此添加
      com.Htc.intent.action.QUICKBOOT\u POWERON
      >

      为您的JobIntent服务排队工作:

      public class BootReceiver extends BroadcastReceiver
      {
      @Override
      public void onReceive(Context context, Intent intent)
      {
          Log.d("BootTest : ", "\nOnBootReceiver - Received a broadcast!");
          Toast.makeText(context, "InstaPromo Is Ready !!", Toast.LENGTH_LONG).show();
          if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
          {
              context.startForegroundService(new Intent(context, MonitorService.class));
          }
          else
          {
              context.startService(new Intent(context, MonitorService.class));
          }
      }
      }
      
      public class BootReceiver extends BroadcastReceiver {
      
          @Override
          public void onReceive(Context context, Intent intent) {
              if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
                  MyService.enqueueWork(context, new Intent());
              }
          }
      
      }
      
      public class MyJobIntentService extends JobIntentService {
      
          public static final int JOB_ID = 0x01;
      
          public static void enqueueWork(Context context, Intent work) {
              enqueueWork(context, MyJobIntentService.class, JOB_ID, work);
          }
      
          @Override
          protected void onHandleWork(@NonNull Intent intent) {
              // your code
          }
      
      /**
       * This will be called if the JobScheduler has decided to stop this job.  The job for
       * this service does not have any constraints specified, so this will only generally happen
       * if the service exceeds the job's maximum execution time.
       *
       * @return True to indicate to the JobManager whether you'd like to reschedule this work,
       * false to drop this and all following work. Regardless of the value returned, your service
       * must stop executing or the system will ultimately kill it.  The default implementation
       * returns true, and that is most likely what you want to return as well (so no work gets
       * lost).
       */
      public boolean onStopCurrentWork() {
          return true;
      }
      
      }
      
      定义您的JobIntentService:

      public class BootReceiver extends BroadcastReceiver
      {
      @Override
      public void onReceive(Context context, Intent intent)
      {
          Log.d("BootTest : ", "\nOnBootReceiver - Received a broadcast!");
          Toast.makeText(context, "InstaPromo Is Ready !!", Toast.LENGTH_LONG).show();
          if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
          {
              context.startForegroundService(new Intent(context, MonitorService.class));
          }
          else
          {
              context.startService(new Intent(context, MonitorService.class));
          }
      }
      }
      
      public class BootReceiver extends BroadcastReceiver {
      
          @Override
          public void onReceive(Context context, Intent intent) {
              if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
                  MyService.enqueueWork(context, new Intent());
              }
          }
      
      }
      
      public class MyJobIntentService extends JobIntentService {
      
          public static final int JOB_ID = 0x01;
      
          public static void enqueueWork(Context context, Intent work) {
              enqueueWork(context, MyJobIntentService.class, JOB_ID, work);
          }
      
          @Override
          protected void onHandleWork(@NonNull Intent intent) {
              // your code
          }
      
      /**
       * This will be called if the JobScheduler has decided to stop this job.  The job for
       * this service does not have any constraints specified, so this will only generally happen
       * if the service exceeds the job's maximum execution time.
       *
       * @return True to indicate to the JobManager whether you'd like to reschedule this work,
       * false to drop this and all following work. Regardless of the value returned, your service
       * must stop executing or the system will ultimately kill it.  The default implementation
       * returns true, and that is most likely what you want to return as well (so no work gets
       * lost).
       */
      public boolean onStopCurrentWork() {
          return true;
      }
      
      }
      

      你的目标sdk是什么version@RohitSharma,min sdk=21,编译sdk 26,目标sdk 26;你能不能试着把你的targetSdkVersion保持在25或更低,并检查反馈,类似的情况下,它也在重新启动时运行。。(即使从最近删除)在Oreo下方和上方,只有在Oreo中,如果从最近删除,则在重新启动时不会调用它,直到再次打开应用程序。。。谷歌强制目标SDK 26。。。现在上传到play Store有两个星期了,你有没有尝试过我提到的
      JobIntentService
      ,它是否支持Api级别26、27。。。(安卓和下一个…)?即使用户将应用程序从最近的列表中删除,它是否能保证每次启动完成后重新启动服务?@sandhyasasane是的,它支持API返回API 14。是的,它保证了,我个人在通过builder初始化作业调度程序时使用了相同的方法Use
      setReplaceCurrent(true)
      属性。如果您想在重新启动期间保持作业,也不要忘记添加
      setLifetime(Lifetime.FOREVER)
      。不,您不需要这样做。顺便问一下,Google Play是否预装了One Plus 3?1)强制停止与从最近删除它不同2)Oreo如果你在清单中对接收器执行多个操作,它不会调用它;只需要保留允许的extempted意图操作,无论哪个操作不允许在运行时实现它。。。您可以查看代码。严格按照文件要求是的,很明显;但是如何在JobIntentService中实现注册和注销运行时接收器。。。?允许吗?
      public class MyJobIntentService extends JobIntentService {
      
          public static final int JOB_ID = 0x01;
      
          public static void enqueueWork(Context context, Intent work) {
              enqueueWork(context, MyJobIntentService.class, JOB_ID, work);
          }
      
          @Override
          protected void onHandleWork(@NonNull Intent intent) {
              // your code
          }
      
      /**
       * This will be called if the JobScheduler has decided to stop this job.  The job for
       * this service does not have any constraints specified, so this will only generally happen
       * if the service exceeds the job's maximum execution time.
       *
       * @return True to indicate to the JobManager whether you'd like to reschedule this work,
       * false to drop this and all following work. Regardless of the value returned, your service
       * must stop executing or the system will ultimately kill it.  The default implementation
       * returns true, and that is most likely what you want to return as well (so no work gets
       * lost).
       */
      public boolean onStopCurrentWork() {
          return true;
      }
      
      }