最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to draw over other apps in React-native? - Stack Overflow

programmeradmin0浏览0评论

I need to have something similar to Facebook Messenger's chat heads in my app, basically a bubble that can be viewed over other apps. I can't find anything online on this topic besides this question. So is there any way to make something like this with RN?

I need to have something similar to Facebook Messenger's chat heads in my app, basically a bubble that can be viewed over other apps. I can't find anything online on this topic besides this question. So is there any way to make something like this with RN?

Share Improve this question asked Sep 27, 2018 at 17:22 pdoopdoo 931 gold badge2 silver badges6 bronze badges 2
  • Its not a built in piece of functionality of RN. You're going to need an Android level Service that does all the work of ReactActivity, but ported to a Service. You'll need to make it set up your react view. You'll need to have it setup a system overlay. Then you can have that react view show a ReactNative app- but it won't be the same app as the rest of your code, or it would display the same thing. And how you'd have the 2 RN apps talk to each other is beyond me. – Gabe Sechan Commented Sep 27, 2018 at 17:30
  • Really if you want to do stuff that's this embedded in the way a platform works, RN is the wrong choice. RN is only really the right choice if you need to hot download code, or you have developers with significant react experience, no mobile experience, and a simple app. – Gabe Sechan Commented Sep 27, 2018 at 17:31
Add a comment  | 

1 Answer 1

Reset to default 16

this feature is not support directly from react native and also this is not supported in ios therefore only you could implement it with java native code in android. to do that you should write a service in android which handle this element life cycle. You could find here simple implementation of that in an android project. it's such a straightforward example and you can use it's service for your react native project and just change it's xml file to customize your view. And just to start your service you must write a very simple react native module look like this

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

in Android-8Oreo you must ask for canDrawOverlays and you can wait for result in your MainActivity like this:

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

And after that to come back again to your app from that service with the same appstate(not to create new activity) first define your activity launchmode as a singleInstance in manifest:

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

And use this kind of intent(!) in your service:

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

I hope it helps.

发布评论

评论列表(0)

  1. 暂无评论