我目前有以下 Activity ,该 Activity 在我的应用启动时创建并在我的 AndroidManifest.xml 中声明为 Activity :
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 按需使用这个功能。到目前为止,我已经像下面这样重构了它,但是当调用这个 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);
}
}
能够调用此方法来切换功能但使用主要 Activity 而不是开始新 Activity 的正确方法是什么?
最佳答案
解释
基本上,你错过了两件事 - 你没有注册你的 UnlockDevice
在 ReactPackage
,而您没有添加 ReactPackage
到应用程序中的包列表。
另外,不要忘记您的 native 方法不会在 UI 线程上执行 。 react .所以,在那里运行它是你的责任。例如,使用 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
中的软件包列表中。类(class)。你的应用程序.java
...
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;
}
...
完整代码作为引用,我创建了一个与您的类似的示例项目,它工作得很好。下面是相关代码。
MainActivity.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);
}
}
主 Activity 模块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";
}
}
MainActivityPackage.javapackage 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;
}
}
MainApplication.javapackage 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();
}
}
}
}
应用程序.jsimport {NativeModules} from 'react-native';
var mainActivityModule = NativeModules.MainActivityModule;
mainActivityModule.unlockScreen();
结果如您所见,来自
Activity
的 Toast显示。而已!
关于java - 如何重构要从 React Native 调用的原生 Android Java 方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66662941/