Orientation is not Updating After unlock the Device in react-native- android - react-native

i am Developing one Application, Actually my App is showing landscape and Portrait in Tabs/iPads. But in Tablets(iPad's working fine) when i was check the Orientation functionality working fine until unlock the Device.When i was lock the screen on Particular mode like (Portrait/Landscape) After that turned the Device showing before Orientation. Not Update the present Orientation.
I followed this link :https://github.com/yamill/react-native-orientation
this is my code:
componentWillMount(){
this.getOrientationtype()
}
getOrientationtype(){
//alert("Hello")
if(Platform.OS == 'ios'){ // to Identifying Android or iOS
if(aspectRatio>1.6){ // Code for Iphone
// alert("phone")
Orientation.lockToPortrait()
}
else{
Orientation.getOrientation((err, initial) => {
if(initial != 'UNKNOWN'){
this.setState({
orientation:initial
})
}
else{
this.setState({
orientation:'PORTRAIT'
})
}
});
}
}
else{
if(DeviceInfo.isTablet()){
// alert("android tab")
Orientation.getOrientation((err, initial) => {
if(initial != 'UNKNOWN'){
this.setState({
orientation:initial
})
}
else{
this.setState({
orientation:'PORTRAIT'
})
}
});
}
else{
Orientation.lockToPortrait()
}
}
}
Please find Out this Solution ....I am Using this link enter link description here

1.You should use Orientation.addOrientationListener for listen to the Orientation Events.
2.As see from the source code of OrientationModule.java, this library just call unregisterReceiver in onHostPause, so you can't receive onConfigurationChanged event after lock the screen.One way is to edit the onHostResume inside OrientationModule.java to meet what you want.
#Override
public void onHostResume() {
final Activity activity = getCurrentActivity();
if (activity == null) {
FLog.e(ReactConstants.TAG, "no activity to register receiver");
return;
}
activity.registerReceiver(receiver, new IntentFilter("onConfigurationChanged"));
//add below code to onHostResume function
//send broadcast onResume
final int orientationInt = getReactApplicationContext().getResources().getConfiguration().orientation;
Configuration newConfig = new Configuration();
newConfig.orientation = orientationInt;
Intent intent = new Intent("onConfigurationChanged");
intent.putExtra("newConfig", newConfig);
activity.sendBroadcast(intent);
}
the whole code can be found here OrientationModule.java

Related

How to run a function continuously in RN

I am trying to create a sound metering app with React Native, but it seems that if I start the metering, which I have as a infinite loop until the user stops it, it hangs the app.
Basically the user taps a button, invokes startMonitor(), then the runMonitor starts and checkSound() does a check for the current decibel level.
The relevant code section here
startMonitor() {
KeepAwake.activate();
this.setState({ monitorStatus: true
}, this.runMonitor );
}
runMonitor() {
while(this.state.monitorStatus) {
if(this.state.beginWait) {
this.wait(5000);
}
if(!this.state.isTransmitting) {
this.checkSound();
}
}
}
Any ideas on how to run a function continuously/infinite until the user cancels it?
You can use setInterval:
startMonitor() {
this.runMonitorIV = setInterval(runMonitor, 1000);
}
runMonitor() {
while(this.state.monitorStatus) {
if(this.state.beginWait) {
this.wait(5000);
}
if(!this.state.isTransmitting) {
this.checkSound();
}
}
}
//called on user event
stopMonitor() {
clearInterval(this.runMonitorIV);
}
(Not sure about your context or scope, but that's the basic idea)
There's also the TimerMixin that clears those timers triggers when a component unmounts.

React-Navigation and creation/destroy os screens/components

I have my app with some screens. One of these screens is called "Race". This race produce a ListView with current race ranking (came from Redux state). This same screen has a TCP connection component which connect to my sensor and get data (async).
When user click on rank item, a new screen is opened with current lap's from clicked racer (item on ListView). At this point, previous screen still working (which is fine), because I can see in my log when data is received by TCP component.
The problem is when user hit back buttom (or navigate to "Race" using side menu), the screen itself is re-created and my TCP component is re-created, which I don't want. So my question is: how can I prevent this screen to be re-constructed OR make this TCP component works like a singleton globally? I'm not sure if is possible or how to make it work with Redux.
Update 1: This is part of code. In this Race screen, I have this internal function that connect my TCP socket.
_connectSensor() {
console.log("Running connectSensor function...");
const { lap_info, dispatchAddLap, dispatchSetSensorStatus } = this.props;
const { race, sensor } = this.props;
if (sensor.sensor_status == SENSOR_ONLINE) {
console.log("Already connected!");
return;
}
dispatchSetSensorStatus(SENSOR_CONNECTING);
//var serverHost = sensor.host;
//var serverPort = sensor.port;
var serverHost = "mydomain.com";
var serverPort = 1212;
console.log("Sensor host: ",serverHost);
console.log("Sensor port: ",serverPort);
this.client = net.createConnection(serverPort, serverHost, () => {
// client.write('Hello, server! Love, Client.');
dispatchSetSensorStatus(SENSOR_ONLINE);
});
this.client.on('data', (data) => {
var obj = JSON.parse(data);
dispatchAddLap(obj);
});
This function is called by a button and it's working fine. When I go to another screen, this TCP socket still running and feeding data to my Redux, which is the desirable state. But when I got back to this screen (from another one), I can't access this socket anymore.....they still running and I can't stop. When I click "Start", "this.client" is a new object because react-navigation re-create my entire screen (my guess....).
I could put some code to force disconnect when this screen is ummounted....but is not what I need. I need to keep socket receiveing data (if user doesn't stop), even if this screen is not active.
Update 2: I have tried to add static client = null; to my class object, but doesn't work.
In my "Stop" button, I've added to debug console.log("Client object:",this.client); and this is the result:
1) When I open race screen and click 'start', then 'stop', object is returned for 'client'.
2) When I open race screen, click start, goe to another screen, go back to race screen and click "Stop": undefined is returned for 'client' object.
Solved. The 'key' for this problem is to export my class as new object, and not just class.
But I had another problem: if I need to use 'connect' from 'react-redux', this doesn't work....simple because 'connect' always return a new object, not the same.
So I made my own ocmponent and create functions to assign dispatchFunctions coming from parent object. This is my final TCP componente:
import React, { Component } from "react";
import { SENSOR_ONLINE, SENSOR_OFFLINE, SENSOR_CONNECTING } from "../constants";
var net = require("react-native-tcp");
class tcpCon extends Component {
static myId;
static dispatchAddLap;
static dispatchSetSensorStatus;
static client;
static sensor_status = SENSOR_OFFLINE;
constructor(props) {
super(props);
console.log("Componente TCP criado! Dados passados: ", props);
var RandomNumber = Math.floor(Math.random() * 10000 + 1);
this.myId = RandomNumber;
}
setDispatchAddLapFunc(func) {
this.dispatchAddLap = func;
}
setDispatchSetSensorStatusFunc(func) {
this.dispatchSetSensorStatus = func;
}
disconnectSensor() {
console.log("Disconnecting....Status no componente TCP: ", this.sensor_status);
if (this.sensor_status == SENSOR_ONLINE) {
this.sensor_status = SENSOR_OFFLINE;
// Dispatch sensor offline
if (this.client) {
console.log("Client object exists. Need to destroy it....");
this.client.destroy();
this.client = null;
} else {
console.log("Client doesn't exists");
}
}
}
displayObj() {
console.log("Client nesta conexao:",this.client);
}
connectSensor(hostname, port) {
console.log("Running connectSensor function...myId: ", this.myId);
console.log("Meu status local:", this.sensor_status);
if (this.sensor_status == SENSOR_ONLINE || this.client) {
console.log("Connection already exists! Returning....");
return;
}
//var con = net.createConnection(port, hostname, () => {
this.client = net.createConnection(port, hostname, () => {
// client.write('Hello, server! Love, Client.');
// dispatchSetSensorStatus(SENSOR_ONLINE);
//this.client = con;
this.sensor_status = SENSOR_ONLINE;
this.dispatchSetSensorStatus(SENSOR_ONLINE);
});
this.client.on("data", data => {
var obj = JSON.parse(data);
//console.log("Data arrived: ",obj);
this.dispatchAddLap(obj);
});
this.client.on("error", error => {
console.log("Erro conectando ao sensor: " + error);
// dispatchSetSensorStatus(SENSOR_OFFLINE);
this.sensor_status = SENSOR_OFFLINE;
this.dispatchSetSensorStatus(SENSOR_OFFLINE);
});
this.client.on("close", () => {
console.log("Conexão fechada no componente TCP.");
// dispatchSetSensorStatus(SENSOR_OFFLINE);
this.sensor_status = SENSOR_OFFLINE;
this.dispatchSetSensorStatus(SENSOR_OFFLINE);
});
//console.log("Client object na connection:", this.client);
//this.dispatchAddLap('Hello world!ID '+this.myId.toString());
}
}
export default new tcpCon();
And this is how I call to connect:
Con.setDispatchAddLapFunc(dispatchAddLap);
Con.setDispatchSetSensorStatusFunc(dispatchSetSensorStatus)
Con.connectSensor("address",1212);
To disconnect, just use this:
Con.setDispatchAddLapFunc(dispatchAddLap); // Just to be sure
Con.setDispatchSetSensorStatusFunc(dispatchSetSensorStatus); // Just to be sure
Con.disconnectSensor();
With this, anytime that I call this component, the same object is returned.

How Can I Set back to last activity in react-native for android?

How Can I Set back to last activity in react-native for android?
My thinking is:
1 set _navigate in index.android.js
// 设置回退的堆栈
var _navigator;
BackAndroid.addEventListener('hardwareBackPress', function() {
if (_navigator && _navigator.getCurrentRoutes().length > 1) {
_navigator.pop();
return true;
}
return false;
});
2 pass navigator in RouteMapping:
RouteMapper: function(route, navigationOperations, onComponentRef) {
_navigator = navigationOperations;
if (route.name === 'detail') {
// 问题详情页
return (
<DetailScreen
navigator={navigationOperations}
question={route.question} />
);
} else if (route.name == 'front') {
// 首页
return(
<FrontScreen
navigator={navigationOperations}
/>
);
}
},
3 set push in list view
gotoDetail: function(question: Object) {
this.props.navigator.push({
id: question.question_id,
name: 'detail',
question: question
})
But It not work. When I click back button in Android, it jump out the app?
How Can I do that?
Or Anyone can give some example?
You need to add the following code to <your project>/android/app/src/main/java/com/<your project>/MainActivity.java:
#Override
public void onBackPressed() {
if (mReactInstanceManager != null) {
mReactInstanceManager.onBackPressed();
} else {
super.onBackPressed();
}
}
Projects created with React Native 0.12 will behave correctly.
For more infos see this issue on Github https://github.com/facebook/react-native/issues/3223.

Transition with keepScrollPosition and navigateBack

We are using Durandal for our SPA application and came to a, in my opinion, common use case. We have two pages: one page is a list of entities (with filters, sorting, virtual scroll) and another is detail preview of an entity. So, user is on list page and set a filter and a list of results comes out. After scrolling a little bit down user notice an entity which he/she would like to see details for. So clicking on a proper link user is navigated to details preview page.
After "work finished" on preview page user click back button (in app itself or browser) and he/she is back on the list page. However, default 'entrance' transition scroll the page to the top and not to the position on list where user pressed preview. So in order to 'read' list further user have to scroll down where he/she was before pressing preview.
So I started to create new transition which will for certain pages (like list-search pages) keep the scroll position and for other pages (like preview or edit pages) scroll to top on transition complete. And this was easy to do however, I was surprised when I noticed that there are strange behavior on preview pages when I hit navigateBack 'button'. My already long story short, after investigation I found out that windows.history.back is completing earlier then the transition is made and this cause that preview pages are scrolled automatically down to position of previous (list) page when back button is hit. This scrolling have a very unpleasant effect on UI not mentioning that it is 'total catastrophe' for my transition.
Any idea or suggestion what could I do in this case?
Here is the code of transition. It is just a working copy not finished yet as far as I have this problem.
define(['../system'], function (system) {
var fadeOutDuration = 100;
var scrollPositions = new Array();
var getScrollObjectFor = function (node) {
var elemObjs = scrollPositions.filter(function (ele) {
return ele.element === node;
});
if (elemObjs.length > 0)
return elemObjs[0];
else
return null;
};
var addScrollPositionFor = function (node) {
var elemObj = getScrollObjectFor(node);
if (elemObj) {
elemObj.scrollPosition = $(document).scrollTop();
}
else {
scrollPositions.push({element: node, scrollPosition: $(document).scrollTop()});
}
};
var scrollTransition = function (parent, newChild, settings) {
return system.defer(function (dfd) {
function endTransition() {
dfd.resolve();
}
function scrollIfNeeded() {
var elemObj = getScrollObjectFor(newChild);
if (elemObj)
{
$(document).scrollTop(elemObj.scrollPosition);
}
else {
$(document).scrollTop(0);
}
}
if (!newChild) {
if (settings.activeView) {
addScrollPositionFor(settings.activeView);
$(settings.activeView).fadeOut(fadeOutDuration, function () {
if (!settings.cacheViews) {
ko.virtualElements.emptyNode(parent);
}
endTransition();
});
} else {
if (!settings.cacheViews) {
ko.virtualElements.emptyNode(parent);
}
endTransition();
}
} else {
var $previousView = $(settings.activeView);
var duration = settings.duration || 500;
var fadeOnly = !!settings.fadeOnly;
function startTransition() {
if (settings.cacheViews) {
if (settings.composingNewView) {
ko.virtualElements.prepend(parent, newChild);
}
} else {
ko.virtualElements.emptyNode(parent);
ko.virtualElements.prepend(parent, newChild);
}
var startValues = {
marginLeft: fadeOnly ? '0' : '20px',
marginRight: fadeOnly ? '0' : '-20px',
opacity: 0,
display: 'block'
};
var endValues = {
marginRight: 0,
marginLeft: 0,
opacity: 1
};
$(newChild).css(startValues);
var animateOptions = {
duration: duration,
easing : 'swing',
complete: endTransition,
done: scrollIfNeeded
};
$(newChild).animate(endValues, animateOptions);
}
if ($previousView.length) {
addScrollPositionFor(settings.activeView);
$previousView.fadeOut(fadeOutDuration, startTransition);
} else {
startTransition();
}
}
}).promise();
};
return scrollTransition;
});
A simpler approach could be to store the scroll position when the module deactivates and restore the scroll on viewAttached.
You could store the positions in some global app variable:
app.scrollPositions = app.scrollPositions || {};
app.scrollPositions[system.getModuleId(this)] = theCurrentScrollPosition;

Titanium notification (android toast) with image

I want to show an image as a toast instead of plain text message.
I have tried:
try{
var toast = Titanium.UI.createNotification({
duration: Ti.UI.NOTIFICATION_DURATION_LONG,
background: '/images/img1.png'
});
toast.show();
}
catch (err)
{
alert(err.message);
}
Application gets crashed without giving any alert. I have also tried :
try{
var toast = Titanium.UI.createNotification({
duration: Ti.UI.NOTIFICATION_DURATION_LONG,
message: 'text',
});
toast.setBackgroundImage('/images/img1.png');
toast.show();
}
catch (err)
{
alert(err.message);
}
But same issue. App crashes without giving error alert. Anyone knows how to give image in toast?
I think you missed '..' in the background image path.
/images/img1.png should be: ../images/img1.png
I solved it by the functions below. I have decide fade-out time as per my requirement (i.e. 10% of total time). This code may need to handle back button pressed event manually.
var createImageToast = function (img, time)
{
Ti.UI.backgroundColor = 'white';
var win = Ti.UI.createWindow();
var image = Ti.UI.createImageView({
image: img,
});
win.add(image);
win.open();
setTimeout(function(){
decreaseImageOpacity(win,image,1,parseInt(time/10));
},parseInt(time*9/10));
}
var decreaseImageOpacity = function (win, image, opacity, time)
{
if(opacity<=0)
{
win.close();
}
else
{
setTimeout(function(){
image.setOpacity(''+opacity);
decreaseImageOpacity(win,image,opacity-0.1, time);
},parseInt(time/10));
}
}