I'm struggling to find out what's going on with my code. This code snippet works on EVERY (apparently) phone, except motorola (Moto G, etc...):
private void createFolder(String folderPath) throws CantCreateFolderPathException {
File folder = new File(folderPath);
if (folder.mkdirs() || folder.isDirectory())
return; //Everything ok!
throw new CantCreateFolderPathException(folderPath);
}
And I generate the folder path with this:
public String getFolderPath(Courseware courseware) {
String path = getBestPath() + courseware.getSubject().getName() + File.separator;
UnisantaApplication.Log_i("SAVE PATH:" + path);
return path;
//Result example: sd/unisantaapp/material/SUBJECT NAME/
}
private String getBestPath() {
if (isExternalStorageWritable())
return getExternalPath();
return getInternalPath();
}
private String getExternalPath() {
return Environment.getExternalStorageDirectory()
.getAbsolutePath() + File.separator +
"unisantaapp" + File.separator +
"material" + File.separator;
}
private String getInternalPath() {
return UnisantaApplication.getInstance().getApplicationContext()
.getFilesDir().getAbsolutePath() + File.separator +
"material" + File.separator;
}
folder.mkdirs
keeps returning false, which causes CantCreateFolderPathException
to be thrown. AGAIN, it works on all other phones that I've tested, so probably it's not a permission manifest missing:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="si.unisanta.tcc.unisantaapp" >
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application
[...]
I asked for help from a friend of mine, since I don't have a motorola. I created a APK with some dialogs to help me understand the error, my steps were:
Find out which path is the "best one" generated from my code: getBestPath returns ExternalStorageDirectory, but mkdirs keeps returning false
Tried to change getBestPath to always returns internal path, then mkdirs returned true! At this path:
But my friend claims that he can't open the file nor find it with another third-party file explorer. When he tries to open a PDF, it says:"Impossible to view PDF" and the file explorer says: "superuser not available".
Frustrated with no clue of what's happening, I took a step back reverting my getBestPath method to work as expected and changed the call for folder.mkdirs()
to Files.createParentDirs(folder)
hoping for some more descriptive error, but instead I just received a simple:
Well, why I can't create folder/file and open it JUST IN MOTOROLA PHONES? Anyone here already faced this? Any clues of what I'm doing wrong?
As @CommonsWare pointed, it's not a MOTOROLA issue, but an Android 6.0 one. I just added support to ask for permissions (runtime) and also read the article suggested (Great article, really worth it).
I just added the following in my activity:
private boolean hasPermissionToDownload() {
int permissionResult = ContextCompat.checkSelfPermission(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE);
return permissionResult == PackageManager.PERMISSION_GRANTED;
}
private void explainOrAskPermission() {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
new AlertDialog.Builder(this)
.setTitle(R.string.download_permission_explain_title)
.setMessage(getString(R.string.download_permission_explain_message))
.setNeutralButton(R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
askPermission();
}
})
.show();
}
else {
askPermission();
}
}
private void askPermission() {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
PERMISSION_SAVE_DOWNLOAD_REQUEST);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == PERMISSION_SAVE_DOWNLOAD_REQUEST) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
downloadCourseware(lastCoursewareClicked);
}
else {
new AlertDialog.Builder(this)
.setTitle(R.string.download_permission_denied_title)
.setMessage(R.string.download_permission_denied_message)
.setNeutralButton(R.string.ok, null)
.show();
}
}
}