-
-
Notifications
You must be signed in to change notification settings - Fork 8
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
file.read or file.readSync error: EACCES (Permission denied) #17
Comments
Hi, I've exactly the same problem. From the Download directory I can read a JPG file but not a PDF file (permission denied) Thanks |
I'm waiting for you to merge the PR pending fix NativeScript/NativeScript#9661 |
// REVIEW: Not sure why DocumentsContact is not there yet
type ProviderWithDocumentsContact = typeof android.provider & {
DocumentsContract: any;
};
// Per https://stackoverflow.com/questions/17546101/get-real-path-for-uri-android
export function getPathFromURI(uri: android.net.Uri) {
const getMediaFilePathForN = (uri: android.net.Uri, context: any) => {
let returnUri = uri;
let returnCursor = context
.getContentResolver()
.query(returnUri, null, null, null, null);
/*
* Get the column indexes of the data in the Cursor,
* * move to the first row in the Cursor, get the data,
* * and display it.
* */
let nameIndex = returnCursor.getColumnIndex(
android.provider.OpenableColumns.DISPLAY_NAME
);
let sizeIndex = returnCursor.getColumnIndex(
android.provider.OpenableColumns.SIZE
);
returnCursor.moveToFirst();
let name = returnCursor.getString(nameIndex);
let size = java.lang.Long.toString(returnCursor.getLong(sizeIndex));
let file = new java.io.File(context.getFilesDir(), name);
try {
let inputStream = context.getContentResolver().openInputStream(uri);
let outputStream = new java.io.FileOutputStream(file);
let read = 0;
let maxBufferSize = 1 * 1024 * 1024;
let bytesAvailable = inputStream.available();
//int bufferSize = 1024;
let bufferSize = Math.min(bytesAvailable, maxBufferSize);
let buffers = java.lang.reflect.Array.newInstance(
java.lang.Byte.class.getField('TYPE').get(null),
bufferSize
);
while ((read = inputStream.read(buffers)) != -1) {
outputStream.write(buffers, 0, read);
}
inputStream.close();
outputStream.close();
console.log('File Path', 'Path ' + file.getPath());
console.log('File Size', 'Size ' + file.length());
} catch (e) {
console.log('Exception', e);
}
return file.getPath();
};
const getDriveFilePath = (uri: android.net.Uri, context: any) => {
let returnUri = uri;
let returnCursor = context
.getContentResolver()
.query(returnUri, null, null, null, null);
/*
* Get the column indexes of the data in the Cursor,
* * move to the first row in the Cursor, get the data,
* * and display it.
* */
let nameIndex = returnCursor.getColumnIndex(
android.provider.OpenableColumns.DISPLAY_NAME
);
returnCursor.moveToFirst();
let name = returnCursor.getString(nameIndex);
let file = new java.io.File(context.getCacheDir(), name);
try {
let inputStream = context.getContentResolver().openInputStream(uri);
let outputStream = new java.io.FileOutputStream(file);
let read = 0;
let maxBufferSize = 1 * 1024 * 1024;
let bytesAvailable = inputStream.available();
//int bufferSize = 1024;
let bufferSize = Math.min(bytesAvailable, maxBufferSize);
let buffers = java.lang.reflect.Array.newInstance(
java.lang.Byte.class.getField('TYPE').get(null),
bufferSize
);
while ((read = inputStream.read(buffers)) != -1) {
outputStream.write(buffers, 0, read);
}
inputStream.close();
outputStream.close();
console.log('File Path', 'Path ' + file.getPath());
console.log('File Size', 'Size ' + file.length());
} catch (e) {
console.log('Exception', e);
}
return file.getPath();
};
const getDataColumn = (
context: any,
uri: android.net.Uri,
selection: any,
selectionArgs: any
) => {
let cursor = null;
const column = '_data';
const projection = [column];
try {
cursor = context
.getContentResolver()
.query(uri, projection, selection, selectionArgs, null);
if (cursor != null && cursor.moveToFirst()) {
let column_index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(column_index);
}
} catch (e) {
return getMediaFilePathForN(uri, context);
} finally {
if (cursor != null) cursor.close();
}
return null;
};
const isExternalStorageDocument = (uri: android.net.Uri) => {
return 'com.android.externalstorage.documents' === uri.getAuthority();
};
const isDownloadsDocument = (uri: android.net.Uri) => {
return 'com.android.providers.downloads.documents' === uri.getAuthority();
};
const isMediaDocument = (uri: android.net.Uri) => {
return 'com.android.providers.media.documents' === uri.getAuthority();
};
const isGooglePhotosUri = (uri: android.net.Uri) => {
return 'com.google.android.apps.photos.content' === uri.getAuthority();
};
const isGoogleDriveUri = (uri: android.net.Uri) => {
return (
'com.google.android.apps.docs.storage' === uri.getAuthority() ||
'com.google.android.apps.docs.storage.legacy' === uri.getAuthority()
);
};
const activity =
Application.android.startActivity || Application.android.foregroundActivity;
const context = activity.getApplicationContext();
const isKitKat = parseInt(Device.sdkVersion, 10) >= 19;
if (typeof uri === 'string') {
uri = android.net.Uri.parse(uri);
}
// DocumentProvider
if (
isKitKat &&
(<ProviderWithDocumentsContact>(
android.provider
)).DocumentsContract.isDocumentUri(context, uri)
) {
// ExternalStorageProvider
if (isExternalStorageDocument(uri)) {
const docId: string = (<ProviderWithDocumentsContact>(
android.provider
)).DocumentsContract.getDocumentId(uri);
const split = docId.split(':');
const type: string = split[0].toLowerCase();
if ('primary' === type) {
return (
android.os.Environment.getExternalStorageDirectory() + '/' + split[1]
);
} else {
// https://stackoverflow.com/questions/44226029/how-get-a-file-path-by-uri-which-authority-is-com-android-externalstorage-docum
let external = context.getExternalMediaDirs();
if (external.length > 0) {
let filePath = external[0].getAbsolutePath();
filePath =
filePath.substring(0, filePath.indexOf('Android')) + split[1];
return filePath;
}
return uri.getPath();
}
}
// DownloadsProvider
else if (isDownloadsDocument(uri)) {
if (parseInt(Device.sdkVersion, 10) >= 23) {
let cursor = null;
try {
cursor = context
.getContentResolver()
.query(
uri,
[android.provider.MediaStore.MediaColumns.DISPLAY_NAME],
null,
null,
null
);
if (cursor != null && cursor.moveToFirst()) {
let fileName = cursor.getString(0);
let path =
android.os.Environment.getExternalStorageDirectory().toString() +
'/Download/' +
fileName;
if (!android.text.TextUtils.isEmpty(path)) {
return path;
}
}
} finally {
if (cursor != null) cursor.close();
}
const id = (<ProviderWithDocumentsContact>(
android.provider
)).DocumentsContract.getDocumentId(uri);
if (!android.text.TextUtils.isEmpty(id)) {
if (id.startsWith('raw:')) {
return id.replace(/^raw:/, '');
}
const contentUriPrefixesToTry = [
'content://downloads/public_downloads',
'content://downloads/my_downloads'
];
for (let contentUriPrefix of contentUriPrefixesToTry) {
try {
let contentUri = android.content.ContentUris.withAppendedId(
android.net.Uri.parse(contentUriPrefix),
java.lang.Long.valueOf(id) as any
);
/* final Uri contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));*/
return getDataColumn(context, contentUri, null, null);
} catch (e) {
//In Android 8 and Android P the id is not a number
return uri
.getPath()
.replace(/^\/document\/raw:/, '')
.replace(/^raw:/, '');
}
}
}
} else {
const id: string = (<ProviderWithDocumentsContact>(
android.provider
)).DocumentsContract.getDocumentId(uri);
if (id.startsWith('raw:')) {
return id.slice(4);
} else {
const contentUri = android.content.ContentUris.withAppendedId(
android.net.Uri.parse('content://downloads/public_downloads'),
java.lang.Long.valueOf(id) as any
);
return getDataColumn(context, contentUri, null, null);
}
}
}
// MediaProvider
else if (isMediaDocument(uri)) {
const docId = (<ProviderWithDocumentsContact>(
android.provider
)).DocumentsContract.getDocumentId(uri);
const split = docId.split(':');
const type = split[0];
let contentUri = null;
if ('image' === type) {
contentUri =
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
} else if ('video' === type) {
contentUri =
android.provider.MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
} else if ('audio' === type) {
contentUri =
android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
} else {
return getMediaFilePathForN(uri, context);
}
const selection = '_id=?';
const selectionArgs = [split[1]]; // js Array?
return getDataColumn(context, contentUri, selection, selectionArgs);
} else if (isGoogleDriveUri(uri)) {
return getDriveFilePath(uri, context);
}
}
// MediaStore (and general)
else if ('content' === uri.getScheme().toLowerCase()) {
if (isGooglePhotosUri(uri)) {
return uri.getLastPathSegment();
}
if (isGoogleDriveUri(uri)) {
return getDriveFilePath(uri, context);
}
if (parseInt(Device.sdkVersion) === 24) {
// return getFilePathFromURI(context,uri);
return getMediaFilePathForN(uri, context);
// return getRealPathFromURI(context,uri);
} else {
return getDataColumn(context, uri, null, null);
}
}
// File
else if ('file' === uri.getScheme().toLowerCase()) {
return uri.getPath();
}
return null;
} @xpalacincreditoh I use this monstrosity for reading files for now. You might only need |
When I call: |
@xpalacincreditoh |
When I use your code I get an error with word type:
|
@xpalacincreditoh seems like you are using typescript code in a JS file? |
yes I use your solution of yesterday #17 (comment) I just realized it's TS and my code is JS. |
Good morning,
My system details:
When Open filepicker and select a PDF file from downloads folder the file.readSync sayas error:
And when call file.read says error:
This just happens only when targetSdkVersion is set to 30 and not in 29, but now to publish and app in Google App Store needs targetSdkVersion 30.
Thanks
The text was updated successfully, but these errors were encountered: