Open Arxi opened 8 years ago
Update: after installing latest crosswalk, the file picker button reacts and I can select a file, but it seems it returns empty object {}
in callback. I'll investigate some more
So, update: it seems the object returned in callback isn't empty, and thus ngf-select works as expected while using latest crosswalk.
I haven't found any answer to the question why the button doesn't do anything while not using crosswalk.
Which version of Crosswalk did you use? I'm trying with v2.1.0 and I'm getting a "Choose an action" popup with the message "No apps can perform this action"
Currently using v2.1.0 as well and everything seems to be in order. Have you used any accept
or ngf-accept
attributes? I think these might have an effect on the selection in the "Choose an action" popup.
Hi, I buld my Cordova App on Android:
now on my Android 4.4 with Crosswalk 22.52.561.4 the button work, but I have dialog:
Choose an action
-----------------
No apps can perform this action.
On Android 6.x -> nothing.... without crosswalk button worked fine... now only popup:
Choose an action
-----------------
open dialog was fixed with adding "cordova-plugin-file"
Were you able to fix this? On Android 6.x this migt be caused by ngf-file-upload not asking for permissions. I have not yet found a way to overcome this.
Hi @Arxi on Android 6.0+ you must ask permissions before click
(https://github.com/NeoLSN/cordova-plugin-android-permission)
Thanks @WuglyakBolgoink which permissions did you have to ask for?
I think this bug has to be solved in ng-file-upload itself. I have added
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<preference name="AndroidPersistentFileLocation" value="Compatibility" />
Also tried to install "cordova-plugin-file", nothing worked. Somehow permission diolag does not fire thus I am getting error
E/XWalkViewInternal: Unable to create Image File, please make sure permission 'WRITE_EXTERNAL_STORAGE' was added.
If I go to android settings-> myapp -> storage and manually enable it, then it works as expected.
Has anyone solved the problem? @WuglyakBolgoink answer is right but I do not want to control this myself on code just for android. My code works for ios, browser but not on android.
EDIT: I have tried also WuglyakBolgoink solution but it also does not help, permissions.hasPermission(permissions.WRITE_EXTERNAL_STORAGE,...) returns true, so still user has to go and manually change this setting.
As for the Android 6 permission problem, I haven't found any other way than to handle this manually. So in the end, I used this plugin: https://github.com/NeoLSN/cordova-plugin-android-permission
I also have cordova-plugin-file
and cordova-plugin-file-transfer
installed which I use for other purposes - it's possible it can affect this.
I have a method which checks whether the app has WRITE_EXTERNAL_STORAGE
permission, and if not, prompts user to grant it.
Here's my solution. Note: I haven't used it in production yet, it may contain bugs.
function requestPermission() {
if (!ionic.Platform.isAndroid()) {
return $q.when();
}
var deferred = $q.defer();
var permissionErrorCallback = function(reason) {
deferred.reject(reason);
};
var permissions = cordova.plugins.permissions;
permissions.hasPermission(
permissions.WRITE_EXTERNAL_STORAGE,
// hasPermission success
function(status) {
console.log("WRITE_EXTERNAL_STORAGE: " + status.hasPermission);
if (status.hasPermission) {
console.log("WRITE_EXTERNAL_STORAGE permission already granted, doing nothing");
deferred.resolve();
return;
}
// so we don't have the permission - request it from the user
permissions.requestPermission(
permissions.WRITE_EXTERNAL_STORAGE,
// requestPermission success
function(status) {
if(!status.hasPermission) {
permissionErrorCallback("Permission not granted");
} else {
deferred.resolve();
}
},
// requestPermission error. How can this happen?
function() {
permissionErrorCallback("requestPermission itself failed!");
}
);
},
// hasPermission error. How can this happen?
function() {
permissionErrorCallback("hasPermission itself failed!");
}
);
return deferred.promise;
}
Now, I have this method in my own service, mine is called fileService
. I can call it when convenient, for example when entering a controller which handles some files. But even more convenient is to use a directive which you can attach to the same element you have ngf-select
on. That way, the permission will be checked and requested (if needed) every time the button is rendered. Something like this:
angular
.module('YourModuleName')
.directive('fileUpload', fileUploadDirective);
/* @ngInject */
function fileUploadDirective(
lodash,
fileService,
notificationService
) {
var debouncedAskForPermission = lodash.debounce(askForPermission, 2000, { "leading" : true, "trailing" : false });
// check storage permissions and request them if needed
function askForPermission() {
fileService.requestPermission() // this is the call to the method described higher up
.then(function() {
console.log("Storage permissions OK");
})
.catch(function(reason) {
notificationService.showGenericToast("Please allow this app to manipulate your Storage to enable more functionality");
});
}
return {
restrict: 'EA',
link: function(scope, element, attrs, ctrl) {
// check storage permissions and request them if needed
debouncedAskForPermission();
}
};
}
And this is how the directive is used in template:
<button class="button button-block button-positive"
file-upload
ngf-select="generalTravel.storeFile($file, $invalidFiles, generalTravel.healthFileHolder)"
>
Upload Copy
</button>
So in conclusion, the directive just checks for the permission. If the app has the permission, it does nothing; if it doesn't, it prompts the user. If the user declines or something bad happens, it throws a toast - notificationService
is another of my services for showing various notifications to user.
I use ng-lodash for debouncing, so that the check is not done too often and the user is not flooded with requests for permission or toasts. This is vital especially if you plan to use multiple elements with this directive in one template. I guess you could create your own helper for debounce if you do not wish the whole lodash/underscore library.
@demirag
EDIT: I have tried also WuglyakBolgoink solution but it also does not help, permissions.hasPermission(permissions.WRITE_EXTERNAL_STORAGE,...) returns true, so still user has to go and manually change this setting. @Arxi
What the problem have you now? If you use Cordova -> install cordova-plugin-android-permission
plugin. Check in manifest READ-*/WRITE_EXTERNAL_STORAGE permissions. and do check before open file this permissions.
All work on my app.
I use the following code:
but I also tried
and many other variations.
The problem I can't get any response when tapping them on physical device (Android tablet) while using cordova/ionic - no dialog appears, no error in console, simply nothing.
When I try opening the Demo page from Chrome/Browser/Firefox on the same tablet, the file picker buttons work fine.
This is my setup:
I also noticed that simple
<input type="file" />
does not work in the webview - which seems to be an unresolved Android 4.4 issue. Could this be related?