react-native : navigate/load url via WebView
No Image, No Truth
use WebView component in reactnative.
var { ...., WebView, } = React;
initial state give a default url
getInitialState: function() { return { url: '', // or default url }; },
render with state url
<WebView ....your styles, properties url={this.state.url} />
Navigate/load codes
load() { this.setState({url:'http://google.com'}); }
Full Sample Codes
import React, { Component } from 'react';
import {
Button,
Modal,
Image,
Keyboard,
NativeModules,
Platform,
StyleSheet,
Text,
TextInput,
TouchableOpacity,
View,
WebView,
} from 'react-native';
const { WeChat } = NativeModules;
const SHARE_TO_WXTIMELINE = 0;
const SHARE_TO_WXSESSION = 1;
const webview = "webview";
const HOME_URL = "https://errong.win";
export default class App extends Component<{}> {
componentWillMount () {
this.keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', () => {this.keyboardDidHide()});
}
componentWillUnmount () {
this.keyboardDidHideListener.remove();
}
keyboardDidHide () {
console.log( this.urlText );
if (this.urlText != null) {
this.setState({url:this.urlText});
}
}
constructor(props) {
super(props);
this.state = {shareModalVisible : false, url : HOME_URL, urlBarVisible : true};
}
setShareModalVisible(visible) {
this.setState({shareModalVisible : visible});
}
onShare(scene) {
this.setShareModalVisible(false);
this.scene = scene;
if (this.shareMsg == null)
return;
if (WeChat.shareToTimeline)
WeChat.shareToTimeline(this.shareMsg, this.scene, null);
}
onWebViewMessage(event) {
console.warn(event.nativeEvent.data);
let msg;
try {
msg = JSON.parse(event.nativeEvent.data);
} catch (err) {
console.warn(err);
return;
}
if (msg.id == "ABSTRACT_FETCHED")
this.shareMsg = msg;
}
genAbstractJS() {
const genAbstractFunction = function() {
try {
let title;
let description;
let imageUrl;
let msg;
let n = document.querySelector('head title');
if (n)
title = n.innerText;
n = document.querySelector('p');
if (n)
description = n.innerText;
n = document.querySelector('p img');
if (n)
imageUrl = n.src;
if (description && imageUrl) {
msg = { 'id' : 'ABSTRACT_FETCHED',
'type' : 'textimage',
'description' : description,
'imageUrl': imageUrl
};
} else {
msg = { 'id' : 'ABSTRACT_FETCHED',
'type' : 'news',
'webpageUrl' : window.location.href
};
}
window.postMessage(JSON.stringify(msg), "*");
} catch (err) {
console.warn(err);
}
}
let js = "(" + String(genAbstractFunction) + ")();";
console.log(js);
return js;
}
onLoadEnd() {
this.refs[webview].injectJavaScript(this.genAbstractJS());
}
onUrlBar() {
}
renderUrlBar() {
if (this.state.urlBarVisible) {
return (
<TouchableOpacity style={styles.urlbar} onPress={() => {this.onUrlBar()}}>
<TextInput
style={styles.urlentry}
placeholder="search or input url"
onChangeText={(text) => {this.urlText = text}}
/>
)
} else {
return null;
}
}
render() {
return (
{this.renderUrlBar()}
<WebView
ref={webview}
style={{flex:1}}
javaScriptEnabled={true}
onMessage={(event) => {this.onWebViewMessage(event)}}
onLoadEnd={this.onLoadEnd.bind(this)}
source={{uri:this.state.url}}
/>
<Button
onPress={() => {this.setShareModalVisible(true)}}
title="Share"
color="#841584"
accessibilityLabel="Social Share"
/>
<TouchableOpacity style={styles.sharebutton} onPress={() => {this.onShare(SHARE_TO_WXTIMELINE)}}>
<Image
source={require('./res/img/wxtimeline.png')}
/>
<TouchableOpacity style={styles.sharebutton} onPress={() => {this.onShare(SHARE_TO_WXSESSION)}}>
<Image
source={require("./res/img/wxsession.png")}
/>
);
}
}
const styles = StyleSheet.create({
urlbar:{
backgroundColor:'#fafad2',
borderTopLeftRadius:4,
borderTopRightRadius:4,
borderBottomLeftRadius:4,
borderBottomRightRadius:4,
boderColor : '#C0C0C0',
borderWidth: 1
},
urlentry:{
height: 40
},
sgc:{
height:100,
width:300,
borderTopLeftRadius:10,
borderTopRightRadius:10,
borderBottomLeftRadius:10,
borderBottomRightRadius:10,
alignSelf: 'center',
top:400,
backgroundColor:'#fafad2'
},
sharegroup: {
flex:1,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-around',
},
sharebutton: {
width:64,
height:64
}
})
react-native : Modal example, share to WeChat
Refer
https://facebook.github.io/react-native/docs/modal.html
No Image, No Truth
Full Codes
import React, { Component } from 'react'; import { Button, Modal, Image, Keyboard, NativeModules, Platform, StyleSheet, Text, TextInput, TouchableOpacity, View, WebView, } from 'react-native'; const { WeChat } = NativeModules; const SHARE_TO_WXTIMELINE = 0; const SHARE_TO_WXSESSION = 1; const webview = "webview"; const HOME_URL = "https://errong.win"; export default class App extends Component<{}> { componentWillMount () { this.keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', () => {this.keyboardDidHide()}); } componentWillUnmount () { this.keyboardDidHideListener.remove(); } keyboardDidHide () { console.log( this.urlText ); if (this.urlText != null) { this.setState({url:this.urlText}); } } constructor(props) { super(props); this.state = {shareModalVisible : false, url : HOME_URL, urlBarVisible : true}; } setShareModalVisible(visible) { this.setState({shareModalVisible : visible}); } onShare(scene) { this.setShareModalVisible(false); this.scene = scene; if (this.shareMsg == null) return; if (WeChat.shareToTimeline) WeChat.shareToTimeline(this.shareMsg, this.scene, null); } onWebViewMessage(event) { console.warn(event.nativeEvent.data); let msg; try { msg = JSON.parse(event.nativeEvent.data); } catch (err) { console.warn(err); return; } if (msg.id == "ABSTRACT_FETCHED") this.shareMsg = msg; } genAbstractJS() { const genAbstractFunction = function() { try { let title; let description; let imageUrl; let msg; let n = document.querySelector('head title'); if (n) title = n.innerText; n = document.querySelector('p'); if (n) description = n.innerText; n = document.querySelector('p img'); if (n) imageUrl = n.src; if (description && imageUrl) { msg = { 'id' : 'ABSTRACT_FETCHED', 'type' : 'textimage', 'description' : description, 'imageUrl': imageUrl }; } else { msg = { 'id' : 'ABSTRACT_FETCHED', 'type' : 'news', 'webpageUrl' : window.location.href }; } window.postMessage(JSON.stringify(msg), "*"); } catch (err) { console.warn(err); } } let js = "(" + String(genAbstractFunction) + ")();"; console.log(js); return js; } onLoadEnd() { this.refs[webview].injectJavaScript(this.genAbstractJS()); } onUrlBar() { } renderUrlBar() { if (this.state.urlBarVisible) { return ( <TouchableOpacity style={styles.urlbar} onPress={() => {this.onUrlBar()}}> <TextInput style={styles.urlentry} placeholder="search or input url" onChangeText={(text) => {this.urlText = text}} /> </TouchableOpacity> ) } else { return null; } } render() { return ( <View style={{flex:1}}> {this.renderUrlBar()} <WebView ref={webview} style={{flex:1}} javaScriptEnabled={true} onMessage={(event) => {this.onWebViewMessage(event)}} onLoadEnd={this.onLoadEnd.bind(this)} source={{uri:this.state.url}} /> <Button onPress={() => {this.setShareModalVisible(true)}} title="Share" color="#841584" accessibilityLabel="Social Share" /> <Modal transparent={true} visible={this.state.shareModalVisible} > <View style={styles.sgc}> <View style={styles.sharegroup}> <TouchableOpacity style={styles.sharebutton} onPress={() => {this.onShare(SHARE_TO_WXTIMELINE)}}> <Image source={require('./res/img/wxtimeline.png')} /> </TouchableOpacity> <TouchableOpacity style={styles.sharebutton} onPress={() => {this.onShare(SHARE_TO_WXSESSION)}}> <Image source={require("./res/img/wxsession.png")} /> </TouchableOpacity> </View> </View> </Modal> </View> ); } } const styles = StyleSheet.create({ urlbar:{ backgroundColor:'#fafad2', borderTopLeftRadius:4, borderTopRightRadius:4, borderBottomLeftRadius:4, borderBottomRightRadius:4, boderColor : '#C0C0C0', borderWidth: 1 }, urlentry:{ height: 40 }, sgc:{ height:100, width:300, borderTopLeftRadius:10, borderTopRightRadius:10, borderBottomLeftRadius:10, borderBottomRightRadius:10, alignSelf: 'center', top:400, backgroundColor:'#fafad2' }, sharegroup: { flex:1, flexDirection: 'row', alignItems: 'center', justifyContent: 'space-around', }, sharebutton: { width:64, height:64 } })
react-native : How to create Image Button
Solution
Use TouchableOpacity, Image and Styles.Key codes
import React, { Component } from 'react'; import { Image, StyleSheet, TouchableOpacity, } from 'react-native'; <TouchableOpacity style={styles.sharebutton} onPress={() => {this.onShare(SHARE_TO_WXTIMELINE)}} > <Image source={require('./res/img/wxtimeline.png')} /> </TouchableOpacity>
No Image, No Truth
See Full sample codes Share to WeXin via Modal
react-natvie run-android --variant=release uncompiled PNG file passed as argument. Must be compiled first into .flat file..
C:\Users\lenger\Desktop\webrowser\android\app\build\intermediates\res\merged\release\drawable-mdpi\res_icon64_appwx_logo
.png: error: uncompiled PNG file passed as argument. Must be compiled first into .flat file..
error: failed parsing overlays.
Task :app:processReleaseResources
Failed to execute aapt
com.android.ide.common.process.ProcessException: Failed to execute aapt
workaround
android\gradle.properties
android.enableAapt2=false
refer
https://github.com/react-navigation/react-navigation/issues/3097
wechat share for react native app on android platform
Register App on weixin open platform
Register your on https://open.weixin.qq.com
While registering your app, you will need app sign signature,
you can refer sign your app for weixin.
You will get your APPID
after your app registered.
please keep it.
prepare wechat sdk for you app
add wechat sdk in android/app/build.gradle
dependencies { compile 'com.tencent.mm.opensdk:wechat-sdk-android-with-mta:+' }
set up AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <uses-permission android:name="android.permission.READ_PHONE_STATE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
build native wechat to react native JS
I export wechat as "NativeModules.WeChat" follow below examples
https://facebook.github.io/react-native/docs/native-modules-android.html
The main java codes:
- WeChatModule, extends ReactContextBaseJavaModule, implements IWXAPIEventHandler
- WeChatPackage, new WeChatModule as NativeModules
- MainApplication::getPackages(), new WeChatPackage
Important:
To expose a method to JavaScript a Java method must be annotated using @ReactMethod. The return type of bridge methods is always void. React Native bridge is asynchronous, so the only way to pass a result to JavaScript is by using callbacks or emitting events (see below).
public class WeChatModule extends ReactContextBaseJavaModule implements IWXAPIEventHandler { // ReactContextBaseJavaModule implementation @Override public String getName() { return "RCTWeChat"; } // IWXAPIEventHandler implementation @Override public void onReq(BaseReq baseReq) { } @Override public void onResp(BaseResp baseResp) { } @ReactMethod public void shareToTimeline(ReadableMap data, Callback callback) { } } public class WeChatPackage implements ReactPackage { @Override public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) { return Collections.emptyList(); } @Override public List<NativeModule> createNativeModules( ReactApplicationContext reactContext) { List<NativeModule> modules = new ArrayList<>(); modules.add(new WeChatModule(reactContext)); return modules; } } 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() { return Arrays.<ReactPackage>asList( new MainReactPackage(), new WeChatPackage() ); }
Use in react native JS
import { NativeModules, } from 'react-native'; const { WeChat } = NativeModules;
You can get all codes by downloading my example app wechat-share-example.
It is a zip file, after you download it, Remember:
1. replace app id in .\android\app\src\main\java\com\wx\react\WeChatModule.java 2. replace package name to your package name. 3. run npm install before react-native run-android
The package name in the example is "com.errong.webrowser".
./android/app/BUCK:48: package = "com.errong.webrowser",
./android/app/BUCK:53: package = "com.errong.webrowser",
./android/app/build.gradle:100: applicationId "com.errong.webrowser"
./android/app/src/main/AndroidManifest.xml:2: package="com.errong.webrowser"
./android/app/src/main/java/com/webrowser/MainActivity.java:1:package com.errong.webrowser;
./android/app/src/main/java/com/webrowser/MainApplication.java:1:package com.errong.webrowser;
app id and package name should exactly same to the one you applied at
open.weixin.com which was mentioned at the beginning of this post.
otherwist, share feature maynot work well.
register app id to wechat
.\android\app\src\main\java\com\wx\react\WeChatModule.java
public class WeChatModule extends ReactContextBaseJavaModule implements IWXAPIEventHandler { private IWXAPI api = null; public WeChatModule(ReactApplicationContext context) { super(context); String appId = "YOURAPPID"; api = WXAPIFactory.createWXAPI(this.getReactApplicationContext().getBaseContext(), appId, true); if (api != null) api.registerApp(appId); }
Share to wechat time line
.\android\app\src\main\java\com\wx\react\WeChatModule.java
@ReactMethod public void shareToTimeline(ReadableMap data, Callback callback) { if (api == null) { Toast.makeText(getReactApplicationContext(), "App not registered to WeChat", Toast.LENGTH_SHORT).show(); return; } WXMediaMessage.IMediaObject mediaObject = _jsonToTextMedia(data); WXMediaMessage message = new WXMediaMessage(); message.mediaObject = mediaObject; if (data.hasKey("title")) message.title = data.getString("title"); if (data.hasKey("description")) message.description = data.getString("description"); SendMessageToWX.Req req = new SendMessageToWX.Req(); req.message = message; req.scene = SendMessageToWX.Req.WXSceneTimeline; req.transaction = UUID.randomUUID().toString(); api.sendReq(req); }
App.js
import { NativeModules, } from 'react-native'; const { WeChat } = NativeModules; var msg = {'id' : 'ABSTRACT_FETCHED', 'url' : window.location.href, 'title' : title, 'description' : desc, 'imgurl' : imgurl}; WeChat.shareToTimeline(msg, null);
Key points
- APPID and package name should same to the one you applied at open.weixin.qq.com
sign your app for weixin - sign your apk with your keystore file before you release.
Generate Signed android APK for react-native app - all sample codes download here
react-native : Native Modules, name prefix "RCT"works for android too
I copied some codes here:
public class WeChatModule extends ReactContextBaseJavaModule implements IWXAPIEventHandler {
private String appId;
public WeChatModule(ReactApplicationContext context) {
super(context);
}
@Override public String getName() {
return "RCTWeChat";
}
}
I used "RCTWeChat" as the module name, I did not know the "RCT" prefix meanings.ReactContextBaseJavaModule requires that a method called getName is implemented. The purpose of this method is to return the string name of the NativeModule which represents this class in JavaScript.
Then I encountered error in my react-native JS codes.
import {NativeModules} from 'react-native'; const { RCTWeChat } = NativeModules;
WeChat or NativeModules.RCTWeChat always undefined.
Cause
RCT is a prefix used in react native, it will be removed when exported to JS.React Native uses RCT as a prefix. In order to avoid name collisions, we recommend using a three-letter prefix other than RCT in your own classes.
Solution
The correct JS codes:const { WeChat } = NativeModules;
fixed: embedded-redis: Unable to run on macOS Sonoma
Issue you might see below error while trying to run embedded-redis for your testing on your macOS after you upgrade to Sonoma. java.la...
-
Refer: https://github.com/bazelbuild/bazel/wiki/Building-with-a-custom-toolchain https://www.tensorflow.org/tutorials/image_recognition
-
F:\webrowser>react-native run-android Scanning folders for symlinks in F:\webrowser\node_modules (73ms) Starting JS server... Buildin...
-
Solution react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android...