{ "id": "171969", "key": "TIMOB-26238", "fields": { "issuetype": { "id": "1", "description": "A problem which impairs or prevents the functions of the product.", "name": "Bug", "subtask": false }, "project": { "id": "10153", "key": "TIMOB", "name": "Titanium SDK/CLI", "projectCategory": { "id": "10100", "description": "Titanium and related SDKs used in application development", "name": "Client" } }, "fixVersions": [], "resolution": { "id": "7", "description": "", "name": "Invalid" }, "resolutiondate": "2018-07-26T16:31:04.000+0000", "created": "2018-07-26T08:52:39.000+0000", "priority": { "name": "Critical", "id": "1" }, "labels": [ "Android8.0", "Permissions" ], "versions": [], "issuelinks": [], "assignee": { "name": "shossain", "key": "shossain", "displayName": "Shak Hossain", "active": false, "timeZone": "America/Los_Angeles" }, "updated": "2018-07-26T16:34:11.000+0000", "status": { "description": "The issue is considered finished, the resolution is correct. Issues which are closed can be reopened.", "name": "Closed", "id": "6", "statusCategory": { "id": 3, "key": "done", "colorName": "green", "name": "Done" } }, "components": [ { "id": "10202", "name": "Android", "description": "Android Platform" } ], "description": "I've made a four different ways to check and request storage permissions. One of them fails, combining *Ti.Android.hasPermission* and *Ti.filesystem.requestStoragePermissions*\r\n\r\nI attached the sample app. Special attention in tiapp.xml. The permission WRITE_EXTERNAL_STORAGE is declared explicitly in the android manifest section and the override property set to true.\r\n\r\nAfter each test, if you disable storage permissions manually from app settings page the log will be disconnected. For a correct testing:\r\n\r\nUninstall the app and build again.\r\n\r\nBehaviour:\r\n\r\n*First execution trace*\r\n\r\nCheck permissions with: Ti.Android.hasPermission\r\nRequesting permissions with: Ti.Filesystem.requestStoragePermissions\r\nhasStoragePermission\r\nTi.Android.hasPermission(\"android.permission.WRITE_EXTERNAL_STORAGE\"): false\r\nrequestFilesystemPermission\r\nTi.Filesystem.requestStoragePermissions\r\n\r\n[Prompt permission grant dialog] Allow\r\n\r\nrequestPermissionCallback\r\nPermission Filesystem permission granted.\r\nFinished\r\n\r\nOK -> Permission granted\r\n\r\nTrying again\r\n\r\nCheck permissions with: Ti.Android.hasPermission\r\nRequesting permissions with: Ti.Filesystem.requestStoragePermissions\r\nhasStoragePermission\r\nTi.Android.hasPermission(\"android.permission.WRITE_EXTERNAL_STORAGE\"): false\r\nrequestFilesystemPermission\r\nTi.Filesystem.requestStoragePermissions\r\n\r\nFAIL\r\n\r\n*Second execution trace*\r\n\r\nCheck permissions with: Ti.Android.hasPermission\r\nRequesting permissions with: Ti.Filesystem.requestStoragePermissions\r\nhasStoragePermission\r\nTi.Android.hasPermission(\"android.permission.WRITE_EXTERNAL_STORAGE\"): false\r\nrequestFilesystemPermission\r\nTi.Filesystem.requestStoragePermissions\r\n\r\nFAIL\r\n\r\nOther 3 combinations works fine:\r\n\r\n*Native method:*\r\n\r\nCheck permissions with: Ti.Android.hasPermission\r\nRequesting permissions with: Ti.Android.requestPermissions\r\n\r\nOK\r\n\r\n*Filesystem method:*\r\n\r\nCheck permissions with: Ti.Filesystem.hasStoragePermissions\r\nRequesting permissions with: Ti.Filesystem.requestStoragePermissions\r\n\r\nOK\r\n\r\n*Mixed method B:*\r\n\r\nCheck permissions with: Ti.Filesystem.hasStoragePermissions\r\nRequesting permissions with: Ti.Android.requestPermissions\r\n\r\nOK", "attachment": [ { "id": "65388", "filename": "CameraExternalTest.js", "author": { "name": "jquick", "key": "jquick", "displayName": "Joshua Quick", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2018-07-26T16:28:23.000+0000", "size": 1268, "mimeType": "application/x-javascript" }, { "id": "65381", "filename": "PermissionTest.zip", "author": { "name": "jormagar", "key": "jormagar", "displayName": "Jorge Macias Garcia", "active": true, "timeZone": "Europe/Brussels" }, "created": "2018-07-26T08:46:33.000+0000", "size": 9206506, "mimeType": "application/zip" }, { "id": "65385", "filename": "test-result.txt", "author": { "name": "jormagar", "key": "jormagar", "displayName": "Jorge Macias Garcia", "active": true, "timeZone": "Europe/Brussels" }, "created": "2018-07-26T09:10:11.000+0000", "size": 5152, "mimeType": "text/plain" } ], "flagged": false, "summary": "Android: Storage-permissions issue on Android 8 (API 26+)", "creator": { "name": "jormagar", "key": "jormagar", "displayName": "Jorge Macias Garcia", "active": true, "timeZone": "Europe/Brussels" }, "subtasks": [], "reporter": { "name": "jormagar", "key": "jormagar", "displayName": "Jorge Macias Garcia", "active": true, "timeZone": "Europe/Brussels" }, "environment": "Ti SDK : 7.3.X\r\nAndroid Build Tools: 27.0.3\r\nExecuting App in a Samsung Galaxy S7 Android 8.0", "comment": { "comments": [ { "id": "439508", "author": { "name": "jquick", "key": "jquick", "displayName": "Joshua Quick", "active": true, "timeZone": "America/Los_Angeles" }, "body": "This is not a bug.\r\n\r\nThe {{Ti.Filesystem.requestStoragePermission()}} requests the {{READ_EXTERNAL_STORAGE}} permission. It does *+not+* request the {{WRITE_EXTERNAL_STORAGE}}.\r\nhttps://docs.appcelerator.com/platform/latest/#!/api/Titanium.Filesystem-method-requestStoragePermissions\r\n\r\nAndroid used to be lenient about this where if the end-user granted {{READ_EXTERNAL_STORAGE}} permission, your app would also be granted {{WRITE_EXTERNAL_STORAGE}} permission since they were both in the same permission group. But Google has changed this for apps which target Android 8.0 or higher, which Titanium 7.3.0 does by default now. Google documents this here...\r\nhttps://developer.android.com/about/versions/oreo/android-8.0-changes#rmp\r\n\r\nPlease see the attached [^CameraExternalTest.js]. You would not normally request permissions separately like this, but it proves that permission request/detection works. The point being, is if you want {{WRITE_EXTERNAL_STORAGE}}, you need to specifically request it.\r\n\r\nI hope this helps.", "updateAuthor": { "name": "jquick", "key": "jquick", "displayName": "Joshua Quick", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2018-07-26T16:30:09.000+0000", "updated": "2018-07-26T16:30:09.000+0000" }, { "id": "439510", "author": { "name": "jormagar", "key": "jormagar", "displayName": "Jorge Macias Garcia", "active": true, "timeZone": "Europe/Brussels" }, "body": "It's clear! Thanks.", "updateAuthor": { "name": "jormagar", "key": "jormagar", "displayName": "Jorge Macias Garcia", "active": true, "timeZone": "Europe/Brussels" }, "created": "2018-07-26T16:34:11.000+0000", "updated": "2018-07-26T16:34:11.000+0000" } ], "maxResults": 3, "total": 3, "startAt": 0 } } }