React Native Android - Static Resources not Showing - android

I'm just trying to load an image as a static resource. Here is an example that gives me a blank white screen.
/**
* Sample React Native App
* https://github.com/facebook/react-native
*/
'use strict';
var React = require('react-native');
var {
AppRegistry,
StyleSheet,
Text,
Image,
View
} = React;
var impowerz = React.createClass({
displayName : "Login",
render: function() {
return (
<View style={styles.container}>
<Image source={require('image!bg-splash')} style={styles.bg} />
</View>
);
}
});
var styles = StyleSheet.create({
bg : {
height: 667,
width: 375
},
container: {
flex: 1,
},
});
AppRegistry.registerComponent('impowerz', () => impowerz);
I checked in Chrome Debugger and this is what I got
[![Chrome Debugger sees my static resource][1]][1]
Edit I wrapped the image tag in a view and added a flex: 1 styles for the container
Update I tried to console.log() the assetsRoot property in react-native/packager/packager.js and it came back as /impowerz/assets/ which is where my image lives. I made a #2x and #3x as suggested [in this answer][2]
I tried using .jpg instead of .png images and tried replacing require('image!bg_splash') with {uri: 'assets/image/bg_splash.jpg'} (with and without the ext).

How did you add "bg-splash" to your android app? It should go under android/app/src/main/res/drawable (or drawable-hdpi, -xhdp etc if you have different version per DPI). Also take into account that android only accept resources names that contain lowercase letters and underscores, so your image name doesn't match that requirement as it contains dash sign.

in react-native v.0.14+
// same syntax for IOS and Android
require('./my-icon.png')
Full Image docs here
As of 0.14 release, React Native provides a unified way of managing images in your iOS and Android apps. To add a static image to your app, place it somewhere in your source code tree and reference it like this:
<Image source={require('./my-icon.png')} />
//relative path
.
├── button.js
└── img
├── check#2x.png
└── check#3x.png

I couldn't get my images to show up either.
When I went to <yourapp>/android/app/src/main/res, there were only mipmap-<qualifier> folders. I first put the images in those folders. Didn't work. My reading comprehension skills obviously need upgrading, because in the instructions, it clearly says "drawable." Then, I made the mistake of thinking that these "mipmap" folders needed to be changed to "drawable" folders (in the place of "mipmap"). So if anyone did that, backtrack, and instead, add the drawable-<qualifier> folders in addition to the "mipmap" ones. And then make sure to recompile the app.

To get the image to show on the screen, put the image in a view:
return (
<View
style={styles.container}>
<Image source={require('image!bg-splash')} style={styles.bg} />
</View>
);
And add these styles to the view
var styles = StyleSheet.create({
container: {
flex: 1,
},

Related

Link Within an App with the React Native Render Html

In my expo / react app I have some HTML from a website that I'm pulling from an api. I'd like to use links within that html to link to pages within the app. Some example html...
responseHtml = "<p>this is a paragraph Some Page<p>"
then I was thinking I would do some string replace so that the html ends up looking like this...
responseHtml = "<p>this is a paragraph Some Page<p>"
Then I would render the content in my app and the links would work if I did something like this...
<HTML onLinkPress={(event, href)=>{Linking.openURL(href)}} html="{responseHtml}" />
I cannot seem to find the right href value to make a successful click to a page within the app. I've tried using the full path, exp://127.0.0.1:19200/Article/some-page, I've tried relative links like /Article/some-page, and I've tried setting a schema value to "myapp" in the app.json and linking to it with myapp://Article/some-page
Have you tried to parse it ? I would use the react-native-htmlview library. There you can customize the Link handler. So you could open the link or pass it down as prop.
Your code could be look like this:
import React from 'react';
import HTMLView from 'react-native-htmlview';
class App extends React.Component {
render() {
const responseHTML = ``;
return (
<HTMLView
value={htmlContent}
stylesheet={{
fontWeight: '300',
color: '#FF3366', // make links coloured pink
}}
/>
);
}
}
If you want to do any custom actions with your link it could look like this:
return (
<HTMLView
value={this.props.putyourhtmlhere}
onLinkPress={(url) => console.log('clicked link: ', url)}
/>
);
Hope that helps

Set InAppBrowser or Themeable Browser height to show app's bottom tabs

I've searched about this around ionic forums, stackoverflow, etc., but I still haven't found an answer.
I'm creating an ionic 4 app with an inappbrowser inside and I want it to be like a part of the app with the bottom tabs showing.
Others suggested to use iframe but I'm not sure if that's good since they're also saying that it has issues uploading to the apple app store.
My folder structure:
Tabs Folder
Page 1 Folder (Where the inappbrowser is located)
Page 2 Folder (This page shows with the tabs and has no problem)
Here's the code in the page 1 folder:
this.platform.ready().then(() => {
const browser = this.iab.create(url, '_blank', {location:'no',
footer:'no', zoom:'no', usewkwebview:'yes', toolbar:'no'});
});
and Here's the routes of the tab folder:
const routes: Routes = [{
path: 'tabs',
component: TabsPage,
children: [
{
path: 'page1',
children: [
{
path: '',
loadChildren: '../page1/page1.module#page1Module'
}
]
}
I understand that inAppBrowser covers all the parts of the app and has the absolute position, so the solution I'm thinking is to just set a height for the inAppBrowser so that it will not cover the bottom tabs, but is that possible?
Update: I used React Native instead.
As React Native webview is not in a different layer, and can be inserted on any part of the app.

How to have display buckets like android in react native?

I am planning to build a react native app.The app gets targetted to 3 main things.
1ft => Mobiles(IOS,ANDROID),
2ft => Tablets,
10ft => Android TV.
How can we create files so that if I want to build for 1ft(Mobiles),the app should take only 1ft files like
eg; 1ft_android.js,1ft_ios.js
eg; 2ft_android.js ,2ft_ios.js
and in the same how can I build separately without using Platform.Select Or is there any chance to use flavours and is there any way to make this happen?
Edit 1: I have the folder structure as follows:
I want to find a way to let react know that if display metric matches
1ft, take landing.1ft.android.js. I don't want to compare display
metrics everytime. I'm looking for some configuration so react will
pick the respective file like it picks platform specific files.
For Platform specific UI you can Switch using Platform module.
import {Platform, StyleSheet} from 'react-native';
const styles = StyleSheet.create({
height: Platform.OS === 'ios' ? 200 : 100,
});
But if you want to create responsive UI which will adjust its shape
and size with respect to screen you can use the following methods:
Flex: https://facebook.github.io/react-native/docs/height-and-width#flex-dimensions
Screen ratio:
var deviceWidth: Dimensions.get('window').width;
...
myImage { width: deviceWidth, height: deviceWidth * 0.5 }
And for font-size you can use this function:
export const getAdjustedFontSize = (size) => {
return parseInt(size) * metrics.screenWidth * (1.8 - 0.002 * metrics.screenWidth) / 400;
};
Edit:
You can refer to this link also: https://medium.com/react-native-training/build-responsive-react-native-views-for-any-device-and-support-orientation-change-1c8beba5bc23

ReactNative - Webview not executing injectedJavaScript on Android

I'm having trouble getting the Webview on ReactNative to execute the injected JavaScript on a physical Android device. I've scoured the web as far as I could over the past 2 days and still haven't found a solution. Results for testing are as follows:
iOS simulator - All good
iPhone - All good
Android simulator - All good
Physical devices, Sony Xperia Z2, Sony Xperia Z5 Compact and LG G4 - NOTHING
My Webview is defined as follows:
<WebView
style={styles.webView}
source={{
html: html,
baseUrl: 'web/'
}}
injectedJavaScript={'render(' + JSON.stringify(this.state.data) + ');'}
javaScriptEnabledAndroid={true}
scrollEnabled={false}
bounces={false}
renderLoading={() => <LoadingIndicator />}
/>
I've tried specifying javaScriptEnabled as well, to no avail. I also tried smaller scripts to just colour elements on the page or post a message back to the app using window.postMessage, but nothing happens. I need to inject the data to the HTML, which will render graphs for me based on the supplied data. My last resort is to manually construct the HTML with the data appended as part of the markup being supplied to the Webview, but I'd really like to keep it simple and just get it to work the way it should.
I'm using the latest version of ReactNative (0.41) and the phones are running Android 6+.
I just discovered that the Android WebView appears to inject any JS as a single line, even if it includes line breaks. That means that missing semicolons can definitely cause issues, or, in my case, comments delimited by //. Using /* and */ for comments got my injected JavaScript working again.
Well, after leaving this question open for some time and finding a (not so elegant) solution to the problem, I decided I'd share what I ended up doing:
I declared the HTML to be passed to the WebView in a constant string along these lines: const html = '<html>...<script>...[INJECTEDSCRIPT]</script></html>';
I retrieved the data in the componentDidMount() event of the React component's lifecycle and set a state variable for it using this.setState({ data: retrievedData });
This, of course, forced the component to re-render itself, after which I now have the data available to "pass" to the WebView
Seeing as I couldn't find any elegant or usable way of using the injectedJavaScript property to work the way I want it to (as stated in the question), I resorted to replacing the [INJECTEDSCRIPT] value in the HTML constant with the serialized data.
Not the most elegant solution, I know, but it's the only one I could get working reliably across a multitude of devices and emulator configurations. Sample, edited for brevity, as below:
const html = `
<!DOCTYPE html>
<html>
<head>...</head>
<body>...</body>
<script>
var render = function (data) {
...
};
[INJECTEDSCRIPT]
</script>
</html>`;
export class GraphComponent extends Component {
constructor(props) {
super(props);
this.state = {};
}
componentDidMount = () => {
SERVICE.getData().done((data) => {
this.setState({ data: data });
});
}
render = () => {
if (!this.state.data)
return <LoadingIndicator />;
let serializedData = JSON.stringify(this.state.data);
return
<WebView
style={styles.webView}
source={{
html: html.replace('[INJECTEDSCRIPT]', 'render(' + serializedData + ');'),
baseUrl: 'web/'
}}
scrollEnabled={false}
bounces={false}
renderLoading={() => <LoadingIndicator />}
/>;
}
}
I have been struggling to get Javascript (pre-embed and injected) to be executed as well. So far, a simple and better solution is to use WebViewBridge. After, everything worked as expected. Here a link to the package: cnpmjs.org/package/react-native-webview-bridge.
Here a demo:
import React, {
Component
} from 'react';
import PropTypes from 'prop-types';
import {
Platform,
WebView,
ActivityIndicator,
} from 'react-native';
import WevViewBridge from 'react-native-webview-bridge';
// TODO: Keep in mind that you should ALWAYS edit
// two separate file and keep them matched.
const IOS_WEB_PAGE_SOURCE = './webPage/wordBody.html';
const ANDROID_WEB_PAGE_SOURCE = 'file:///android_asset/webPage/wordBody.html';
export default class WordBody extends Component {
static propTypes = {
data: PropTypes.object.isRequired,
}
_injectedScript = `
(function(){
let data = ${JSON.stringify(this.props.data)};
refresh(data);
})();
`;
render() {
/*
* We are using Platform.select here for two reasons:
* 0. Everythig work fine for IOS using `WebView` from RN
* 1. Android doesn't load web ressource with `require`
* 2. On Android, `WebView` from react-native doesn't
* execute JavaScript so we use `WebViewBridge`.
*/
return Platform.select({
ios: (<WebView
style = {{backgroundColor: 'rgba(0, 0, 0, 0)', flex:1,}}
scalesPageToFit
source = {require(IOS_WEB_PAGE_SOURCE)}
javaScriptEnabled={true}
originWhitelist={['*']}
injectedJavaScript = {this._injectedScript}
renderLoading={() => <ActivityIndicator/>}
/>),
android: (<WevViewBridge
style = {{backgroundColor: 'rgba(0, 0, 0, 0)', flex:1,}}
scalesPageToFit
source = {{uri:ANDROID_WEB_PAGE_SOURCE}}
javaScriptEnabled={true}
// originWhitelist={['*']}
injectedJavaScript = {this._injectedScript}
renderLoading={() => <ActivityIndicator/>}
/>)
});
};
}

Downloading data files with React Native for offline use

I am wanting to develop an app where a user can select different gamepacks to install on their android or ios device. A gamepack will consist of:
one or more JSON files
images
sounds
Right now I'm not really concerned if these are transferred individually or in a zip file (though a zip file would certainly be preferred). Of course the device will need to be connected to the Internet to get the current list of gamepacks and to download the ones that the user chooses. Once the gamepacks are downloaded to the phone the user will not need an Internet connection to play the game as they will have all the files.
How do I go about implementing this in my project?
How do I download the files? Would I use the react-native-fetch-blob library and save it in a specific location? This library refers to saving it as "cache" rather than permanently, so I am not sure if this is the correct solution. The specific section I am looking at on the library page is "Use Specific File Path". But because it is cache, should I be looking for something else that is more of a longer term storage? It does say on the page that files will not be deleted so I am a bit confused as to what the difference between permanent storage and cache is in this case.
Once the files are downloaded would I then be able to open images and display them, open sound files and play them, and open the json files and process them?
Check out React Native FS, specifically the documentation on downloadFile:
https://github.com/johanneslumpe/react-native-fs#downloadfileoptions-downloadfileoptions--jobid-number-promise-promisedownloadresult-
Here's a working example:
import React, { Component } from 'react';
import {
AppRegistry,
Text,
View,
Image,
} from 'react-native';
import RNFS from 'react-native-fs';
export default class downloadFile extends Component {
constructor() {
super()
this.state = {
isDone: false,
};
this.onDownloadImagePress = this.onDownloadImagePress.bind(this);
}
onDownloadImagePress() {
RNFS.downloadFile({
fromUrl: 'https://facebook.github.io/react-native/img/header_logo.png',
toFile: `${RNFS.DocumentDirectoryPath}/react-native.png`,
}).promise.then((r) => {
this.setState({ isDone: true })
});
}
render() {
const preview = this.state.isDone ? (<View>
<Image style={{
width: 100,
height: 100,
backgroundColor: 'black',
}}
source={{
uri: `file://${RNFS.DocumentDirectoryPath}/react-native.png`,
scale: 1
}}
/>
<Text>{`file://${RNFS.DocumentDirectoryPath}/react-native.png`}</Text>
</View>
) : null;
return (
<View>
<Text onPress={this.onDownloadImagePress}>Download Image</Text>
{preview}
</View>
);
}
}
AppRegistry.registerComponent('downloadFile', () => downloadFile);
It's important to know that the height and width must be set on the Image

Categories

Resources