如何在 Android 10 中打开 activity(传入 voip 呼叫)

How to open activity (incoming voip call) in Android 10

在 Android 10 中应用了新的应用限制。 我们不能再从后台启动 activity。虽然这对大多数应用程序来说可能没问题,但对于需要在推送通知到达后显示来电的 voip 应用程序来说,这是一个致命的打击。

根据这个 https://developer.android.com/guide/components/activities/background-starts 有一个条件列表可以满足仍然允许打开 activity,但是我不完全理解(这里不是英语母语) .

我绝对知道的是:

我需要达到的目标:

如何在 android 10 中为传入的 voip 呼叫打开 activity? 在锁屏界面等等,就像普通用户对 PHONE 应用程序的期望一样。

提前感谢您的任何提示。

使用带有 "full-screen intent" 的高优先级通知。那将:

  • 如果设备已锁定
  • ,请调用您的"full-screen intent"
  • 否则,显示 "heads-up" 通知

请阅读我的博客,了解如何为 OS 10 打开 activity 以及如何显示提醒通知和处理操作按钮上的点击。

https://medium.com/@dcostalloyd90/show-incoming-voip-call-notification-and-open-activity-for-android-os-10-5aada2d4c1e4

检查这个link这对你有帮助 here

您需要请求“绘制其他应用程序”的权限,然后才能像以前的版本一样制作

  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            if (!Settings.canDrawOverlays(this)) {
                RequestPermission();

        }
        }

    private void RequestPermission() {
        // Check if Android P or higher
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            // Show alert dialog to the user saying a separate permission is needed
            // Launch the settings activity if the user prefers
            Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                    Uri.parse("package:" + BuildConfig.APPLICATION_ID));
            startActivityForResult(intent, 
            ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE);
        }
     }

或者你可以使用我的这个answer

在锁定屏幕上打开 Activity。您可以使用具有“全屏意图”的高通知作为 CommonsWare 的答案。但有关更多详细信息,您可以尝试我的解决方案,如下代码:

  1. 创建一个前台服务然后在onStartCommand方法中调用buildNotification,buildNotification方法将return一个通知放入startForeground方法参数。

     public class IncomingCallService extends Service {
         public int onStartCommand(Intent intent, int flags, int startId) {
             Notification notification = buildNotification();
             startForeground(1, notification);
             return START_NOT_STICKY;
         }
     }
    
  2. 在 buildNotification 方法中,我们将创建具有高优先级、调用类别和全屏意图的通知。

     private Notification buildNotification() {
         Intent fullScreenIntent = new Intent(this, IncomingCallActivity.class);
         PendingIntent fullScreenPendingIntent = PendingIntent.getActivity(this, 0, fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT);
         NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    
         NotificationCompat.Builder notificationBuilder =
             new NotificationCompat.Builder(this)
                     .setSmallIcon(R.drawable.ic_notification_icon)
                     .setContentTitle("Incoming call")
                     .setContentText("(919) 555-1234")
                     .setPriority(NotificationCompat.PRIORITY_HIGH)
                     .setCategory(NotificationCompat.CATEGORY_CALL)
                     // Use a full-screen intent only for the highest-priority alerts where you
                     // have an associated activity that you would like to launch after the user
                     // interacts with the notification. Also, if your app targets Android 10
                     // or higher, you need to request the USE_FULL_SCREEN_INTENT permission in
                     // order for the platform to invoke this notification.
                     .setFullScreenIntent(fullScreenPendingIntent, true);
         notificationBuilder.setAutoCancel(true);
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
             notificationManager.createNotificationChannel(new NotificationChannel("123", "123", NotificationManager.IMPORTANCE_HIGH));
             notificationBuilder.setChannelId("123");
         }
         Notification incomingCallNotification = notificationBuilder.build();
         return incomingCallNotification;
     }
    
  3. 在onStartCommand中,添加一行代码发送ACTION_CLOSE_SYSTEM_DIALOGS广播动作。这验证了启动全屏挂起意图的重要信息。

     public int onStartCommand(Intent intent, int flags, int startId) {
         Notification notification = buildNotification();
         startForeground(1, notification);
         sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
         return START_NOT_STICKY;
     }
    
  4. 创建要在锁定屏幕上显示的全屏 activity 然后您需要添加 setShowWhenLocked 和 setTurnScreenOn 以在锁定屏幕上显示。否则,您的 activity 将显示在锁定屏幕后面。下面是我的示例。

     public class IncomingCallActivity extends AppCompatActivity {
         protected void onCreate(@Nullable Bundle savedInstanceState) {
             super.onCreate(savedInstanceState);
             setContentView(R.layout.activity_explore);
             setShowWhenLocked(true);
             setTurnScreenOn(true);
             getWindow().addFlags(
             WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                     | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
                     | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
                     | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
                     | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON);
         }
     }
    
  5. 现在您必须在收到逻辑调用时启动 IncomingCallService。

     public void startCallService() {
         Intent intent = new Intent(context, IncomingCallService.class);
         startForegroundService(intent);
     }
    
  6. 您必须在清单中声明 activity、服务和一些权限,如下所示:

     <uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
     <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
     <application
        ...>
         <activity android:name=".IncomingCallActivity" />
         <service
             android:name=".IncomingCallService"
             android:enabled="true"
             android:exported="true" />
     </application>
    

我在 google、三星、vsmart phone 上测试过。它运作良好。但对于 xaomi 设备。您需要通过以下步骤启用一些权限:

  1. 长按你的应用程序图标
  2. 打开应用信息
  3. 点击“其他权限”项
  4. 允许在锁定屏幕上显示

现在您的应用程序可以在 xaomi 设备上运行了。如果您对我的解决方案有任何疑问,请在此处发表评论。如果可以我会帮你的。