[英]How to refactor native Android Java method to be called from React Native?
I currently have the following activity which is created when my app starts and is declared as an activity in my AndroidManifest.xml:我目前有以下活动,它是在我的应用程序启动时创建的,并在我的 AndroidManifest.xml 中声明为活动:
AndroidManifest.xml: AndroidManifest.xml:
<activity android:name=".IncomingActivity"></activity>
IncomingActivity.java:传入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);
}
}
I now want to be able to use this functionality on demand from React Native.我现在希望能够从 React Native 按需使用这个功能。 I have refactored it like the below so far but when this native method is called, I just get a blank white screen and I think the problem is this line: activity.setContentView(mReactRootView);
到目前为止,我已经像下面这样重构了它,但是当调用这个本机方法时,我只是得到一个空白的白屏,我认为问题出在这一行: activity.setContentView(mReactRootView);
Updated class:更新了 class:
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);
}
}
What is the correct way to be able to call this method to toggle the functionality but with the main activity instead of starting a new one?能够调用此方法来切换功能但使用主要活动而不是开始新活动的正确方法是什么?
Basically, you missed 2 things - you didn't register your UnlockDevice
in a ReactPackage
, and you didn't add your ReactPackage
to the list of packages in the application.基本上,您错过了两件事 - 您没有在UnlockDevice
中注册ReactPackage
,并且您没有将ReactPackage
添加到应用程序的包列表中。
Also, don't forget that your native method will not be executed on the UI thread with React .另外,不要忘记您的本地方法不会在带有React的 UI 线程上执行。 So, it's your responsibility to run it there.所以,在那里运行它是你的责任。 For example, by using runOnUiThread()
as below:例如,通过使用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);
});
}
...
So, first create a ReactPackage
class to register your module.所以,首先创建一个ReactPackage
class 来注册你的模块。
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;
}
}
Then, add the latter to the list of packages in your Application
class.然后,将后者添加到Application
class 中的包列表中。
...
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;
}
...
For a reference, I created a sample project similar to yours that works just fine.作为参考,我创建了一个与您的类似的示例项目,它工作得很好。 Below is relevant code.下面是相关代码。
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";
}
}
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();
}
}
}
}
import {NativeModules} from 'react-native';
var mainActivityModule = NativeModules.MainActivityModule;
mainActivityModule.unlockScreen();
As you can see, the Toast from the Activity
is shown.如您所见,显示了来自Activity
的 Toast。 That's it!而已!
Have you already registered your Native module with your React Native?你已经用你的 React Native 注册了你的 Native 模块了吗? Reference: https://reactnative.dev/docs/native-modules-android#register-the-module-android-specific参考: https://reactnative.dev/docs/native-modules-android#register-the-module-android-specific
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.