如何重构要从ReactNative调用的原生AndroidJava方法?

我目前有以下活动,它是在我的应用程序启动时创建的,并在我的 AndroidManifest.xml 中声明为活动:

AndroidManifest.xml:

<activity android:name=".IncomingActivity"></activity>

传入Activity.java:

package com.xyz;

import android.os.Build;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.WindowManager;

public class IncomingActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
            setShowWhenLocked(true);
            setTurnScreenOn(true);
        }
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
                | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);

        setContentView(R.layout.activity_incoming);
    }
}

我现在希望能够从 React Native 按需使用此功能。到目前为止,我已经像下面这样重构了它,但是当调用这个本机方法时,我只是得到一个空白的白屏,我认为问题出在这一行:activity.setContentView(mReactRootView);

更新类:

public class UnlockDevice extends ReactContextBaseJavaModule {

    @Override
    public String getName() {
        return "UnlockDevice";
    }

        private ReactContext mReactContext;
        private ReactRootView mReactRootView;

    public UnlockDevice(ReactApplicationContext reactContext) {
        super(reactContext);
                mReactContext = reactContext;
                mReactRootView = new ReactRootView(reactContext);
    }

    /* React Methods */
   @ReactMethod
    public void Unlock() {
                    Activity activity = mReactContext.getCurrentActivity();

                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
                    activity.setShowWhenLocked(true);
                    activity.setTurnScreenOn(true);
                }
                
                activity.getWindow().addFlags(
                        WindowManager.LayoutParams.FLAG_FULLSCREEN 
                        | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
                        | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON 
                        | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                        | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);

                activity.setContentView(mReactRootView);
    }
}

能够调用此方法来切换功能但使用主要活动而不是启动新活动的正确方法是什么?

回答

解释

基本上,你错过了两件事——你没有UnlockDevice在 a 中注册你的ReactPackage,并且你没有将你ReactPackage的添加到应用程序的包列表中。

另外,不要忘记您的本机方法不会在带有React的 UI 线程上执行。因此,您有责任在那里运行它。例如,通过使用runOnUiThread()如下:

...
    @ReactMethod
    public void Unlock() {
        Activity activity = mReactContext.getCurrentActivity();

        activity.runOnUiThread(() -> {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
                activity.setShowWhenLocked(true);
                activity.setTurnScreenOn(true);
            }

            activity.getWindow().addFlags(
                WindowManager.LayoutParams.FLAG_FULLSCREEN
                        | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
                        | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
                        | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                        | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
            activity.setContentView(mReactRootView);
        });
   }
...

因此,首先创建一个ReactPackage类来注册您的模块。

MainReactPackage.java

public class MainReactPackage implements ReactPackage {
   @Override
   @NonNull
   public List<ViewManager> createViewManagers(@NonNull ReactApplicationContext reactContext) {
       return Collections.emptyList();
   }

   @Override
   @NonNull
   public List<NativeModule> createNativeModules(
           @NonNull ReactApplicationContext reactContext) {
       List<NativeModule> modules = new ArrayList<>();

       modules.add(new UnlockDevice(reactContext));

       return modules;
   }
}

然后,将后者添加到Application类中的包列表中。

你的应用程序

 ...

 private final ReactNativeHost mReactNativeHost =
      new ReactNativeHost(this) {
        @Override
        public boolean getUseDeveloperSupport() {
          return BuildConfig.DEBUG;
        }

        @Override
        protected List<ReactPackage> getPackages() {
          @SuppressWarnings("UnnecessaryLocalVariable")
          List<ReactPackage> packages = new PackageList(this).getPackages();
          packages.add(new MainReactPackage());
          return packages;
        }

        @Override
        protected String getJSMainModuleName() {
          return "index";
        }
      };

  @Override
  public ReactNativeHost getReactNativeHost() {
    return mReactNativeHost;
  }
...

完整代码

作为参考,我创建了一个与您类似的示例项目,效果很好。下面是相关代码。

主活动.java

package com.reacttest;

import android.os.Bundle;

import com.facebook.react.ReactActivity;

public class MainActivity extends ReactActivity {

    /**
     * Returns the name of the main component registered from JavaScript. This is used to schedule
     * rendering of the component.
     */
    @Override
    protected String getMainComponentName() {
        return "ReactTest";
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);
    }
}

主活动模块

package com.reacttest;

import android.app.Activity;
import android.os.Build;
import android.view.WindowManager;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;

import com.facebook.react.ReactRootView;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;

public class MainActivityModule extends ReactContextBaseJavaModule {

    private ReactContext mReactContext;
    private ReactRootView mReactRootView;

    public MainActivityModule(ReactApplicationContext reactContext) {
        super(reactContext);
        mReactContext = reactContext;
        mReactRootView = new ReactRootView(reactContext);
    }

    @ReactMethod
    public void helloFromAndroid() {
        Activity activity = mReactContext.getCurrentActivity();
        activity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
                    activity.setShowWhenLocked(true);
                    activity.setTurnScreenOn(true);
                }

                activity.getWindow().addFlags(
                        WindowManager.LayoutParams.FLAG_FULLSCREEN
                                | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
                                | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
                                | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                                | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
                activity.setContentView(mReactRootView);
                Toast.makeText(activity, "Hello from Android", Toast.LENGTH_LONG).show();
            }
        });
    }

    @NonNull
    @Override
    public String getName() {
        return "MainActivityModule";
    }
}

主活动包.java

package com.reacttest;

import androidx.annotation.NonNull;

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;


public class MainReactPackage implements ReactPackage {
    @Override
    @NonNull
    public List<ViewManager> createViewManagers(@NonNull ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }

    @Override
    @NonNull
    public List<NativeModule> createNativeModules(
            @NonNull ReactApplicationContext reactContext) {
        List<NativeModule> modules = new ArrayList<>();

        modules.add(new MainActivityModule(reactContext));

        return modules;
    }
}

主应用程序

package com.reacttest;

import android.app.Application;
import android.content.Context;

import com.facebook.react.PackageList;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.soloader.SoLoader;

import java.lang.reflect.InvocationTargetException;
import java.util.List;

public class MainApplication extends Application implements ReactApplication {

    private final ReactNativeHost mReactNativeHost =
            new ReactNativeHost(this) {
                @Override
                public boolean getUseDeveloperSupport() {
                    return BuildConfig.DEBUG;
                }

                @Override
                protected List<ReactPackage> getPackages() {
                    @SuppressWarnings("UnnecessaryLocalVariable")
                    List<ReactPackage> packages = new PackageList(this).getPackages();
                    packages.add(new MainReactPackage());
                    return packages;
                }

                @Override
                protected String getJSMainModuleName() {
                    return "index";
                }
            };

    @Override
    public ReactNativeHost getReactNativeHost() {
        return mReactNativeHost;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        SoLoader.init(this, /* native exopackage */ false);
        initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
    }

    /**
     * Loads Flipper in React Native templates. Call this in the onCreate method with something like
     * initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
     *
     * @param context
     * @param reactInstanceManager
     */
    private static void initializeFlipper(
            Context context, ReactInstanceManager reactInstanceManager) {
        if (BuildConfig.DEBUG) {
            try {
        /*
         We use reflection here to pick up the class that initializes Flipper,
        since Flipper library is not available in release mode
        */
                Class<?> aClass = Class.forName("com.reacttest.ReactNativeFlipper");
                aClass
                        .getMethod("initializeFlipper", Context.class, ReactInstanceManager.class)
                        .invoke(null, context, reactInstanceManager);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
    }
}

应用程序.js

import {NativeModules} from 'react-native';

var mainActivityModule = NativeModules.MainActivityModule;
mainActivityModule.unlockScreen();

结果

如您所见,显示了来自 的 Toast Activity。就是这样!


以上是如何重构要从ReactNative调用的原生AndroidJava方法?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>