Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Android hardware back exit or back page #18954

Closed
forster-thomas opened this issue Apr 19, 2018 · 4 comments
Closed

Android hardware back exit or back page #18954

forster-thomas opened this issue Apr 19, 2018 · 4 comments
Labels
Platform: Android Android applications. Resolution: For Stack Overflow A question for Stack Overflow. Applying this label will cause issue to be closed. Resolution: Locked This issue was locked by the bot.

Comments

@forster-thomas
Copy link

Hi guys!

I need some help. I'm newest on react-native. And I don't know how fix that problem. I try any solutions, but neither one fix my occurrence.
That's the hell.

I have on "Home.js" and a "Detail.js".
When I'm on Home.js, and press android hardware button, I need to app close. That work's perfectly. But, when I go to Detail, and press android hardware button, the app close too. BUT I want to go back, and not close it.

See my files and show me the WAY. Thnks 4all.

Home.js

import React, { Component } from 'react';
import { connect } from 'react-redux';
import AXIOS from 'axios';
import { AsyncStorage, BackHandler, FlatList } from 'react-native';
import { Body, Button, Container, Content, Footer, FooterTab, Header, Icon, Left, Right, Text, Title } from 'native-base';
import { List, ListItem } from 'react-native-elements';
import { SetUserArticles, UserSession, modifySESSIONID } from '../actions/auth';
import Loading from '../components/Loading/Loading';
import { Login } from '../routes/Screens';

class Home extends Component {
constructor(props) {
super(props);

this.state = {
  keyname: '',
  visible: true,
  loading: true,
  state: false,
  sessionid: '',
  url: '',
  email: '',
  password: '',
  ticketids: '',
  chamados: []
};

}

componentWillMount() {
this.setState({ keyname: this.props.navigation.state.key });
}

componentDidMount() {
console.disableYellowBox = true;
console.log(this.props);

BackHandler.addEventListener('hardwareBackPress', () => {
  if (this.state.keyname === 'Home') {
    this._handleBackButton();
  }
});
this._loadAsyncArticles();

}

_handleBackButton() {
BackHandler.exitApp();
}

_loadAsyncArticles() {
AsyncStorage.getItem('UserArticles').then((ARTICLES) => {
if (ARTICLES === null) {
this._loadSession();
} else {
const DataArticles = JSON.parse(ARTICLES);
this.setState({
visible: false,
chamados: DataArticles.Articles
});
}
});
}

_reloadLogin = async () => {
const url = this.state.url;
const email = this.state.email;
const password = this.state.password;

try {
  return await AXIOS({
    url: `${url}/nph-genericinterface.pl/Webservice/AppTicket/Session`,
    method: 'POST',
    params: {
      UserLogin: email,
      Password: password,
    }
  });
} catch (error) {
  console.log('reloadLogin: ', error);
}

}

_loadSession = async () => {
try {
await AsyncStorage.getItem('UserSession').then((session) => {
if (session != null) {
const DataSession = JSON.parse(session);
this.setState({
sessionid: (DataSession.sessionid !== '') ? DataSession.sessionid : null,
});

      if (this.state.sessionid !== null) {
        this._loadUserData().then(() => {
          const url = this.state.url;
          const SessionID = this.state.sessionid;

          AXIOS({
            url: `${url}/nph-genericinterface.pl/Webservice/AppTicket/TicketSearch`,
            method: 'GET',
            params: {
              SessionID,
              Limit: 25
            }
          }).then((GETSESSION) => {
            const DATA = GETSESSION.data;

            if (Object.prototype.hasOwnProperty.call(DATA, 'Error')) {
              this._reloadLogin().then((result) => {
                if (Object.prototype.hasOwnProperty.call(result.data, 'SessionID')) {
                  this.props.modifySESSIONID(result.data.SessionID);

                  this.setState({
                    sessionid: result.data.SessionID
                  });

                  const sessionid = result.data.SessionID;
                  this.props.UserSession({ sessionid });
                }

                this._loadSession();
              });
            } else {
              const IDS = DATA.TicketID;
              let TICKETIDS = '';
              IDS.forEach((ticket) => { TICKETIDS += `${ticket},`; });
              TICKETIDS = TICKETIDS.slice(0, -1);

              this.setState({
                ticketids: `${TICKETIDS}`
              });

              this._loadArticles().then((result) => {
                const Articles = {
                  Articles: result.data.Ticket,
                  Timestamp: Date.now()
                };

                this.props.SetUserArticles(Articles);
                this._loadAsyncArticles();
              });
            }
          });
        });
      }
    }
  });
} catch (error) {
  console.log(error);
}

}

_loadUserData = async () => {
try {
await AsyncStorage.getItem('UserLogin').then((info) => {
if (info != null) {
const DataInfo = JSON.parse(info);
this.setState({
url: (DataInfo.url !== '') ? DataInfo.url : null,
email: (DataInfo.email !== '') ? DataInfo.email : null,
password: (DataInfo.password !== '') ? DataInfo.password : null,
});
}
});
} catch (error) {
console.log(error);
}
}

_loadArticles = async () => {
const url = this.state.url;
const SessionID = this.state.sessionid;
const TicketID = this.state.ticketids;
const AllArticles = 1;

try {
  return await AXIOS({
    url: `${url}/nph-genericinterface.pl/Webservice/AppTicket/TicketGet`,
    method: 'GET',
    params: {
      AllArticles,
      SessionID,
      TicketID
    }
  });
} catch (error) {
  console.log(error);
}

}

_handleTicket = (ticket) => {
BackHandler.removeEventListener('hardwareBackPress', this._handleBackButton);
this.props.navigation.navigate('Detail', ticket);
}

_handleClearArticles() {
AsyncStorage.removeItem('UserArticles');
this.setState({ visible: true });
this._loadAsyncArticles();
}

_handleExit() {
AsyncStorage.removeItem('UserSession');
this.props.navigation.navigate(Login);
}

render() {
if (this.state.visible) {
return (

);
}

return (
  <Container>
    <Header style={{ marginBottom: -20 }}>
      <Left>
        <Button transparent onPress={() => this.props.navigation.navigate('DrawerOpen')}>
          <Icon name='menu' />
        </Button>
      </Left>
      <Body>
        <Title>Header</Title>
      </Body>
      <Right />
    </Header>
    <Content>
      <List>
        <FlatList
          data={this.state.chamados}
          renderItem={({ item }) => (
            <ListItem onPress={() => this._handleTicket(item)} title={item.Title} subtitle={item.Created} subtitle={item.Created} />
          )}
          keyExtractor={item => item.TicketID}
        />
      </List>
    </Content>
    <Footer>
      <FooterTab>
        <Button vertical onPress={() => this._handleExit()}>
          <Icon name='exit' />
          <Text>Sign Out</Text>
        </Button>
        <Button vertical onPress={() => this._handleClearArticles()}>
          <Icon name='trash' />
          <Text>Clear Articles</Text>
        </Button>
      </FooterTab>
    </Footer>
  </Container>
);

}
}

const mapStateToProps = state => ({
sessionid: state.Spread.sessionid
});

export default connect(mapStateToProps, { SetUserArticles, UserSession, modifySESSIONID })(Home);

Detail.js
import React, { Component } from 'react';
import { NavigationActions } from 'react-navigation';
import { Body, Button, Container, Content, Header, Icon, Left, Subtitle, Title } from 'native-base';

class Detail extends Component {
render() {
const title = this.props.navigation.state.params.Title;
const ticketNumber = Ticket#${this.props.navigation.state.params.TicketNumber};

return (
  <Container>
    <Header noShadow style={{ marginBottom: -20 }}>
      <Left>
        <Button
          transparent
          onPress={() => {
            const dispatch = this.props.navigation.dispatch;
            dispatch(NavigationActions.back());
          }}
        >
          <Icon name='arrow-back' />
        </Button>
      </Left>
      <Body style={{ marginLeft: -100 }}>
        <Title> {title} </Title>
        <Subtitle> {ticketNumber} </Subtitle>
      </Body>
    </Header>
    <Content />
  </Container>
);

}
}

export default Detail;

@react-native-bot
Copy link
Collaborator

Thanks for posting this! It looks like your issue may be incomplete. Are all the fields required by the Issue Template filled out?

If you believe your issue contains all the relevant information, let us know in order to have a maintainer remove the No Template label. Thank you for your contributions.

How to ContributeWhat to Expect from Maintainers

@forster-thomas forster-thomas changed the title Android Back Exit or Back Android hardware back exit or back page Apr 19, 2018
@kunalqss
Copy link

@forster-thomas I use react-navigation in my project and it handles app navigation properly without me having to add back button listener.

When navigating from Login to Detail, use

this.props.navigation.navigate('Login')

and when navigating back from Detail to Login, simply invoke goBack() function on the navigation prop.

this.props.navigation.goBack()

Make sure both of these screens are declared in a single StackNavigator Object in your main router. That is only when the system will treat both screens as part of a single stack, and then push detail page on top of login initially, and pop the detail page from stack when goBack is invoked.

@christoph-jerolimov
Copy link
Contributor

christoph-jerolimov commented Apr 30, 2018

Hi, I created a PR which fixes this issue. Maybe you can verify this this change and give a thump up for #19077.

@react-native-bot react-native-bot added the Resolution: For Stack Overflow A question for Stack Overflow. Applying this label will cause issue to be closed. label May 7, 2018
@react-native-bot
Copy link
Collaborator

This issue looks like a question and not an actual bug report. Please try asking over on Stack Overflow instead.

facebook-github-bot pushed a commit that referenced this issue Sep 7, 2018
Summary:
This fixes issues #18954 and #15497

The transformation from Set to (an reversed) Array does not work on Android devices when the remote debugging was started with `react-native run-android`.

<!--
  Required: Write your motivation here.
  If this PR fixes an issue, type "Fixes #issueNumber" to automatically close the issue when the PR is merged.
-->

Add the following code to your App.js and run the app with `react-native run-android` in an Android device:

```
  componentDidMount() {
    BackHandler.addEventListener('hardwareBackPress', () => {
      console.warn('Callback called. Do not close app. Do nothing at all.');
      return true; // Do not close the app.
    });
  }
```

After adding this, the app should NOT close when you press the back button. Without this fix, the app closes (which is the default behaviour).

See also the comments from Victoriayangx in #18954 and #15497.

<!--
  Does this PR require a documentation change?
  Create a PR at https://github.com/facebook/react-native-website and add a link to it here.
-->

<!--
  Required.
  Help reviewers and the release process by writing your own release notes. See below for an example.
-->

[ANDROID] [BUGFIX] [BackHandler] - Fix that BackHandler was not called on Android

<!--
  **INTERNAL and MINOR tagged notes will not be included in the next version's final release notes.**

    CATEGORY
  [----------]      TYPE
  [ CLI      ] [-------------]    LOCATION
  [ DOCS     ] [ BREAKING    ] [-------------]
  [ GENERAL  ] [ BUGFIX      ] [ {Component} ]
  [ INTERNAL ] [ ENHANCEMENT ] [ {Filename}  ]
  [ IOS      ] [ FEATURE     ] [ {Directory} ]   |-----------|
  [ ANDROID  ] [ MINOR       ] [ {Framework} ] - | {Message} |
  [----------] [-------------] [-------------]   |-----------|

 EXAMPLES:

 [IOS] [BREAKING] [FlatList] - Change a thing that breaks other things
 [ANDROID] [BUGFIX] [TextInput] - Did a thing to TextInput
 [CLI] [FEATURE] [local-cli/info/info.js] - CLI easier to do things with
 [DOCS] [BUGFIX] [GettingStarted.md] - Accidentally a thing/word
 [GENERAL] [ENHANCEMENT] [Yoga] - Added new yoga thing/position
 [INTERNAL] [FEATURE] [./scripts] - Added thing to script that nobody will see
-->
Pull Request resolved: #19077

Reviewed By: yns88

Differential Revision: D9692298

Pulled By: hramos

fbshipit-source-id: 4526b07a4924055ebc9c42e02615c27aa5c97fbb
gengjiawen pushed a commit to gengjiawen/react-native that referenced this issue Sep 14, 2018
Summary:
This fixes issues facebook#18954 and facebook#15497

The transformation from Set to (an reversed) Array does not work on Android devices when the remote debugging was started with `react-native run-android`.

<!--
  Required: Write your motivation here.
  If this PR fixes an issue, type "Fixes #issueNumber" to automatically close the issue when the PR is merged.
-->

Add the following code to your App.js and run the app with `react-native run-android` in an Android device:

```
  componentDidMount() {
    BackHandler.addEventListener('hardwareBackPress', () => {
      console.warn('Callback called. Do not close app. Do nothing at all.');
      return true; // Do not close the app.
    });
  }
```

After adding this, the app should NOT close when you press the back button. Without this fix, the app closes (which is the default behaviour).

See also the comments from Victoriayangx in facebook#18954 and facebook#15497.

<!--
  Does this PR require a documentation change?
  Create a PR at https://github.com/facebook/react-native-website and add a link to it here.
-->

<!--
  Required.
  Help reviewers and the release process by writing your own release notes. See below for an example.
-->

[ANDROID] [BUGFIX] [BackHandler] - Fix that BackHandler was not called on Android

<!--
  **INTERNAL and MINOR tagged notes will not be included in the next version's final release notes.**

    CATEGORY
  [----------]      TYPE
  [ CLI      ] [-------------]    LOCATION
  [ DOCS     ] [ BREAKING    ] [-------------]
  [ GENERAL  ] [ BUGFIX      ] [ {Component} ]
  [ INTERNAL ] [ ENHANCEMENT ] [ {Filename}  ]
  [ IOS      ] [ FEATURE     ] [ {Directory} ]   |-----------|
  [ ANDROID  ] [ MINOR       ] [ {Framework} ] - | {Message} |
  [----------] [-------------] [-------------]   |-----------|

 EXAMPLES:

 [IOS] [BREAKING] [FlatList] - Change a thing that breaks other things
 [ANDROID] [BUGFIX] [TextInput] - Did a thing to TextInput
 [CLI] [FEATURE] [local-cli/info/info.js] - CLI easier to do things with
 [DOCS] [BUGFIX] [GettingStarted.md] - Accidentally a thing/word
 [GENERAL] [ENHANCEMENT] [Yoga] - Added new yoga thing/position
 [INTERNAL] [FEATURE] [./scripts] - Added thing to script that nobody will see
-->
Pull Request resolved: facebook#19077

Reviewed By: yns88

Differential Revision: D9692298

Pulled By: hramos

fbshipit-source-id: 4526b07a4924055ebc9c42e02615c27aa5c97fbb
@facebook facebook locked as resolved and limited conversation to collaborators May 7, 2019
@react-native-bot react-native-bot added the Resolution: Locked This issue was locked by the bot. label May 7, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Platform: Android Android applications. Resolution: For Stack Overflow A question for Stack Overflow. Applying this label will cause issue to be closed. Resolution: Locked This issue was locked by the bot.
Projects
None yet
Development

No branches or pull requests

5 participants