3

Kit-Kat issue can't write to external SD card,

As mentioned in Goolge Document To simplify your code on devices running KITKAT or earlier, you can use fromFile(File) which emulates the behavior of a DocumentsProvider The code below (New API) works for Lollipop but how to use the new API for kitkat ?

Also look at Kit-Kat issue (New API)

public class MyActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_my);
    Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
    startActivityForResult(intent, 42);
}

public void onActivityResult(int requestCode, int resultCode, Intent resultData) {
    if (resultCode == RESULT_OK) {
        Uri treeUri = resultData.getData();
        DocumentFile pickedDir = DocumentFile.fromFile(new File("/mnt/extSdCard/Test"));

        // List all existing files inside picked directory
        for (DocumentFile file : pickedDir.listFiles()) {
            Log.d("Tag", "Found file " + file.getName() + " with size " + file.length());
        }

        // Create a new file and write into it
        DocumentFile newFile = pickedDir.createFile("text/plain", "My Novel");
        OutputStream out = null;
        try {
            out = getContentResolver().openOutputStream(newFile.getUri());
            out.write("A long time ago...".getBytes());
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.my, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();
    if (id == R.id.action_settings) {
        return true;
    }
    return super.onOptionsItemSelected(item);
}
}

How to use fromFile(File) ?

I tried but says Failed to createFile: java.io.IOException: open failed: EACCES (Permission denied)

Even after adding the permission uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"

Android version 4.4.2

 protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_my);

    DocumentFile pickedDir = DocumentFile.fromFile(new File("/mnt/extSdCard/Test"));

    // List all existing files inside picked directory
    for (DocumentFile file : pickedDir.listFiles()) {
        Log.d("Tag", "Found file " + file.getName() + " with size " + file.length());
    }

    // Create a new file and write into it
    DocumentFile newFile = pickedDir.createFile("text/plain", "My Novel");
    OutputStream out = null;
    try {

        //Says NullPointerException
        out = getContentResolver().openOutputStream(newFile.getUri());                             out.write("A long time ago...".getBytes());
        out.close();
    } catch (Exception e) {
        e.printStackTrace();
    }        
}
Shivaraj Patil
  • 8,186
  • 4
  • 29
  • 56

1 Answers1

5

The new API only helps people on Lollipop to write to the secondary sdcard, people on KitKat are still out of luck.

DocumentFile.fromFile(...)

This doesn't give you any additional access to the underlying files beyond what your app already has.

To leverage the new permissions created by Intent.ACTION_OPEN_DOCUMENT_TREE you have to use the Uri returned by with DocumentFile.fromTreeUri

Community
  • 1
  • 1
darken
  • 807
  • 12
  • 25
  • I actually have this permission, but for some reason, calling DocumentFile.fromFile(context,file).delete(); will always fail for me. – android developer Sep 05 '15 at 22:48
  • As far as I know, "doesn't give you any additional access" still holds true . If you have been given URI access to a full storage, and want File -> DocumentFile, you'll have to do some painfull URI building based on the tree uri you have access to and then created a DocumentFile from that. Look into the DocumentFile source code and look at the differences in URIs returned by FilePicker / Helper methods etc. – darken Sep 05 '15 at 23:37
  • Why is it this way? And isn't this function considered useless because of this? You mean to tell me that I would need to traverse the file-tree for this? – android developer Sep 06 '15 at 05:13
  • I find it crazy too, but afaik this is what's available... Either traverse the tree or lookup AOSP code and make a function that constructs a working DocumentFile (it's possible, just very hacky). – darken Sep 06 '15 at 15:13
  • It's just that many related functions about it are already quite a workaround. Just have a look at this code: https://github.com/jeisfeld/Augendiagnose/blob/master/AugendiagnoseLib/src/de/jeisfeld/augendiagnoselib/util/imagefile/FileUtil.java – android developer Sep 06 '15 at 22:05
  • I know it's frustrating, but I can't change that :). Mail me if you want to chat about this. Nice link, looks similar to my methods. Traversing the uri root as fallback is a nice touch. I build my methods mostly from AOSP code (ExternalStorageProvider and AOSP file picker). – darken Sep 06 '15 at 22:32
  • When I grow up, I wish I would be able to understand most Google developer's decisions. – Luis A. Florit Oct 26 '15 at 17:31