open failed: EACCES (Permission denied) in ionic -2 - android

I was using cordova-plugin-file-transfer and cordova-plugin-file-chooser on Ionic mobile application to upload some files to Android device which can open with native applications like pdf, word, excel..etc
It is now throwing "exception":"/storage/emulated/0/Download/pdf-test.pdf: open failed: EACCES (Permission denied)"}".
openFile() {
console.log("openFile");
this.fileChooser.open()
.then(uri => {
console.log(uri)
const fileTransfer: FileTransferObject = this.transfer.create();
let options: FileUploadOptions = {
fileKey: 'files',
fileName: 'name.doc',
params: { resume: uri},
chunkedMode: false,
headers: {
'token': this.token,
'sid': this.sid,
'user': this.user,
'to': this.to,
'node': this.node,
'type': 'doc',
'cap': this.cap
}
}
console.log("Headers" + JSON.stringify(options));
fileTransfer.upload(uri,this.apiurl, options)
.then((data) => {
// success
console.log("Response data ->>>>>>> :- " + JSON.stringify(data));
alert("success" + JSON.stringify(data));
}, (err) => {
// error
console.log("Error data ->>>>>>> :- " + JSON.stringify(err));
alert("error" + JSON.stringify(err));
});
})
.catch(e => console.log(e));
}
I also added permission on AndroidManifest.xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

Android Permissions
This plugin is designed for supporting Android new permissions checking mechanism.
Since Android 6.0, the Android permissions checking mechanism has been changed. In the past, the permissions were granted by users when they decide to install the app. Now, the permissions should be granted by a user when he/she is using the app.
For old Android plugins you (developers) are using may not support this new mechanism or already stop updating. So either to find a new plugin to solving this problem, nor trying to add the mechanism in the old plugin. If you don't want to do those, you can try this plugin.
https://ionicframework.com/docs/native/android-permissions/
filePermission() {
this.androidPermissions.checkPermission(this.androidPermissions.PERMISSION.WRITE_EXTERNAL_STORAGE).then(
result => console.log('Has permission?', result.hasPermission),
err => this.androidPermissions.requestPermission(this.androidPermissions.PERMISSION.WRITE_EXTERNAL_STORAGE)
);
}

Related

Error in implementing push notification on Android

I am creating an ionic-angular app. I tried to use push notification with the capacitor plugin. But I got an error like this. Can anyone help me?
**"ERROR Error: Uncaught (in promise): Error: "PushNotifications" plugin is not implemented on android
Error: "PushNotifications" plugin is not implemented on android"**
I resolved "ERROR Error: Uncaught (in promise): Error: "PushNotifications" plugin is not implemented on android
Error: "PushNotifications" plugin is not implemented on android" error please follow below step
Add google-service.json file inside android/app folder
add this code in .ts file
import {
ActionPerformed,
PushNotificationSchema,
PushNotifications,
Token,
} from '#capacitor/push-notifications';
import { Platform } from '#ionic/angular';
constructor(public platform: Platform) {
this.platform.ready().then(() => {
this.pushAdded();
})
}
pushAdded() {
// Request permission to use push notifications
// iOS will prompt user and return if they granted permission or not
// Android will just grant without prompting
PushNotifications.requestPermissions().then(result => {
if (result.receive === 'granted') {
// Register with Apple / Google to receive push via APNS/FCM
PushNotifications.register();
} else {
// Show some error
}
});
PushNotifications.addListener('registration', (token: Token) => {
alert('Push registration success, token: ' + token.value);
});
PushNotifications.addListener('registrationError', (error: any) => {
alert('Error on registration: ' + JSON.stringify(error));
});
PushNotifications.addListener(
'pushNotificationReceived',
(notification: PushNotificationSchema) => {
alert('Push received: ' + JSON.stringify(notification));
},
);
PushNotifications.addListener(
'pushNotificationActionPerformed',
(notification: ActionPerformed) => {
alert('Push action performed: ' + JSON.stringify(notification));
},
);
}
I have fixed this issue by removing the android folder and re-add that. Then it worked. Thanks, Ravi Ashara for helping.
Check your MainActivity.java within your project. In the last version of Capacitor you have to remove the code "onCreate".
See: https://capacitorjs.com/docs/updating/3-0#switch-to-automatic-android-plugin-loading

Launch local pdf file with external pdf viewer using react-native and expo

I'm new to react-native. I have a sample pdf file on my mobile storage and tried to launch in an external pdf viewer using IntentLauncher.startActivityAsync. It launches the external app but doesn't open the file. Here is my code,
IntentLauncher.startActivityAsync("android.intent.action.VIEW", {
data: FileUri,
flags: 1,
type: "application/pdf",
});
This is my file-url: '/storage/emulated/0/MyFolder/sample-file.pdf'.
I think the data (key) may be wrong. How can I fix it?
Without any other way, now I am using React Native CLI to overcome the issue.
react-native-file-viewer fulfilled my need. And here is my code,
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE,
);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
FileViewer.open(path, {showOpenWithDialog: true})
.then(() => {
// something useful here
})
.catch((err) => {
console.log('err: ', err);
});
} else {
console.log('Permission denied');
}
And this is my path: 'file:///storage/emulated/0/Download/test.pdf'

Expo InAppPurchases connectAsync returns undefined

I'm having issues trying to get the InAppPurchases to work in my React Native app using Expo. https://docs.expo.io/versions/latest/sdk/in-app-purchases
This is a bare workflow app that I ejected from a standard Expo app.
I made sure to follow the install instructions here carefully: https://docs.expo.io/bare/installing-unimodules/
I did test if unimodules was properly installed:
import { Constants } from "react-native-unimodules";
useEffect(() => {
alert("installed: " + JSON.stringify(Constants.systemFonts));
}, []);
The code above worked.
I'm using react-native-unimodules version 0.11.0.
Here's my code:
useEffect(() => {
(async function init() {
try {
const connect_res = await connectAsync();
alert("connect: " + JSON.stringify(connect_res));
} catch (err) {
alert("general error for connect async: " + err);
}
})();
}, []);
This is in the App.js entrypoint file. It always returns undefined for the connect_res so I assume this is the reason why I couldn't get any of the code to work.
Just below connectAsync() I have the following. This one also doesn't return anything:
setPurchaseListener(({ responseCode, results, errorCode }) => {
if (responseCode === IAPResponseCode.OK) {
results.forEach((purchase) => {
if (!purchase.acknowledged) {
alert("purchase successful!");
finishTransactionAsync(purchase, true);
}
});
}
if (responseCode === IAPResponseCode.USER_CANCELED) {
alert("user cancelld!");
} else if (responseCode === IAPResponseCode.DEFERRED) {
alert("user does not have permission to buy");
} else {
alert("something went wrong: " + errorCode);
}
});
Then on my payment screen I have the following:
import { getProductsAsync, purchaseItemAsync } from "expo-in-app-purchases";
This is the code for the payment button:
const makePayment = async () => {
alert("now making payment...");
try {
const items = Platform.select({
ios: ["abc"],
android: ["my-sub-id", "sku-my-sub-id"],
});
alert("items: " + JSON.stringify(items));
const products = await getProductsAsync(items);
alert("products: " + JSON.stringify(products));
if (products.results.length > 0) {
alert("found products!");
await purchaseItemAsync("my-sub-id");
alert("done making payment!");
} else {
alert("no products..");
}
} catch (err) {
alert("error occured while trying to purchase: " + err);
}
};
In this case, getProductsAsync() does return something resembling the format the results should be. But it doesn't return any of the subscriptions I created (I copied the product ID value listed in that column and I supplied it to both getProductsAsync and purchaseItemAsync. I also supplied the url version which basically just has a prefix of sku-:
I also enabled licensing testing for the email I'm using in Google Play:
Do note that I'm uploading the .aab file to Google Play on the internal testing track then I install it using this URL format: https://play.google.com/apps/test/com.myname.appname/versionNumber
But when I open that link, it seems like google play is detecting it as an old version even though its the latest one. The changes I've made shows up though so I'm pretty sure that's the correct install URL.
What else could I be missing?
For anyone having the same problem. all you have to do is add this on your android/app/src/main/AndroidManifest.xml file:
<uses-permission android:name="com.android.vending.BILLING" />
It wasn't mentioned in the docs at the time of this post, and it doesn't get automatically added when you install a module. Might help save you the headache if you assume the same is true for all Expo modules.

rn-fetch-blob actionViewIntent() Does not work on Android 8.1 phones?

code
import RNFetchBlob from 'rn-fetch-blob';
RNFetchBlob.android
.actionViewIntent(
'/storage/emulated/0/Android/data/aaa.bbb.ccc/files/184.apk',
'application/vnd.android.package-archive',
)
.then(() => {
console.log('success');
})
.catch(err => {
console.log('error');
});
In the simulator, the above code works normally, and pops up the installation APK interface
On the phone (Android 8.1), the screen flashed white, then there was nothing, and the installation interface could not pop up, No error message
you should add permission in the AndroidMainFest.xml:
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
but because it is dynamic permission, I suggest you every time before you download and install APK to check it if it has permission.
In this situation, you can write a native module, for dynamic check permission you can see this answer after it goes to the permission set page
you can also use the react-native-permission library.
requestInstallUpdate = async () => {
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.REQUEST_INSTALL_PACKAGES,
{
'title': 'Test App',
'message': 'Test App needs to install updates.'
}
)
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
console.log("You can now install updates")
return true;
} else {
console.log("App install permission denied")
return false;
}
} catch (err) {
console.warn(err)
return false;
}
}
then in your download method
let canInstall = await requestInstallUpdate()
if(canInstall){
//download apk
}
Found out the reason for this, it's a know bug of the library and has a PR waiting to be merged (no timeframe from the repo owner). Here is the link to the PR: https://github.com/joltup/rn-fetch-blob/pull/317
So basically this needs to be added to line 122-123 of file android/src/main/java/com/RNFetchBlob/RNFetchBlob.java:
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
If above is not working do to the below step: overwrite the 121 line in android/src/main/java/com/RNFetchBlob/RNFetchBlob.java:
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // 121 line
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); // 122 line

Permission always returns never_ask_again

Steps to replicate:
react-native init project
<add code below to the project(App.js component)>
react-native run-android
I called the function in onPress of a text component.
The permission request always returns never_ask_again even for the fresh app run.
async requestPermissions() {
// android 6.0 +
if (Platform.OS === 'android' && Platform.Version >= 23) {
try {
const granted = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION, {
'title': 'Let the access location',
'message': 'locate you.'
});
console.log('granted: ', granted);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
Alert.alert("Granted access", [{ text: "ok" }])
} else {
Alert.alert(
"can't access to GPS title",
"returned " + granted,
[
{ text: "ok" }
]
);
}
} catch (err) {
}
}
}
Even when the permissions is enabled from settings, still the never_ask_again is returned.
React Native Version: 0.55.2
React Version: 16.3.1
in app/build.gradle
targetSdkVersion 23
Thanks
One thing I missed was to add <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission> in AppManifest.xml

Categories

Resources