I have an app (Webview exactly) and I'm trying to handle the Android hardware button to return from the second page for example to the first one. My problem now is the button won't close the app anymore, and I don't know what should I do. Here is my code:
export default class App extends Component {
constructor(props) {
super(props)
this.state={
};
this.handleBackButtonClick = this.handleBackButtonClick.bind(this);
}
componentWillMount() {
BackHandler.addEventListener('hardwareBackPress',this.handleBackButtonClick);
}
componentWillUnmount() { BackHandler.removeEventListener('hardwareBackPress',this.handleBackButtonClick);
}
onNavigationStateChange(navState){
console.log(JSON.stringify(navState));
canGoBack = navState.url == initialUrl && !navState.loading
}
handleBackButtonClick() {
this.refs[WEBVIEW_REF].goBack();
return true;
}
The return value of handleBackButtonClick determines whether the app is to be kept running or not.
Currently, you are always returning true. Instead, you could check whether the current navigation state is such that you would like to close the app, and return false accordingly.
handleBackButtonClick() {
const canGoBack = someCalculation();
if(canGoBack)
this.refs[WEBVIEW_REF].goBack();
}
return canGoBack;
}
Related
I have a requirement of pausing video and some other actions to perform when user clicks on home button or switch to another app using swiper action. I looked at react-native AppState, but it is not calling the event listener when home button clicked on android for some devices. Is there any compatibility minimum version requirements for the react-native app state to work?
The code I tried is as below
useEffect(() => {
AppState.addEventListener("change", _handleAppStateChange);
return () => {
AppState.removeEventListener("change", _handleAppStateChange);
};
}, []);
const _handleAppStateChange = (nextAppState: any) => {
console.log(nextAppState);
};
The console is not printed when clicked on home button/Swiped to another app on some android devices. Is there anyway I can achieve this using react-native preferably without using any external libraries.
As for your requirement, in react-native, to detect is application is in foreground or in background, you don't need to add home-button listener, we can easily achieve this with the help of AppState, check below example,
_handleAppStateChange = (nextAppState: any) => {
if (this.state.appState === "active" && nextAppState === "background") {
// this condition calls when app goes in background mode
// here you can detect application is in background, and you can pause your video
} else if (this.state.appState === "background" && nextAppState === "active") {
// this condition calls when app is in foreground mode
// here you can detect application is in active state again,
// and if you want you can resume your video
}
this.setState({ appState: nextAppState });
};
You also need to attach AppState listener to application to detect application states, for example,
componentDidMount() {
AppState.addEventListener("change", _handleAppStateChange);
}
and detach app-state listener when application component unmount, for example,
componentWillUnmount {
AppState.removeEventListener("change", _handleAppStateChange);
}
Or if you are working with functional component you attach or detach app-state listener in useEffect, for example,
useEffect(() => {
AppState.addEventListener("change", _handleAppStateChange);
return () => {
AppState.removeEventListener("change", _handleAppStateChange);
};
}, []);
I want to perform some actions when my app goes to the background—e.g., when pressing the home button. (I am testing on an Android device.)
I tried the following in my app.component.ts:
this.platform.ready().then(() => {
this.platform.pause.subscribe(async () => {
alert("Pause event detected");
//Do stuff here
});
this.platform.resume.subscribe(async () => {
alert("Resume event detected");
//Do stuff here
});
…
I also tried:
App.getState().then((result) => {
alert("state active?" + result.isActive);
});
No listener is triggered when the app goes to background (e.g., by pressing the home button). But when I start the app again, all events are triggered (in this case, the alerts), including the platform.pause event.
I am using Ionic 9 and Capacitor.
Am I misunderstanding something? What could be the problem?
You can use the event listeners provided in Capacitor's App API.
// Import the relevant stuff from Capacitor
import { Plugins, AppState } from '#capacitor/core';
const { App } = Plugins;
Then in your AppComponent class
this.platform.ready().then(() => {
App.addListener('appStateChange', (state: AppState) => {
if (state.isActive) {
console.log('App has become active');
} else {
console.log('App has become inactive');
}
});
})
Note that you can test this in a desktop browser as well by switching to another tab.
Ok... things work. The problem was, that I had both variants in code active.
I am trying to disabling the physical device back in android only in some screens. Trying the below code is not working. Any idea?
import { RouterExtensions } from "nativescript-angular";
import * as application from "application";
import { AndroidApplication, AndroidActivityBackPressedEventData } from "application";
import { isAndroid } from "platform";
export class ItemComponent implements OnInit {
constructor(private router: Router) {}
ngOnInit() {
if (!isAndroid) {
return;
}
application.android.on(AndroidApplication.activityBackPressedEvent, (data: AndroidActivityBackPressedEventData) => {
data.cancel = true; // prevents default back button behavior
});
}
}
#Override
public void onBackPressed() {
if (!shouldAllowBack()) {
doSomething();
} else {
super.onBackPressed();
}
}
Add this code in your activity-
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// Your Code Here. Leave empty if you want nothing to happen on back press.
}
For more information visit this link.
Back button is controlled at Activity level, NativeScript uses one single Activity and all your pages / routes are fragments inside that.
So you don't have to call it on every page / component. Add the listener to your app component and check the router to know which page you are at and cancel the back event.
Use location and check if location consists the desired path(as mentioned in routing file) where you want to use your custom function.
import { Location } from '#angular/common';
constructor(private _location: Location
){}
if (application.android) {
application.android.on(AndroidApplication.activityBackPressedEvent, (data: AndroidActivityBackPressedEventData) => {
const path = this._location.path();
console.log(`path i s--> ${path}`);
switch (path) {
case '/Screen 1':
data.cancel = true;
break;
case '/Screen 2':
//do something else
break;
});
}
I have an ionic 3 app based on the super template. I have set the root page to the following:
<ion-tabs>
<ion-tab [root]="tab1Root" [tabTitle]="tab1Title" tabIcon="bonfire"></ion-tab>
<ion-tab [root]="tab2Root" [tabTitle]="tab2Title" tabIcon="search"></ion-tab>
<ion-tab [root]="tab3Root" [tabTitle]="tab3Title" tabIcon="cog"></ion-tab>
</ion-tabs>
When I press the hardware back button on this page, nothing happens at all. However, when I change the content to something else, like:
<p>Hello</p>
Then the hardware back button exits, as I would like.
How can I make the hardware back button work correctly on the tabbed page, while preserving the working default behaviour on other pages?
Inside your app.component.ts file
import { Nav, App } from 'ionic-angular';
export class MyApp {
#ViewChild(Nav) nav: Nav;
and then
platform.registerBackButtonAction(() => {
let nav = app.getActiveNav();
let activeView: ViewController = nav.getActive();
if(activeView != null){
if(nav.canGoBack()) {
nav.pop();
}else if (typeof activeView.instance.backButtonAction === 'function')
{
activeView.instance.backButtonAction();
}
else {
nav.parent.select(0); // goes to the first tab
}
}
});
Hope this helps you and also don't forget to place it inside the platform.
in your respcted ts file where you need to close the application write a funtion
backButtonAction(){
this.platfrom.exitApp();
}
I ended up needing to do this in app.container.ts to get the desired behaviour:
platform.registerBackButtonAction(() => {
let nav = app.getActiveNav();
let activeView = nav.getActive();
if (activeView != null){
if (nav.canGoBack()) {
nav.pop();
} else if (nav.parent.getSelected() != nav.parent.getByIndex(0)) {
// goes to the first tab
nav.parent.select(0);
} else {
platform.exitApp();
}
}
});
In your Tabs Page try to Add ionViewDidEnter and try to append the following class as follows:
ionViewDidEnter() {
this.platform.registerBackButtonAction(() => {
this.platform.exitApp();
});
}
Write your code inside the constructor() from which page you to leave.
Home.ts
constructor(
public navCtrl: NavController,
private platform: Platform) {
this.platform.registerBackButtonAction(()=>{
this.platform.exitApp();
});
}
I have splash screen on my apps, so I want to exit the apps when we click android back button from the main page (not go back to splash screen). So I want to implement this method from react-native tutorial.
if (!this.onMainScreen()) {
this.goBack();
return true;
}
return false;
Is there anyone can help me how to implement onMainScreen(), and goBack() functions?
Thank you for the help.
you should be able to use this function
function getCurrentRouteFromState(navigationState): NavigationRouteConfigMap {
const route = navigationState.routes[navigationState.index];
// dive into nested navigators
if (route.routes) {
return getCurrentRouteFromState(route);
}
return route;
}
pass it your navigation state and access the routeName member on the resulting object:
let screenName = getCurrentRouteFromState(state).routeName then you can compare the screen name with your main screen name and decide what to do.
So, On your main page(I think which is your Main.js)
import { BackHandler } from 'react-native';
componentWillMount(){
BackHandler.addEventListener('hardwareBackPress', function() {
BackHandler.exitApp();
});
}