Android Question How to access the whole of external SD card?

Discussion in 'Android Questions' started by Inman, Feb 20, 2018.

  1. Inman

    Inman Well-Known Member Licensed User

    Ok. What about permission? Say I make the user select external SD card folder today with the above code. Will I be able to write into that folder, say 2 weeks from now, using a background service, without any user interaction?
     
  2. Erel

    Erel Administrator Staff Member Licensed User

    Updated code:
    Code:
    Sub Activity_Click
       
    Dim i As Intent
       i.Initialize(
    "android.intent.action.OPEN_DOCUMENT_TREE""")
       StartActivityForResult(i)
    End Sub

    Sub ion_Event (MethodName As String, Args() As Object) As Object
       
    If Args(0) = -1 Then 'resultCode = RESULT_OK
           Dim i As Intent = Args(1)
           
    Dim jo As JavaObject = i
           
    Dim treeUri As Uri = jo.RunMethod("getData"Null)
           
    Dim ctxt As JavaObject
           ctxt.InitializeContext
           
    Dim takeFlags As Int = Bit.And(i.Flags, 3)
           ctxt.RunMethodJO(
    "getContentResolver"Null).RunMethod("takePersistableUriPermission"Array(treeUri, takeFlags))
           
    Dim uri As String = treeUri 'ignore
           'uri should be a process global variable and you can save it
       End If
       
    Return Null
    End Sub

    Sub GetPickedDir (uri As StringAs JavaObject
       
    Dim ctxt As JavaObject
       ctxt.InitializeContext
       
    Dim DocumentFileStatic As JavaObject
       
    Dim treeUri As Uri
       treeUri.Parse(
    uri)
       
    Dim pickedDir As JavaObject = DocumentFileStatic.InitializeStatic("android.support.v4.provider.DocumentFile").RunMethod("fromTreeUri"Array(ctxt, treeUri))
       
    Return pickedDir
       
    'usage example of pickedDir
    '   Dim files() As Object = pickedDir.RunMethod("listFiles", Null)
    '   For Each f As JavaObject In files
    '       Log(f.RunMethod("getName", Null))
    '   Next
    '   Dim newFile As JavaObject = pickedDir.RunMethod("createFile", Array("text/plain", "My Novel"))
    '   Dim out As OutputStream = ctxt.RunMethodJO("getContentResolver", Null).RunMethod("openOutputStream", Array(newFile.RunMethod("getUri", Null)))
    '   Dim tw As TextWriter
    '   tw.Initialize(out)
    '   tw.Write("this is a test")
    '   tw.Close
    End Sub

    Sub StartActivityForResult(i As Intent)
       
    Dim jo As JavaObject = GetBA
       ion = jo.CreateEvent(
    "anywheresoftware.b4a.IOnActivityResult""ion"Null)
       jo.RunMethod(
    "startActivityForResult"Array As Object(ion, i))
    End Sub

    Sub GetBA As Object
       
    Dim jo As JavaObject
       
    Dim cls As String = Me
       cls = cls.SubString(
    "class ".Length)
       jo.InitializeStatic(cls)
       
    Return jo.GetField("processBA")
    End Sub
    You can save the uri string and use it later without requesting a new permission.
    Depends on ContentResolver and JavaObject libraries.
     
    Inman and DonManfred like this.
  3. Inman

    Inman Well-Known Member Licensed User

    Thank you so much, Erel. The permission is retained correctly, even after restarting emulator. Couple more requests.

    1. Just like how you opened an outputstream, how can I open an inputstream for a treeuri like in the above code so that I can use File.Copy2?

    2. How can I get the real path of a uri (for display purpose)? Currently when I print uri, I get (HierarchicalUri) content://com.android.externalstorage.documents/tree/17FC-3214%3Atff

    I then tried this
    Code:
    jo=treeUri
    Log(jo.RunMethod("getPath",Null))
    But it printed /tree/17FC-3214:tff. How can I get a path like /storage/17FC-3214/tff? I saw this stackoverflow post. Could you please take a look?

    https://stackoverflow.com/questions...th-from-uri-from-mediastore/10564727#10564727
    Code:
    private String getRealPathFromURI(Uri contentUri) 
    {
        
    String[] proj = { MediaStore.Images.Media.DATA };
        CursorLoader loader = new CursorLoader(mContext, contentUri, proj, null, null, null);
        Cursor cursor = loader.loadInBackground();
        int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        String result = cursor.getString(column_index);
        cursor.close();
        return result;
    }
     
  4. DonManfred

    DonManfred Expert Licensed User

  5. Inman

    Inman Well-Known Member Licensed User

    Thank you Don. I won't be using real path for any operation; just to show user the path he selected.

    Btw that code is throwing error on line Cursor1 = cr.Query(Uri1, Proj, "", Null, "")
    Code:
    java.lang.UnsupportedOperationException: Unsupported Uri content://com.android.externalstorage.documents/tree/17FC-3214%3Atff
    Google must have changed something is the 4 years that code was posted
     
  6. DonManfred

    DonManfred Expert Licensed User

    Create a new thread FOR ANY NEW QUESTION you have!
     
  7. Erel

    Erel Administrator Staff Member Licensed User

    Just replace "openOutputStream" with "openInputStream".
     
  8. Inman

    Inman Well-Known Member Licensed User

    What about the newFile javaobject that is passed with openOutputStream?
    Code:
    Dim newFile As JavaObject = pickedDir.RunMethod("createFile"Array("text/plain""My Novel"))
    What should I replace "createFile" with?
     
  9. Erel

    Erel Administrator Staff Member Licensed User

  10. Inman

    Inman Well-Known Member Licensed User

    Thanks for the all the help, Erel. I am posting the code I came up with as it may help someone someday. Please check this question I posted which is connected to this discussion.
    Code:
    Sub StreamFileCopier(dirsource As String,filesource As String,dirdest As String,filedest As String)

        
    Dim inp As InputStream,out As OutputStream
        
    Dim suri,duri As String
        
        
    Dim sctxt,dctxt,spickedDir,dpickedDir As JavaObject
            
        suri=dirsource
        spickedDir=GetPickedDir(suri)
        sctxt.InitializeContext
        
        duri=dirdest
        dpickedDir=GetPickedDir(duri)
        dctxt.InitializeContext
        
        
    Dim oldFile As JavaObject = spickedDir.RunMethod("findFile"Array(filesource))
        inp = sctxt.RunMethodJO(
    "getContentResolver"Null).RunMethod("openInputStream"Array(oldFile.RunMethod("getUri"Null)))
        
        
    Dim newFile As JavaObject = dpickedDir.RunMethod("createFile"Array("text/plain", filedest))
        out = dctxt.RunMethodJO(
    "getContentResolver"Null).RunMethod("openOutputStream"Array(newFile.RunMethod("getUri"Null)))
        
        
    File.Copy2(inp,out)
        out.Close
        
    End Sub
     
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice