【问题标题】:How to draw over other apps in React-native?如何在 React-native 中绘制其他应用程序?
【发布时间】:2019-03-03 16:11:40
【问题描述】:

我的应用中需要类似于 Facebook Messenger 的聊天头,基本上是一个可以在其他应用上查看的气泡。除了this 问题,我在网上找不到任何关于此主题的内容。那么有没有办法用 RN 做这样的事情呢?

【问题讨论】:

  • 它不是 RN 的内置功能。您将需要一个 Android 级别的服务来完成 ReactActivity 的所有工作,但要移植到服务中。你需要让它设置你的反应视图。你需要让它设置一个系统覆盖。然后你可以让那个反应视图显示一个 ReactNative 应用程序——但它不会和你的代码的其余部分是同一个应用程序,或者它会显示相同的东西。我无法让这 2 个 RN 应用程序相互通信。
  • 真的,如果你想做嵌入在平台工作方式中的东西,RN 是错误的选择。如果您需要热下载代码,或者您的开发人员具有丰富的 React 经验、没有移动经验且应用程序简单,RN 才是真正正确的选择。

标签: javascript android reactjs react-native


【解决方案1】:

react native 不直接支持此功能,而且 ios 也不支持此功能,因此只有您可以在 android 中使用 java 本机代码来实现它。为此,您应该在 android 中编写一个处理此元素生命周期的服务。 您可以在 android 项目中找到 here 的简单实现。这是一个非常简单的示例,您可以将它的服务用于您的 react native 项目,只需更改它的 xml 文件即可自定义您的视图。 为了启动您的服务,您必须编写一个非常简单的 React Native 模块,如下所示

@ReactMethod
public void startService(Promise promise) {

    String result = "Success";
    Activity activity = getCurrentActivity();
    if (activity != null) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(getReactApplicationContext())) {
            Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                    Uri.parse("package:" + getCurrentActivity().getPackageName()));
            getCurrentActivity().startActivityForResult(intent, MainActivity.DRAW_OVER_OTHER_APP_PERMISSION_REQUEST_CODE);
        }
    }
    try {
        Intent intent = new Intent(FloatingWidgetService.FLOATING_WIDGET_ID);
        intent.setClass(this.getReactApplicationContext(), FloatingWidgetService.class);
        getReactApplicationContext().startService(intent);
        FloatingWidgetService.setUri(uri);
    } catch (Exception e) {
        promise.reject(e);
        return;
    }
    promise.resolve(result);
}

在 Android-8Oreo 中,您必须请求 canDrawOverlays,您可以在 MainActivity 中等待结果,如下所示:

private static final int DRAW_OVER_OTHER_APP_PERMISSION_REQUEST_CODE = 1222;
....
private void startFloatingWidgetService() {
    if (!mStarted) {
        Intent intent = new Intent(this, FloatingWidgetService.class);
        ContextCompat.startForegroundService(this, intent);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            this.startForegroundService(intent);
        }else{
            startService(intent);
        }
        mStarted = true;
        finish();
    }
}
....
 @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == DRAW_OVER_OTHER_APP_PERMISSION_REQUEST_CODE) {
            //Check if the permission is granted or not.
            if (resultCode == RESULT_OK)
                //If permission granted start floating widget service
                startFloatingWidgetService();
            else
                //Permission is not available then display toast
                Toast.makeText(this,
                        getResources().getString(R.string.draw_other_app_permission_denied),
                        Toast.LENGTH_SHORT).show();

        } else {
            super.onActivityResult(requestCode, resultCode, data);
        }
    }

然后,要从具有相同 appstate 的服务再次返回您的应用(不是创建新活动),首先将您的活动启动模式定义为清单中的单个实例:

<activity
        ...
        android:launchMode="singleInstance"
        ...
        >

并在您的服务中使用这种意图(!):

ReactApplicationContext reactContext = VideoViewModule.getReactContext();
Intent activityIntent = createSingleInstanceIntent();
reactContext.startActivity(activityIntent);



 private Intent createSingleInstanceIntent() {
        ReactApplicationContext reactContext = VideoViewModule.getReactContext();
        String packageName = reactContext.getPackageName();
        Intent launchIntent = reactContext.getPackageManager().getLaunchIntentForPackage(packageName);
        String className = launchIntent.getComponent().getClassName();
        Intent activityIntent = null;
        try {

            Class<?> activityClass = Class.forName(className);

            activityIntent = new Intent(reactContext, activityClass);

            activityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        } catch (Exception e) {
            stopCurrentService();
            Log.e("POIFOIWEGBF", "Class not found", e);

        }
        return activityIntent;
    }

希望对你有帮助。

【讨论】:

  • 能给个链接教程吗?对于 React Native。
  • 对不起@zidniryi 去年当我搜索这个时,在 react native 中找不到任何东西,所以我已经将 android guides 实现为 react native。但现在如果有任何我知道的问题或分享任何相关的源代码,我很乐意为您提供帮助
  • 对不起,这是我可以分享的代码的肮脏实现,它必须工作,但如果有问题请告诉我link
猜你喜欢
  • 1970-01-01
  • 2018-01-26
  • 1970-01-01
  • 2020-09-26
  • 1970-01-01
  • 2022-08-03
  • 1970-01-01
  • 2023-02-23
  • 1970-01-01
相关资源
最近更新 更多