各类学习资源参见:http://www.tuicool.com/articles/zaInUbA
要使java的接口能被javascript调用,主要有三个步骤:
步骤一:编写接口类,在类中编写对应的、供javascript调用的接口。
步骤二:编写接口对应的包类,在类中将步骤一编写的接口类添加到此包中。
步骤三:MainActivity类,在此类中,添加步骤二中编写的包类。
完成以上三步,javascript就能调用java的接口了。
一、接口类
假设编写一个名为ReadIDModule 的接口类,参考代码如下:
package com.nativetest;
import android.widget.Toast;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.Callback;
import com.facebook.react.uimanager.PixelUtil;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.bridge.Arguments;
import java.util.HashMap;
import java.util.Map;
public class ReadIDModule extends ReactContextBaseJavaModule {
<span style="white-space:pre"> </span>private static final String DURATION_SHORT_KEY = "SHORT";
<span style="white-space:pre"> </span>private static final String DURATION_LONG_KEY = "LONG";
<span style="white-space:pre"> </span>public ReadIDModule(ReactApplicationContext reactContext){
<span style="white-space:pre"> </span>super(reactContext);
}
@Override
public String getName() {
return "ReadIDModule";
}
<span style="white-space:pre"> </span>@Override
<span style="white-space:pre"> </span>public Map<String, Object> getConstants() {
<span style="white-space:pre"> </span>final Map<String, Object> constants = new HashMap<>();
<span style="white-space:pre"> </span>constants.put(DURATION_SHORT_KEY, Toast.LENGTH_SHORT);
<span style="white-space:pre"> </span>constants.put(DURATION_LONG_KEY, Toast.LENGTH_LONG);
<span style="white-space:pre"> </span>return constants;
<span style="white-space:pre"> </span>}
@ReactMethod
public void getIdCardInfo(Callback infoCallback) {
// 读二代证代码,此处省略
// 假设所读信息存放在自定义类IdCardInfo的对象idCardInfo中,并以Map传给javascript
WritableMap map = Arguments.createMap();
<span style="white-space:pre"> </span>map.putString("cardId", new String(perInfo.cardId).trim());
<span style="white-space:pre"> </span>map.putString("name", new String(perInfo.name).trim());
<span style="white-space:pre"> </span>map.putString("sex", new String(perInfo.sex).trim());
<span style="white-space:pre"> </span>map.putString("nation", new String(perInfo.nation).trim());
<span style="white-space:pre"> </span>map.putString("birthday", new String(perInfo.birthday).trim());
<span style="white-space:pre"> </span>map.putString("address", new String(perInfo.address).trim());
<span style="white-space:pre"> </span>map.putString("police", new String(perInfo.police).trim());
<span style="white-space:pre"> </span>map.putString("validStart", new String(perInfo.validStart).trim());
<span style="white-space:pre"> </span>map.putString("validEnd", new String(perInfo.validEnd).trim());
infoCallback.invoke(map);
}
@ReactMethod
public void showToast(String message, int duration){
Toast.makeText(getReactApplicationContext(), message, duration).show();
}
@ReactMethod
public void getCusName(Callback nickNameCallback){
nickNameCallback.invoke(new String(perInfo.name).trim);
}
}
说明:
此处主要介绍javascript如何给java参数,java如何返回信息给javascript。
1.@Override的getName()方法很重要,指明了javascript中此模块的名称。
2.@Override的getConstants()方法指明了javascript可用的在java中定义的常数,如没有可不重写此方法。
3.以@ReactMethod标明的方法就是提供给javascript的接口。
4.javascript向java的接口传递参数,可传递的类型及映射到javascript的类型如下:
java javascript
Boolean -> Bool
Integer -> Number
Double -> Number
Float -> Number
String -> String
Callback -> function
ReadableMap -> Object
ReadableArray-> Array
5.java返回数据给javascript没法直接用return的方式返回,需要调用回调函数,向回调函数传递参数的方式来实现。回调函数就是接口中Callback类型的入参。
一个接口可有多个回调函数,但一个回调函数只能传递一个参数,回调函数可传递的类型及映射到javascript的类型如下:
java javascript
Boolean -> Bool
Integer -> Number
Double -> Number
Float -> Number
String -> String
WritableMap -> Object
WritableArray-> Array
6.实例化一个WritableMap不是用new,而是用Arguments.createMap()。
WritableMap源码如下:
package com.facebook.react.bridge;
/**
* Interface for a mutable map. Used to pass arguments from Java to JS.
*/
public interface WritableMap extends ReadableMap {
void putNull(String key);
void putBoolean(String key, boolean value);
void putDouble(String key, double value);
void putInt(String key, int value);
void putString(String key, String value);
void putArray(String key, WritableArray value);
void putMap(String key, WritableMap value);
void merge(ReadableMap source);
}
ReadableMap则是getBoolean(String key)、getString(String key)等。
7.实例化一个WritebleArray也是一样,用Arguments.createArray)。
WritebleArray源码如下:
package com.facebook.react.bridge;
/**
* Interface for a mutable array. Used to pass arguments from Java to JS.
*/
public interface WritableArray extends ReadableArray {
void pushNull();
void pushBoolean(boolean value);
void pushDouble(double value);
void pushInt(int value);
void pushString(String value);
void pushArray(WritableArray array);
void pushMap(WritableMap map);
}
二、接口包类
假设编写一个名为ReadIDModule 的接口包类,参考代码如下:
package com.nativetest;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.uimanager.ViewManager;
import com.facebook.react.bridge.JavaScriptModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import java.util.ArrayList;
import java.util.List;
import java.util.Arrays;
import java.util.Collections;
public class ReadCardPackage implements ReactPackage {
/*
注册模块#
我们需要在你的应用的Package类的createNativeModules方法中添加这个模块。
如果一个模块没有被注册,它从JavaScript中也无法访问到。
*/
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();
<span style="color:#ff0000;"> </span><span style="background-color: rgb(204, 0, 0);">modules.add(new ReadIDModule(reactContext));</span>
return modules;
}
@Override
public List<Class<? extends JavaScriptModule>> createJSModules(){
return Collections.emptyList();
}
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext){
return Arrays.asList();
}
}
重点看红色字体部分,其余均无需改变。如有多个接口类都要归到这个包,只需往modules再add一个即可,add进去的为借口类的对象。
三、主程序MainActivity
package com.nativetest;
import com.facebook.react.ReactActivity;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
import com.facebook.react.shell.ReactMaterialKitPackage;
import java.util.Arrays;
import java.util.List;
public class MainActivity extends ReactActivity {
private LogcatUtil logcat;
private static AutofillSettings conf;
private static Context context;
/**
* Returns the name of the main component registered from JavaScript.
* This is used to schedule rendering of the component.
*/
@Override
protected String getMainComponentName() {
<span style="background-color: rgb(204, 0, 0);">return "NativeTest";</span>
}
/**
* Returns whether dev mode should be enabled.
* This enables e.g. the dev menu.
*/
@Override
protected boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
/**
* A list of packages used by the app. If the app uses additional views
* or modules besides the default ones, add more packages here.
*/
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
<span style="background-color: rgb(255, 0, 0);">new ReadCardPackage()</span>
);
}
}
红色字体部分为重点,return "NativeTest"表示主要组件的名称,通常是工程名。new ReadCardPackage()表示将此接口包添加到主要组件中,如有多个接口包,可再此添加接口包。
如图,MainActivity可添加多个包类,每个包类又可添加多个接口类。有助于代码的分类管理。