java - 如何在 Android 10 中打开 Activity (传入 voip 调用)

标签 java android android-10.0

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

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

我绝对知道的是:

  • 我没有任何正在运行的 Activity 、任务、backstack 等
  • 该应用程序甚至没有运行

  • 我需要达到的目标:
  • 应用程序的 FCM 服务从我们的服务器接收推送,并应显示来电屏幕(锁定屏幕和所有 - 就像它在 android 9 及更低版本中所做的那样)

  • 我该怎么做才能在 android 10 中打开传入 voip 调用的 Activity ?
    就像普通用户对 PHONE 应用程序所期望的那样,在锁屏和所有内容中。

    提前感谢您的任何提示。

    最佳答案

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

  • 创建一个前台服务,然后在 onStartCommand 方法中调用 buildNotification,buildNotification 方法将返回一个通知放入 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;
         }
     }
    
  • 在 buildNotification 方法中,我们将创建具有高优先级、调用类别和全屏 Intent 的通知。
     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;
     }
    
  • 在 onStartCommand 中,添加一行代码发送 ACTION_CLOSE_SYSTEM_DIALOGS 广播 Action 。这验证重要的是启动全屏挂起 Intent 。
     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;
     }
    
  • 创建要在锁定屏幕上显示的全屏 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);
         }
     }
    
  • 现在,当您收到来自您的逻辑的调用时,您必须启动 IncomingCallService。
     public void startCallService() {
         Intent intent = new Intent(context, IncomingCallService.class);
         startForegroundService(intent);
     }
    
  • 您必须在 list 中声明 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>
    

  • 我在谷歌、三星、vsmart 手机上测试过。它运作良好。但是对于小米设备。您需要通过以下步骤启用一些权限:
  • 长按到你的应用图标
  • 打开应用信息
  • 点击“其他权限”项
  • 允许在锁定屏幕上显示

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

    关于java - 如何在 Android 10 中打开 Activity (传入 voip 调用),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58819246/

    相关文章:

    java - java 套接字中收到的延迟响应

    java - 将方法添加到 org.w3c.dom.Node

    Android 10 媒体播放器无法在状态 1 中调用错误停止,mNative : error (-38, 0)

    android - 我们如何在 Android Q 中访问扩展文件?

    android - 如何使用 "libsu"库(或 adb)在 Android Q 上安装拆分 APK 文件?

    java - 填充方法结果的全局数组

    java - 在使用 Web 服务的客户端应用程序中使用证书

    java - equalsIgnoreCase() 方法内有多个参数

    android - 编译 ARM64 android 内核时出错

    android - 选择构建类型时如何区分构建风格?