Steps to Reproduce
Connect the actual device to the Android studio, start an extension, and then click the Run app button in the Android studio to install the app on the device. The permissions check is successful in this app.
However, after ‘expo publish’ build => signed Bundle APK => select APK => click release=> V1,V2 Check => APK on the device to run.
Pressing a button does not generate an alert for the privilege.
Expected Behavior
Shall be operated like a simulator apk.
Actual Behavior
The actual APK does not notify you of any permissions.
Reproducible Demo
import React, { Component } from "react";
import {
Platform,
StyleSheet,
View,
Text,
Modal,
TouchableOpacity,
TouchableHighlight,
Image,
Alert,
NativeModules
} from "react-native";
import * as Permissions from "expo-permissions";
import { Ionicons } from "@expo/vector-icons";
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
alertVisibility: true
};
}
static navigationOptions = ({ navigation }) => {
return {
headerLeft: (
<TouchableOpacity style={{ paddingLeft: 25 }} onPress={() => {}}>
<Ionicons
name={"ios-arrow-back"}
size={30}
color={"#ffffff"}
/>
</TouchableOpacity>
),
headerRight: null
};
};
showCustomAlert(visible) {
this.setState({ alertVisibility: visible });
}
okButton = async () => {
this.setState({
buttonColor: "#ffd90d"
});
const permission = await Permissions.getAsync(Permissions.CAMERA_ROLL);
if (permission.status !== "granted") {
const newPermission = await Permissions.askAsync(Permissions.CAMERA_ROLL);
if (newPermission.status === "granted") {
const permission2 = await Permissions.getAsync(Permissions.CAMERA);
if (permission2.status !== "granted") {
const newPermission2 = await Permissions.askAsync(Permissions.CAMERA);
if (newPermission2.status === "granted") {
const permission3 = await Permissions.getAsync(
Permissions.NOTIFICATIONS
);
if (permission3.status !== "granted") {
const newPermission3 = await Permissions.askAsync(
Permissions.NOTIFICATIONS
);
if (newPermission3.status === "granted") {
const permission4 = await Permissions.getAsync(
Permissions.REMINDERS
);
if (permission4.status !== "granted") {
const newPermission4 = await Permissions.askAsync(
Permissions.REMINDERS
);
if (newPermission4.status === "granted") {
this.setState({ alertVisibility: false });
this.props.navigation.navigate("RegisterWalletIndex");
} else {
this.setState({ alertVisibility: false });
this.props.navigation.navigate("RegisterWalletIndex");
}
}
if (permission4.status === "granted") {
console.log(
"permission4.status not granted"
);
} else {
console.log(
"permission4.status not granted"
);
}
} else {
const permission4 = await Permissions.getAsync(
Permissions.REMINDERS
);
if (permission4.status !== "granted") {
const newPermission4 = await Permissions.askAsync(
Permissions.REMINDERS
);
if (newPermission4.status === "granted") {
this.setState({ alertVisibility: false });
this.props.navigation.navigate("RegisterWalletIndex");
} else {
this.setState({ alertVisibility: false });
this.props.navigation.navigate("RegisterWalletIndex");
}
}
if (permission4.status === "granted") {
console.log(
"permission4.status not granted"
);
} else {
console.log(
"permission4.status not granted"
);
}
}
}
if (permission3.status === "granted") {
console.log(
"permission4.status not granted"
);
} else {
console.log(
"permission4.status not granted"
);
}
} else {
const permission3 = await Permissions.getAsync(
Permissions.NOTIFICATIONS
);
if (permission3.status !== "granted") {
const newPermission3 = await Permissions.askAsync(
Permissions.NOTIFICATIONS
);
if (newPermission3.status === "granted") {
const permission4 = await Permissions.getAsync(
Permissions.REMINDERS
);
if (permission4.status !== "granted") {
const newPermission4 = await Permissions.askAsync(
Permissions.REMINDERS
);
if (newPermission4.status === "granted") {
this.setState({ alertVisibility: false });
this.props.navigation.navigate("RegisterWalletIndex");
} else {
this.setState({ alertVisibility: false });
this.props.navigation.navigate("RegisterWalletIndex");
}
}
if (permission4.status === "granted") {
console.log(
"permission4.status not granted"
);
} else {
console.log(
"permission4.status not granted"
);
}
} else {
console.log(
"permission3.status not granted"
);
const permission4 = await Permissions.getAsync(
Permissions.REMINDERS
);
if (permission4.status !== "granted") {
const newPermission4 = await Permissions.askAsync(
Permissions.REMINDERS
);
if (newPermission4.status === "granted") {
this.setState({ alertVisibility: false });
this.props.navigation.navigate("RegisterWalletIndex");
} else {
this.setState({ alertVisibility: false });
this.props.navigation.navigate("RegisterWalletIndex");
}
}
if (permission4.status === "granted") {
console.log(
"permission4.status not granted"
);
} else {
console.log("permission4.status not granted");
}
}
}
if (permission3.status === "granted") {
console.log(
"permission4.status not granted"
);
}
}
}
if (permission2.status === "granted") {
console.log(
"permission4.status not granted"
);
} else {
console.log(
"permission4.status not granted"
);
}
} else {
alert("close");
}
} else {
if (permission.status === "granted") {
console.log(
"permission4.status not granted"
);
} else {
console.log(
"permission4.status not granted"
);
}
}
};
androidButton = async () => {
const permission = await Permissions.getAsync(Permissions.CAMERA_ROLL);
if (permission.status !== "granted") {
const newPermission = await Permissions.askAsync(Permissions.CAMERA_ROLL);
if (newPermission.status === "granted") {
const permission2 = await Permissions.getAsync(Permissions.CAMERA);
if (permission2.status !== "granted") {
const newPermission2 = await Permissions.askAsync(Permissions.CAMERA);
if (newPermission2.status === "granted") {
const permission3 = await Permissions.getAsync(
Permissions.NOTIFICATIONS
);
if (permission3.status !== "granted") {
const newPermission3 = await Permissions.askAsync(
Permissions.NOTIFICATIONS
);
if (newPermission3.status === "granted") {
this.setState({ alertVisibility: false });
this.props.navigation.navigate("RegisterWalletIndex");
}
}
if (permission3.status === "granted") {
this.setState({ alertVisibility: false });
this.props.navigation.navigate("RegisterWalletIndex");
} else {
console.log("permission3.status not granted");
}
} else {
const permission3 = await Permissions.getAsync(
Permissions.NOTIFICATIONS
);
if (permission3.status !== "granted") {
const newPermission3 = await Permissions.askAsync(
Permissions.NOTIFICATIONS
);
if (newPermission3.status === "granted") {
this.setState({ alertVisibility: false });
this.props.navigation.navigate("RegisterWalletIndex");
} else {
this.setState({ alertVisibility: false });
this.props.navigation.navigate("RegisterWalletIndex");
}
}
if (permission3.status === "granted") {
this.setState({ alertVisibility: false });
this.props.navigation.navigate("RegisterWalletIndex");
}
}
}
if (permission2.status === "granted") {
this.setState({ alertVisibility: false });
this.props.navigation.navigate("RegisterWalletIndex");
}
} else {
Alert.alert(
"info",
`Text`,
[
{
text: "ok",
onPress: () => alert("close")
}
],
{ cancelable: false }
);
}
} else {
const permission2 = await Permissions.getAsync(Permissions.CAMERA);
if (permission2.status !== "granted") {
const newPermission2 = await Permissions.askAsync(Permissions.CAMERA);
if (newPermission2.status === "granted") {
this.setState({ alertVisibility: false });
this.props.navigation.navigate("RegisterWalletIndex");
} else {
this.setState({ alertVisibility: false });
this.props.navigation.navigate("RegisterWalletIndex");
}
} else {
this.setState({ alertVisibility: false });
this.props.navigation.navigate("RegisterWalletIndex");
}
}
};
render() {
return (
<View style={styles.MainContainer}>
<Modal
visible={this.state.alertVisibility}
transparent={true}
animationType={"fade"}
onRequestClose={() => {
this.showCustomAlert(!this.state.alertVisibility);
}}
>
<View
style={{
flex: 1,
height: "100%",
alignItems: "center",
justifyContent: "center",
backgroundColor: "rgba(0,0,0,.8)"
}}
>
<View style={styles.alertmainview}>
<Text style={styles.alerttitle}>Text</Text>
<View
style={{
width: "60%",
height: 1,
backgroundColor: "#fed80c",
marginLeft: 20
}}
/>
<Text style={styles.alertmessage}>
Text
</Text>
<View>
<Text style={styles.subtitle}>Text</Text>
<View
style={{
flexDirection: "row",
backgroundColor: "#efefef",
alignItems: "center",
marginLeft: 20,
marginRight: 20,
borderRadius: 3,
marginBottom: 10
}}
>
<Text style={styles.subtitletextstorage}>Text</Text>
<Text style={styles.subtitletext2}>Text</Text>
</View>
<Text style={styles.subtitle}>Text Text</Text>
<View
style={{
flexDirection: "column",
backgroundColor: "#efefef",
marginLeft: 20,
marginRight: 20,
borderRadius: 3
}}
>
<View style={{ flexDirection: "row", marginTop: 6 }}>
<Text style={styles.subtitletext}>Text</Text>
<Text style={styles.subtitletext2}>Text Text</Text>
</View>
<View
style={{
flexDirection: "row",
paddingTop: 8,
paddingBottom: 8
}}
>
<Text style={styles.subtitletext}>Text</Text>
<Text style={styles.subtitletext2}>
Text
</Text>
</View>
</View>
</View>
<View
style={{
width: "90%",
height: 1,
backgroundColor: "#fed80c",
marginLeft: 20,
marginRight: 20,
marginTop: 20
}}
/>
<View
style={{
width: "100%",
alignItems: "flex-end",
paddingRight: 20,
paddingTop: 10
}}
>
<TouchableHighlight
underlayColor="#ffd90d"
style={styles.buttonStyle}
onPress={() =>
Platform.OS === "ios"
? this.okButton()
: this.androidButton()
}
>
<Text style={styles.TextStyle}> ok </Text>
</TouchableHighlight>
</View>
</View>
</View>
</Modal>
<Image
style={{ width: 180, height: 180 }}
source={require("./assets/snack-icon.png")}
resizeMode="contain"
/>
</View>
);
}
}
const styles = StyleSheet.create({
MainContainer: {
flex: 1,
justifyContent: "center",
alignItems: "center",
marginTop: Platform.OS == "ios" ? 20 : 0,
backgroundColor: "rgba(0,0,0,.8)"
},
alertmainview: {
width: "90%",
borderRadius: 8,
backgroundColor: "#fff"
},
alerttitle: {
fontSize: 18,
textAlign: "left",
paddingLeft: 24,
paddingTop: 30,
marginBottom: 10
},
alertmessage: {
fontSize: 14,
padding: 20
},
subtitle: {
fontWeight: "bold",
marginLeft: 20,
paddingTop: 12,
fontSize: 12,
paddingBottom: 8
},
subtitletext: {
fontWeight: "bold",
marginLeft: 10,
fontSize: 14
},
subtitletextstorage: {
fontWeight: "bold",
marginLeft: 10,
fontSize: 14,
marginTop: 6,
marginBottom: 6
},
subtitletext2: {
marginLeft: 10,
fontSize: 14,
color: "#434343"
},
buttonStyle: {
width: 60,
height: 34,
justifyContent: "center",
borderRadius: 20,
marginBottom: 18
},
TextStyle: {
textAlign: "center",
fontSize: 14,
fontWeight: "bold"
}
});
export default App;
Environment
Expo CLI 2.20.2 environment info:
System:
OS: macOS 10.14.5
Shell: 3.2.57 - /bin/bash
Binaries:
Node: 10.16.0 - ~/.nvm/versions/node/v10.16.0/bin/node
Yarn: 1.15.2 - ~/.yarn/bin/yarn
npm: 6.9.0 - ~/.nvm/versions/node/v10.16.0/bin/npm
Watchman: 4.9.0 - /usr/local/bin/watchman
IDEs:
Android Studio: 3.3 AI-182.5107.16.33.5314842
Xcode: 10.2.1/10E1001 - /usr/bin/xcodebuild
npmGlobalPackages:
expo-cli: 2.20.2
“react-native”: “https://github.com/expo/react-native/archive/sdk-33.0.0.tar.gz”,
“expo”: “^33.0.0”,
“expo-ads-admob”: “~5.0.1”,
Android real device : LGM-V300S.
Android Studio 3.3.2
macOS 10.14.5
Standalone App(ExpoKit)