上次的Xposed插件少个可视化界面,如果直接使用Android开发也不是不行,但是那样太无聊了,正好试试一直想使用的React Native技术来开发一个简单的界面。
开发工具同样是简单的Android Studio,按照RN中文网上的开发步骤先搭建一个Hello World,基于这个demo先做一个不读取数据的展示页面,顺便学习一下导航栏的使用。
RN 与原生的数据交互是通过NativeModules这个对象进行异步操作的,可以通过async和await使操作更简单,并封装一个调用原生的方法
1 2 3 4 5 import  { NativeModules } from  'react-native' ;export  async  function  JsDBHelperCall (func, ...args )   return  await  NativeModules.JsDBHelper[func](...args); } 
简单的应用里也无需使用redux来管理数据,直接使用Props传递即可,其他的代码基本和写React一样,然后运行起来并写好java端的代码,实现数据流通便算完成。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 public  class  JsDBHelper  extends  ReactContextBaseJavaModule      private  DBHelper db = null ;     private  SportEditorDao sportEditorDao = null ;     public  JsDBHelper (ReactApplicationContext reactContext)           super (reactContext);         db = new  DBHelper(reactContext);         sportEditorDao = new  SportEditorDao(reactContext);     }     @Override      public  String getName ()           return  this .getClass().getSimpleName();     }     @ReactMethod      public  void  ExecSQL (String sql, ReadableArray selectionArgs)           try  {             JSONArray args = ArrayUtil.toJSONArray(selectionArgs);             db.ExecSQL(sql, args.toJavaList(String.class));         } catch  (JSONException e) {             e.printStackTrace();         }     }     @ReactMethod      public  void  QueryForMap (String sql, ReadableArray selectionArgs)           try  {             JSONArray args = ArrayUtil.toJSONArray(selectionArgs);             Map<String, String> result = db.QueryForMap(sql, args.toJavaList(String.class));         } catch  (JSONException e) {             e.printStackTrace();         }     }     @ReactMethod      public  void  QueryForListMap (String sql, ReadableArray selectionArgs, Promise promise)           ...     }     @ReactMethod      public  void  GetConfigByPackageName (String packageName, Promise promise)           ...     }     @ReactMethod      public  void  GetConfigs (Promise promise)           ...     }     @ReactMethod      public  void  SaveConfig (ReadableMap selectionArgs, Promise promise)           ...     } } 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 export  default  class  HomeScreen  extends  React .PureComponent    constructor (props )     super (props);     this .state = {       configs : Immutable.fromJS([]),       refreshing : false ,       isLoading : true ,     };     this .onRefresh = this .onRefresh.bind(this );     this .rowClick = this .rowClick.bind(this );   }   async  componentDidMount (     let  configs = await  JsDBHelperCall('GetConfigs' );     this .setState({       isLoading : false ,       configs : Immutable.fromJS(configs),     });     console .log(configs);   }   async  onRefresh (     this .setState({       refreshing : true ,     });     let  configs = await  JsDBHelperCall('GetConfigs' );     this .setState({       refreshing : false ,       configs : Immutable.fromJS(configs),     });     console .log(configs);   }   rowClick (config, index )     this .props.navigation.navigate('Detail' , {       config : config,       callBack : this .onRefresh,     });   }   render (     const  emptyText = this .state.isLoading ? 'Loading...'  : this .state.errorMsg ? 'Error!'  : 'No data.' ;     return  (       <View >          <ImmutableVirtualizedList             immutableData ={this.state.configs}            keyExtractor ={(item,  index ) =>  item.get('packageName')}          ListHeaderComponent={() => <AppRowHeader  /> }           renderItem={({ item, index }) => <AppRow  config ={item}  rowClick ={this.rowClick}  index ={index}  /> }           onRefresh={this.onRefresh}           refreshing={this.state.refreshing}           renderEmptyInList={emptyText}         />       </View >      );   } } 
然后再将原来的Xposed APP代码原样移植到这边的java层,丢到手机运行,收工!
这个插件如果有需要也可以自由下载代码 编译,个人比较懒,也不想发布到Xposed市场里。