/* Ċ Ġ* ĠĠ Ġ____ ĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ_ ĠĠ Ġ__ ___ Ġ_ Ġ_ ĠĠĠĠ Ġ__ Ġ Ġ__ Ċ Ġ* Ġ Ġ| Ġ Ġ_ Ġ\ Ġ Ġ___ ĠĠ Ġ___ Ġ_ ĠĠ Ġ_ Ġ_ Ġ__ Ġ___ ĠĠ Ġ___ Ġ_ Ġ__ Ġ| Ġ|_| Ġ Ġ___ (_) Ġ| Ġ___ \ Ġ\/ Ġ/ Ċ Ġ* Ġ Ġ| Ġ| Ġ| Ġ| / Ġ_ Ġ\ Ġ/ Ġ__ | Ġ| Ġ| Ġ| Ġ'_ Ġ` Ġ_ Ġ\ Ġ/ Ġ_ Ġ\ Ġ'_ Ġ\| Ġ__ | Ġ|_ Ġ Ġ| Ġ| Ġ| / Ġ_ Ġ\\ Ġ Ġ/ Ċ Ġ* Ġ Ġ| Ġ|_| Ġ| Ġ(_) Ġ| Ġ(__ | Ġ|_| Ġ| Ġ| Ġ| Ġ| Ġ| Ġ| Ġ Ġ__ / Ġ| Ġ| Ġ| Ġ|_| Ġ Ġ_ | Ġ| Ġ| Ġ| Ġ Ġ__ // Ġ Ġ\ Ċ Ġ* Ġ Ġ| ____ / Ġ\ ___ / Ġ\ ___ |\ __, _| _| Ġ|_| Ġ|_ |\ ___ | _| Ġ|_ |\ __| _| ĠĠ Ġ|_| _ |\ ___ /_ / \_ \ Ċ Ġ* Ċ Ġ* ĠĠĠĠ ĠCopyright Ġ 2 0 2 0 Ġtom 5 0 7 9 Ċ Ġ* Ċ Ġ* ĠĠĠĠ ĠLicensed Ġunder Ġthe ĠApache ĠLicense , ĠVersion Ġ 2 . 0 Ġ( the Ġ" License "); Ċ Ġ* ĠĠĠĠ Ġyou Ġmay Ġnot Ġuse Ġthis Ġfile Ġexcept Ġin Ġcompliance Ġwith Ġthe ĠLicense . Ċ Ġ* ĠĠĠĠ ĠYou Ġmay Ġobtain Ġa Ġcopy Ġof Ġthe ĠLicense Ġat Ċ Ġ* Ċ Ġ* ĠĠĠĠĠĠĠĠ Ġhttp :// www . apache . org / licenses / LICENSE - 2 . 0 Ċ Ġ* Ċ Ġ* ĠĠĠĠ ĠUnless Ġrequired Ġby Ġapplicable Ġlaw Ġor Ġagreed Ġto Ġin Ġwriting , Ġsoftware Ċ Ġ* ĠĠĠĠ Ġdistributed Ġunder Ġthe ĠLicense Ġis Ġdistributed Ġon Ġan Ġ" AS ĠIS " ĠBASIS , Ċ Ġ* ĠĠĠĠ ĠWITHOUT ĠWARRANTIES ĠOR ĠCONDITIONS ĠOF ĠANY ĠKIND , Ġeither Ġexpress Ġor Ġimplied . Ċ Ġ* ĠĠĠĠ ĠSee Ġthe ĠLicense Ġfor Ġthe Ġspecific Ġlanguage Ġgoverning Ġpermissions Ġand Ċ Ġ* ĠĠĠĠ Ġlimitations Ġunder Ġthe ĠLicense . Ċ Ġ*/ Ċ Ċ @ file : SuppressWarnings (" unused ") Ċ Ċ package Ġxyz . qu aver . io . util Ċ Ċ import Ġandroid . annotation . Suppress Lint Ċ import Ġandroid . content . Content Resolver Ċ import Ġandroid . content . Context Ċ import Ġandroid . content . Intent Ċ import Ġandroid . content . pm . PackageManager Ċ import Ġandroid . net . Uri Ċ import Ġandroid . os . Build Ċ import Ġandroid . os . storage . Storage Manager Ċ import Ġandroid . os . storage . Storage Volume Ċ import Ġandroid . provider . Documents Contract Ċ import Ġandroidx . annotation . Requires Api Ċ import Ġandroidx . core . content . Context Compat Ċ import Ġandroidx . core . database . getString OrNull Ċ import Ġjava . io . File Ċ import Ġjava . lang . reflect . Array Ċ Ċ const Ġval ĠPATH _ DOCUMENT Ġ= Ġ" document " Ċ const Ġval ĠPATH _ TREE Ġ= Ġ" tree " Ċ Ċ const Ġval ĠURL _ SL ASH Ġ= Ġ"% 2 F " Ċ const Ġval ĠURL _ COL ON Ġ= Ġ"% 3 A " Ċ Ċ val ĠUri ?. is External Storage Document : ĠBoolean ĊĠĠĠ Ġget () Ġ= Ġthis ?. authority Ġ== Ġ" com . android . external storage . documents " Ċ Ċ val ĠUri ?. is Downloads Document : ĠBoolean ĊĠĠĠ Ġget () Ġ= Ġthis ?. authority Ġ== Ġ" com . android . providers . downloads . documents " Ċ Ċ val ĠUri ?. is Media Document : ĠBoolean ĊĠĠĠ Ġget () Ġ= Ġthis ?. authority Ġ== Ġ" com . android . providers . media . documents " Ċ Ċ val ĠUri ?. is Content Uri : ĠBoolean ĊĠĠĠ Ġget () Ġ= Ġthis ?. scheme Ġ== ĠContent Resolver . SCHEME _ CONTENT Ċ val ĠUri ?. isFile Uri : ĠBoolean ĊĠĠĠ Ġget () Ġ= Ġthis ?. scheme Ġ== ĠContent Resolver . SCHEME _ FILE Ċ Ċ val ĠUri . tree Document Id : ĠString ? ĊĠĠĠ Ġget () Ġ= Ġthis . path Segments . let Ġ{ Ġpaths Ġ-> ĊĠĠĠĠĠĠĠ Ġif Ġ( paths . size Ġ>= Ġ 2 Ġ&& Ġpaths [ 0 ] Ġ== ĠPATH _ TREE ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpaths [ 1 ] ĊĠĠĠĠĠĠĠ Ġelse ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnull ĊĠĠĠ Ġ} Ċ Ċ val ĠUri . is Tree Uri : ĠBoolean ĊĠĠĠ Ġget () Ġ= Ġthis . tree Document Id Ġ!= Ġnull Ċ Ċ val ĠUri . document Id : ĠString ? ĊĠĠĠ Ġget () Ġ= Ġthis . path Segments . let Ġ{ Ġpaths Ġ-> ĊĠĠĠĠĠĠĠ Ġif Ġ( paths . size Ġ>= Ġ 2 Ġ&& Ġpaths [ 0 ] Ġ== ĠPATH _ DOCUMENT ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpaths [ 1 ] ĊĠĠĠĠĠĠĠ Ġelse Ġif Ġ( paths . size Ġ>= Ġ 4 Ġ&& Ġpaths [ 0 ] Ġ== ĠPATH _ TREE Ġ&& Ġpaths [ 2 ] Ġ== ĠPATH _ DOCUMENT ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpaths [ 3 ] ĊĠĠĠĠĠĠĠ Ġelse ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnull ĊĠĠĠ Ġ} Ċ Ċ val ĠUri . is Document Uri : ĠBoolean ĊĠĠĠ Ġget () Ġ= Ġthis . document Id Ġ!= Ġnull Ċ Ċ val ĠUri . is Root : ĠBoolean ĊĠĠĠ Ġget () Ġ= Ġthis . nice Document Id ?. split (': ') ?. get OrNull ( 1 ). isNull Or Blank () Ċ Ċ /** Ċ Ġ* ĠReturns Ġthe Ġsegment ed ĠDocument ID Ċ Ġ* Ċ Ġ* Ġ### ĠExample Ċ Ġ* Ġ` 1 A 1 9 - 3 B 8 9 : Android / data ` Ċ Ġ* Ġreturns Ġ`[" 1 A 1 9 - 3 B 8 9 ", Ġ" Android / data "]` Ċ Ġ*/ Ċ internal Ġval ĠString . document Id Segments : ĠList < String > ĊĠĠĠ Ġget () Ġ= Ġthis . split (": ") Ċ Ċ val ĠUri . document Id Segment : ĠList < String >? ĊĠĠĠ Ġget () Ġ= Ġthis . nice Document Id ?. document Id Segments Ċ Ċ /** Ċ Ġ* ĠReturns Ġthe Ġroot Ġof Ġthe ĠUri Ċ Ġ* Ċ Ġ* Ġ### ĠExample Ċ Ġ* Ġ` 1 A 1 9 - 3 B 8 9 : Android / data ` Ċ Ġ* Ġreturns Ġ`" 1 A 1 9 - 3 B 8 9 "` Ċ Ġ*/ Ċ internal Ġval ĠString . volume Id : ĠString ? ĊĠĠĠ Ġget () Ġ= Ġthis . document Id Segments . first OrNull () Ċ Ċ val ĠUri . volume Id : ĠString ? ĊĠĠĠ Ġget () Ġ= Ġthis . nice Document Id ?. volume Id Ċ Ċ /** Ċ Ġ* ĠReturns Ġa Ġpath Ġof Ġthe Ġgiven ĠDocument ID Ċ Ġ* Ċ Ġ* Ġ### ĠExample Ċ Ġ* Ġ` 1 A 1 9 - 3 B 8 9 : Android / data ` Ċ Ġ* Ġreturns Ġ` Android / data ` Ċ Ġ*/ Ċ internal Ġval ĠString . document Id Path : ĠString ? ĊĠĠĠ Ġget () Ġ= Ġthis . document Id Segments . get OrNull ( 1 ) Ċ Ċ val ĠUri . document Id Path : ĠString ? ĊĠĠĠ Ġget () Ġ= Ġthis . nice Document Id ?. document Id Path Ċ Ċ /** Ċ Ġ* ĠReturns Ġa Ġsegment ed Ġpath Ġof Ġthe Ġgiven ĠDocument ID Ċ Ġ* Ċ Ġ* Ġ### ĠExample Ċ Ġ* Ġ` 1 A 1 9 - 3 B 8 9 : Android / data ` Ċ Ġ* Ġreturns Ġ`[" Android ", Ġ" data "]` Ċ Ġ*/ Ċ internal Ġval ĠString . document Id Path Segments : ĠList < String >? ĊĠĠĠ Ġget () Ġ= Ġthis . document Id Path ?. split ('/') Ċ Ċ val ĠUri ?. document Id Path Segments : ĠList < String >? ĊĠĠĠ Ġget () Ġ= Ġthis ?. nice Document Id ?. document Id Path Segments Ċ Ċ /** Ċ Ġ* ĠReturns Ġa Ġnew ĠDocument ĠID Ġaccording Ġto Ġthe Ġgiven Ġparameters Ċ Ġ* Ċ Ġ* Ġ@ param Ġ[ volume Id ] ĠRoot Ġof Ġthe ĠURI Ċ Ġ* Ġ@ param Ġ[ path ] ĠPath Ġunder Ġthe Ġroot Ċ Ġ* Ċ Ġ* Ġ@ return ĠDocument ID Ġstring Ċ Ġ*/ Ċ fun Ġcreate New Document Id ( volume Id : ĠString , Ġpath : ĠString ) Ġ= ĊĠĠĠ Ġ"$ volume Id :$ path " Ċ Ċ val ĠUri ?. nice Document Id : ĠString ? ĊĠĠĠ Ġget () Ġ= Ġthis ?. document Id Ġ?: Ġthis ?. tree Document Id Ċ Ċ /** Ċ Ġ* ĠReturns Ġa Ġchild ĠUri Ġwith Ġa Ġgiven Ġfilename Ċ Ġ* Ċ Ġ* ĠOnly Ġworks Ġwhen Ġthe ĠUri Ġis Ġexternal Ġstorage Ġdocument . Ċ Ġ* Ċ Ġ* Ġ@ see ĠUri . is External Storage Document Ċ Ġ*/ Ċ @ Requires Api ( 2 1 ) Ċ fun ĠUri . getChild Uri ( context : ĠContext , Ġchild : ĠString ): ĠUri ? Ġ{ ĊĠĠĠ Ġif Ġ(! this . is Tree Uri ) ĊĠĠĠĠĠĠĠ Ġreturn Ġnull ĊĊĠĠĠ Ġreturn Ġif Ġ( this . is External Storage Document ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġchild Document Id Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( this . is Root ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"${ this . volume Id }:${ child }" ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"${ this . nice Document Id }/ $ child " ĊĊĠĠĠĠĠĠĠ ĠDocuments Contract . build Document Uri Using Tree ( this , Ġchild Document Id ) ĊĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġchild Uri Ġ= ĠDocuments Contract . build Child Documents Uri Using Tree ( this , Ġnice Document Id ) ĊĊĠĠĠĠĠĠĠ Ġcontext . content Resolver . query ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġchild Uri , ĊĠĠĠĠĠĠĠĠĠĠĠ ĠarrayOf ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠDocuments Contract . Document . COLUMN _ DOCUMENT _ ID , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠDocuments Contract . Document . COLUMN _ DISPLAY _ NAME ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnull , Ġnull , Ġnull ĊĠĠĠĠĠĠĠ Ġ). use Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhile Ġ( it ?. moveTo Next () Ġ== Ġtrue ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( it . getString OrNull ( it . getColumnIndex ( Documents Contract . Document . COLUMN _ DISPLAY _ NAME )) Ġ== Ġchild ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĠDocuments Contract . build Document Uri Using Tree ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthis , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . getString ( it . getColumnIndex ( Documents Contract . Document . COLUMN _ DOCUMENT _ ID )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġreturn Ġnull ĊĠĠĠ Ġ} Ċ } Ċ Ċ /** Ċ Ġ* ĠReturns Ġa ĠUri Ġthat Ġpoints Ġa Ġfile Ġwith Ġa Ġgiven Ġfilename Ġin Ġthe Ġsame Ġdirectory Ċ Ġ* Ċ Ġ* ĠOnly Ġworks Ġwhen Ġthe ĠUri Ġis Ġexternal Ġstorage Ġdocument . Ċ Ġ* Ċ Ġ* Ġ@ see ĠUri . is External Storage Document Ċ Ġ*/ Ċ @ Requires Api ( 2 1 ) Ċ fun ĠUri . get Neighbor Uri ( filename : ĠString ): ĠUri Ġ{ ĊĠĠĠ Ġif Ġ(! this . is External Storage Document ) ĊĠĠĠĠĠĠĠ Ġthrow ĠUnsupportedOperationException (" Only ĠExternal ĠStorage ĠDocument ĠUri Ġis Ġallowed ") ĊĊĠĠĠ Ġval Ġneighbor Document Id Ġ= Ġthis . document Id Path Segments !!. let Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( it . isEmpty ()) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠlistOf ( filename ) ĊĠĠĠĠĠĠĠ Ġelse ĊĠĠĠĠĠĠĠĠĠĠĠ Ġit . to Mutable List (). apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthis [ last Index ] Ġ= Ġfilename ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ}. join ToString ("/") ĊĊĠĠĠ Ġreturn ĠDocuments Contract . build Document Uri Using Tree ( ĊĠĠĠĠĠĠĠ Ġthis , ĊĠĠĠĠĠĠĠ Ġcreate New Document Id ( volume Id !! , Ġneighbor Document Id ) ĊĠĠĠ Ġ) Ċ } Ċ Ċ @ Requires Api ( Build . VERSION _ CODES . KIT K AT ) Ċ fun ĠUri . getName ( context : ĠContext ): ĠString ? Ġ{ ĊĠĠĠ Ġreturn Ġwhen Ġ{ ĊĠĠĠĠĠĠĠ Ġthis . is External Storage Document Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthis . document Id Path Segments ?. let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( it . isNotEmpty ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . last () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġthis . is Tree Uri Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġquery < String >( context , ĠDocuments Contract . Document . COLUMN _ DISPLAY _ NAME ) ĊĠĠĠĠĠĠĠ Ġelse Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnull ĊĠĠĠ Ġ} Ċ } Ċ Ċ val ĠUri . extension : ĠString ? ĊĠĠĠ Ġget () Ġ= Ġthis . document Id Path Segments ?. last ()?. split ('.') ?. let Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( it . size Ġ>= Ġ 2 ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġit . last () ĊĠĠĠĠĠĠĠ Ġelse ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnull ĊĠĠĠ Ġ} Ċ Ċ inline Ġfun Ġ< re ified ĠT > ĠUri . query ( context : ĠContext , ĠcolumnName : ĠString ): ĠT ? Ġ{ ĊĠĠĠ Ġreturn Ġkotlin . run Catch ing Ġ{ ĊĠĠĠĠĠĠĠ Ġcontext . content Resolver . query ( this , ĠarrayOf ( columnName ), Ġnull , Ġnull , Ġnull )?. use Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( it . moveTo First ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ( T :: class ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠString :: class Ġ-> Ġit . getString ( 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠInt :: class Ġ-> Ġit . getInt ( 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLong :: class Ġ-> Ġit . getLong ( 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠFloat :: class Ġ-> Ġit . get Float ( 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠDouble :: class Ġ-> Ġit . getDouble ( 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠShort :: class Ġ-> Ġit . get Short ( 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠByteArray :: class Ġ-> Ġit . get Blob ( 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġas ĠT ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġnull ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ}. get OrNull () Ċ } Ċ Ċ val ĠUri . parent : ĠUri ĊĠĠĠ Ġ@ Requires Api ( 2 1 ) ĊĠĠĠ Ġget () Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ(! this . is Tree Uri ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠUnsupportedOperationException (" Only ĠTree ĠUri Ġis Ġallowed ") ĊĊĠĠĠĠĠĠĠ Ġval Ġparent Document Id Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcreate New Document Id ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthis . volume Id !! , Ġthis . document Id Path Segments !! ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. drop Last ( 1 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. join ToString ("/") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠĠĠ Ġreturn ĠDocuments Contract . build Document Uri Using Tree ( this , Ġparent Document Id ) ĊĠĠĠ Ġ} Ċ Ċ fun ĠUri . write Text ( context : ĠContext , Ġstr : ĠString ) Ġ= ĊĠĠĠ Ġcontext . content Resolver . open OutputStream ( this )?. buffered Writer ()?. use Ġ{ Ġit . write ( str ) Ġ} Ċ Ċ fun ĠUri . read Text ( context : ĠContext ) Ġ= ĊĠĠĠ Ġcontext . content Resolver . open InputStream ( this )?. buffered Reader ()?. use Ġ{ Ġit . read Text () Ġ} Ċ Ċ @ Requires Api ( 1 9 ) Ċ fun ĠUri . exists ( context : ĠContext ): ĠBoolean Ġ{ ĊĠĠĠ Ġreturn Ġkotlin . run Catch ing Ġ{ ĊĠĠĠĠĠĠĠ Ġcontext . content Resolver . query ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthis , ĊĠĠĠĠĠĠĠĠĠĠĠ ĠarrayOf ( Documents Contract . Document . COLUMN _ DOCUMENT _ ID ), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnull , Ġnull , Ġnull ĊĠĠĠĠĠĠĠ Ġ) ?. use Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġit . count Ġ> Ġ 0 ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ}. get OrNull () Ġ?: Ġfalse Ċ } Ċ Ċ @ Requires Api ( 2 1 ) Ċ fun ĠUri . create ( context : ĠContext , ĠmimeType : ĠString , ĠdisplayName : ĠString ): ĠUri ? Ġ= ĊĠĠĠ ĠDocuments Contract . create Document ( context . content Resolver , Ġthis , ĠmimeType , ĠdisplayName ) Ċ Ċ @ Requires Api ( 1 9 ) Ċ fun ĠUri . delete ( context : ĠContext ) Ġ= ĊĠĠĠ ĠDocuments Contract . delete Document ( context . content Resolver , Ġthis ) Ċ Ċ internal Ġfun ĠInt . check Flag ( flag : ĠInt ) Ġ= ĊĠĠĠ Ġthis . and ( flag ) Ġ!= Ġ 0 Ċ Ċ internal Ġfun ĠUri . has Permission ( context : ĠContext ) Ġ= ĊĠĠĠ Ġcontext . check Calling Or Self Uri Permission ( ĊĠĠĠĠĠĠĠ Ġthis , ĊĠĠĠĠĠĠĠ ĠIntent . FLAG _ GRANT _ WRITE _ URI _ PERMISSION ĊĠĠĠ Ġ) Ġ== ĠPackage Manager . PERMISSION _ GRAN TED Ċ Ċ internal Ġfun Ġcan Read ( type : ĠString ?) Ġ= Ġtype ?. isNotEmpty () Ġ?: Ġfalse Ċ Ċ @ Requires Api ( 1 9 ) Ċ fun ĠUri . can Read ( context : ĠContext ): ĠBoolean Ġ{ ĊĠĠĠ Ġif Ġ(! this . has Permission ( context )) ĊĠĠĠĠĠĠĠ Ġreturn Ġfalse ĊĊĠĠĠ Ġval Ġtype Ġ= Ġkotlin . run Catch ing Ġ{ ĊĠĠĠĠĠĠĠ Ġcontext . content Resolver . query ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthis , ĊĠĠĠĠĠĠĠĠĠĠĠ ĠarrayOf ( Documents Contract . Document . COLUMN _ MIME _ TYPE ), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnull , Ġnull , Ġnull ĊĠĠĠĠĠĠĠ Ġ) ?. use Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( it . moveTo First ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . getString ( 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnull ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ}. get OrNull () ĊĊĠĠĠ Ġreturn Ġcan Read ( type ) Ċ } Ċ Ċ internal Ġfun Ġcan Write ( type : ĠString ?, Ġflags : ĠInt ?): ĠBoolean Ġ{ ĊĠĠĠ Ġtype Ġ?: Ġreturn Ġfalse ĊĠĠĠ Ġflags Ġ?: Ġreturn Ġfalse ĊĊĠĠĠ Ġif Ġ( type . isEmpty ()) ĊĠĠĠĠĠĠĠ Ġreturn Ġfalse ĊĊĠĠĠ Ġif Ġ( flags . check Flag ( Documents Contract . Document . FLAG _ SUPPORT S _ DELETE )) ĊĠĠĠĠĠĠĠ Ġreturn Ġtrue ĊĊĠĠĠ Ġif Ġ( type Ġ== ĠDocuments Contract . Document . MIME _ TYPE _ DIR ĊĠĠĠĠĠĠĠ Ġ&& Ġflags . check Flag ( Documents Contract . Document . FLAG _ DIR _ SUPPORT S _ CREATE ) ĊĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġreturn Ġtrue ĊĠĠĠ Ġif Ġ( flags . check Flag ( Documents Contract . Document . FLAG _ SUPPORT S _ WRITE )) ĊĠĠĠĠĠĠĠ Ġreturn Ġtrue ĊĊĠĠĠ Ġreturn Ġfalse Ċ } Ċ Ċ @ Requires Api ( 1 9 ) Ċ fun ĠUri . can Write ( context : ĠContext ): ĠBoolean Ġ{ ĊĠĠĠ Ġif Ġ(! this . has Permission ( context )) ĊĠĠĠĠĠĠĠ Ġreturn Ġfalse ĊĊĠĠĠ Ġval Ġ( type , Ġflags ) Ġ= Ġkotlin . run Catch ing Ġ{ ĊĠĠĠĠĠĠĠ Ġcontext . content Resolver . query ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthis , ĊĠĠĠĠĠĠĠĠĠĠĠ ĠarrayOf ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠDocuments Contract . Document . COLUMN _ MIME _ TYPE , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠDocuments Contract . Document . COLUMN _ FLAGS ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnull , Ġnull , Ġnull ĊĠĠĠĠĠĠĠ Ġ) ?. use Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( it . moveTo First ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠPair ( it . getString ( 0 ), Ġit . getInt ( 1 )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnull ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ}. get OrNull () Ġ?: Ġreturn Ġfalse ĊĊĠĠĠ Ġreturn Ġcan Write ( type , Ġflags ) Ċ } Ċ Ċ @ Requires Api ( 1 9 ) Ċ fun ĠUri . isDirectory ( context : ĠContext ): ĠBoolean Ġ{ ĊĠĠĠ Ġval Ġtype Ġ= Ġthis . query < String >( context , ĠDocuments Contract . Document . COLUMN _ MIME _ TYPE ) ĊĠĠĠĠĠĠĠ Ġ?: Ġreturn Ġfalse ĊĊĠĠĠ Ġreturn Ġtype Ġ== ĠDocuments Contract . Document . MIME _ TYPE _ DIR Ċ } Ċ Ċ @ Requires Api ( 1 9 ) Ċ fun ĠUri . lastModified ( context : ĠContext ) Ġ= ĊĠĠĠ Ġthis . query < Long >( context , ĠDocuments Contract . Document . COLUMN _ LAST _ MODI FIED ) Ċ Ċ @ Requires Api ( 1 9 ) Ċ fun ĠUri . length ( context : ĠContext ) Ġ= ĊĠĠĠ Ġthis . query < Long >( context , ĠDocuments Contract . Document . COLUMN _ SIZE ) Ċ Ċ @ Requires Api ( 2 1 ) Ċ fun ĠUri . list ( context : ĠContext ): ĠList < Uri > Ġ{ ĊĠĠĠ Ġif Ġ(! this . is Tree Uri ) ĊĠĠĠĠĠĠĠ Ġthrow ĠUnsupportedOperationException (" Only ĠTree ĠUri Ġis Ġallowed ") ĊĊĠĠĠ Ġval Ġchildren Ġ= ĠDocuments Contract . build Child Documents Uri Using Tree ( this , Ġthis . nice Document Id ) ĊĠĠĠ Ġval Ġresult Ġ= Ġmutable ListOf < String >() ĊĊĠĠĠ Ġkotlin . run Catch ing Ġ{ ĊĠĠĠĠĠĠĠ Ġcontext . content Resolver . query ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġchildren , ĊĠĠĠĠĠĠĠĠĠĠĠ ĠarrayOf ( Documents Contract . Document . COLUMN _ DOCUMENT _ ID ), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnull , Ġnull , Ġnull ĊĠĠĠĠĠĠĠ Ġ) ?. use Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhile Ġ( it . moveTo Next ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġresult . add ( it . getString ( 0 )) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġreturn Ġresult . map Ġ{ Ġchild Document Id Ġ-> ĊĠĠĠĠĠĠĠ ĠDocuments Contract . build Document Uri Using Tree ( this , Ġchild Document Id ) ĊĠĠĠ Ġ} Ċ } Ċ Ċ // ĠH uge Ġthanks Ġto Ġav lu is ( https :// github . com / av lu is ) Ċ // ĠThese Ġcodes Ġare Ġorigin ated Ġfrom ĠH ent oid ( https :// github . com / av lu is / H ent oid ) Ġunder ĠApache - 2 . 0 Ġlicense . Ċ private Ġconst Ġval ĠPRIMARY _ VOLUME _ NAME Ġ= Ġ" primary " Ċ Ċ // ĠCompat Ġfunctions Ċ private Ġval ĠContext . storage Manager : ĠStorage Manager ĊĠĠĠ Ġget () Ġ= Ġthis . getSystem Service ( Context . STORAGE _ SERVICE ) Ġas ĠStorage Manager Ċ Ċ private Ġval ĠStorage Manager . volume List Compat : ĠList < Storage Volume > ĊĠĠĠ Ġ@ Suppress Lint (" New Api ") ĊĠĠĠ Ġget () Ġ= Ġwhen Ġ( Build . VERSION . SDK _ INT ) Ġ{ ĊĠĠĠĠĠĠĠ Ġin Ġ 0 Ġuntil Ġ 2 1 Ġ-> Ġempty List () ĊĠĠĠĠĠĠĠ Ġin Ġ 2 4 Ġ.. ĠInt . MAX _ VALUE Ġ-> Ġthis . storage Volumes ĊĠĠĠĠĠĠĠ Ġelse Ġ-> Ġkotlin . run Catch ing Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġjava Class . getMethod (" get Volume List "). invoke ( this )?. let Ġ{ Ġarr Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ( 0 Ġuntil ĠArray . getLength ( arr )). map Ġ{ Ġi Ġ-> ĠArray . get ( arr , Ġi ) Ġas ĠStorage Volume Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ}. get OrNull () Ġ?: Ġempty List () ĊĠĠĠ Ġ} Ċ Ċ private Ġval ĠStorage Volume . directory Compat : ĠFile ? ĊĠĠĠ Ġget () Ġ= Ġif Ġ( Build . VERSION . SDK _ INT Ġ< Ġ 3 0 ) Ġjava Class . getMethod (" getPath File "). invoke ( this ) Ġas ĠFile ? ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġthis . directory Ċ Ċ /** Ċ Ġ* ĠGet Ġthe Ġhuman - readable Ġaccess Ġpath Ġfor Ġthe Ġgiven Ġvolume ĠID Ċ Ġ* Ċ Ġ* Ġ@ param Ġcontext Ġ ĠContext Ġto Ġuse Ċ Ġ* Ġ@ param Ġvolume ID ĠVolume ĠID Ġto Ġget Ġthe Ġpath Ġfrom Ċ Ġ* Ġ@ return ĠHuman - readable Ġaccess Ġpath Ġof Ġthe Ġgiven Ġvolume ĠID Ċ Ġ*/ Ċ @ Suppress Lint (" New Api ") Ċ private Ġfun Ġget Volume Path ( context : ĠContext , Ġvolume ID : ĠString ): ĠString ? Ġ{ ĊĠĠĠ Ġval Ġdoes Volume Id Match Ġ= Ġ{ Ġuuid : ĠString ?, Ġis Primary : ĠBoolean , Ġtree Volume ID : ĠString Ġ-> ĊĠĠĠĠĠĠĠ Ġ( uuid Ġ== Ġtree Volume ID . replace ("/", Ġ"")) Ġ|| Ġ( is Primary Ġ&& Ġtree Volume ID Ġ== ĠPRIMARY _ VOLUME _ NAME ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġreturn Ġcontext . storage Manager . volume List Compat . first OrNull Ġ{ ĊĠĠĠĠĠĠĠ Ġdoes Volume Id Match ( it . uuid , Ġit . is Primary , Ġvolume ID ) ĊĠĠĠ Ġ} ?. let Ġ{ Ġget Volume Path ( it ) Ġ} Ċ } Ċ Ċ /** Ċ Ġ* ĠReturns Ġthe Ġhuman - readable Ġaccess Ġpath Ġof Ġthe Ġroot Ġof Ġthe Ġgiven Ġstorage Ġvolume Ċ Ġ* Ċ Ġ* Ġ@ param Ġstorage Volume Ġandroid . os . storage . Storage Volume Ġto Ġreturn Ġthe Ġpath Ġfrom Ċ Ġ* Ġ@ return ĠHuman - readable Ġaccess Ġpath Ġof Ġthe Ġroot Ġof Ġthe Ġgiven Ġstorage Ġvolume ; Ġempty Ġstring Ġif Ġnot Ġfound Ċ Ġ*/ Ċ // ĠAccess Ġto ĠgetPath File Ġis Ġlimited Ġto ĠAPI < 3 0 Ċ private Ġfun Ġget Volume Path ( storage Volume : ĠStorage Volume ): ĠString ? Ġ{ ĊĠĠĠ Ġval Ġpath File Ġ= Ġstorage Volume . directory Compat Ġ?: Ġreturn Ġnull ĊĊĠĠĠ Ġval Ġpath Ġ= Ġpath File . path ĊĠĠĠ Ġval Ġabsolute Path Ġ= Ġpath File . absolute Path ĊĊĠĠĠ Ġreturn Ġwhen Ġ{ ĊĠĠĠĠĠĠĠ Ġpath . isEmpty () Ġand Ġabsolute Path . isEmpty () Ġ-> Ġpath File . canonical Path ĊĠĠĠĠĠĠĠ Ġpath . isEmpty () Ġ-> Ġabsolute Path ĊĠĠĠĠĠĠĠ Ġelse Ġ-> Ġpath ĊĠĠĠ Ġ} Ċ } Ċ Ċ fun Ġget FullPath From Tree Uri ( context : ĠContext , Ġuri : ĠUri ): ĠString ? Ġ{ ĊĠĠĠ Ġval Ġvolume Path Ġ= Ġget Volume Path ( context , Ġuri . volume Id Ġ?: Ġreturn Ġnull ). let Ġ{ ĊĠĠĠĠĠĠĠ Ġit Ġ?: Ġreturn ĠFile . separator ĊĊĠĠĠĠĠĠĠ Ġif Ġ( it . endsWith ( File . separator )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġit . drop Last ( 1 ) ĊĠĠĠĠĠĠĠ Ġelse ĊĠĠĠĠĠĠĠĠĠĠĠ Ġit ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġval Ġdocument Path Ġ= Ġuri . document Id Path ?. let Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( it . endsWith ( File . separator )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġit . drop Last ( 1 ) ĊĠĠĠĠĠĠĠ Ġelse ĊĠĠĠĠĠĠĠĠĠĠĠ Ġit ĊĠĠĠ Ġ} Ġ?: Ġreturn Ġnull ĊĊĠĠĠ Ġreturn Ġif Ġ( document Path . isNotEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( document Path . startsWith ( File . separator )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvolume Path Ġ+ Ġdocument Path ĊĠĠĠĠĠĠĠ Ġelse ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvolume Path Ġ+ ĠFile . separator Ġ+ Ġdocument Path ĊĠĠĠ Ġ} Ġelse ĊĠĠĠĠĠĠĠ Ġvolume Path Ċ } Ċ Ċ fun ĠUri . to File ( context : ĠContext ): ĠFile ? Ġ{ ĊĠĠĠ Ġreturn Ġwhen Ġ{ ĊĠĠĠĠĠĠĠ Ġthis . is External Storage Document Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġexternal Storage Root Ġ= Ġcontext . get External Storage Paths () ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġpath Ġ= Ġthis . document Id Path Ġ?: Ġreturn Ġnull ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ/* ĠFirst Ġtest Ġis Ġto Ġcompare Ġroot Ġnames Ġwith Ġknown Ġroots Ġof Ġremov able Ġmedia ĊĠĠĠĠĠĠĠĠ Ġ* ĠIn Ġmany Ġcases , Ġthe ĠSD Ġcard Ġroot Ġname Ġis Ġshared Ġbetween Ġpre - SA F Ġ( File ) Ġand ĠS AF Ġ( Document File ) Ġframeworks ĊĠĠĠĠĠĠĠĠ Ġ* Ġ( e . g . Ġ/ storage / 3 4 3 7 - 3 9 3 4 Ġvs . Ġ/ tree / 3 4 3 7 - 3 9 3 4 ) ĊĠĠĠĠĠĠĠĠ Ġ* ĠThis Ġis Ġwhat Ġthe Ġfollowing Ġblock Ġis Ġtrying Ġto Ġdo ĊĠĠĠĠĠĠĠĠ Ġ*/ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġexternal Storage Root . forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( it . substring After Last ( File . separator Char ). equals ( this . volume Id , Ġtrue )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĠFile ( it , Ġpath ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ/* ĠIn Ġsome Ġother Ġcases , Ġthere Ġis Ġno Ġcommon Ġname Ġ( e . g . Ġ/ storage / sd card 1 Ġvs . Ġ/ tree / 3 4 3 7 - 3 9 3 4 ) ĊĠĠĠĠĠĠĠĠ Ġ* ĠWe Ġcan Ġuse Ġa Ġslower Ġmethod Ġto Ġtranslate Ġthe ĠUri Ġobtained Ġwith ĠS AF Ġinto Ġa Ġpre - SA F Ġpath ĊĠĠĠĠĠĠĠĠ Ġ* Ġand Ġcompare Ġit Ġto Ġthe Ġknown Ġremov able Ġmedia Ġvolume Ġnames ĊĠĠĠĠĠĠĠĠ Ġ*/ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġroot Ġ= Ġget FullPath From Tree Uri ( context , Ġthis ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġexternal Storage Root . forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( root ?. startsWith ( it ) Ġ== Ġtrue ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĠFile ( root ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠFile ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠContext Compat . get External Files Dirs ( context , Ġnull ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. first (). canonical Path . substring Before Last ("/ Android / data "), Ġpath ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġthis . is Downloads Document Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ ĠFile ( this . document Id Segment ?. last () Ġ?: Ġreturn Ġnull ) ĊĠĠĠĠĠĠĠ Ġelse Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnull ĊĠĠĠ Ġ} Ċ }