App-specific files can be stored internally or externally (on the sd card) and the Android API helps you to find the appropriate directories.
Suche
HowtoCorrectlyStoreApp-SpecificFilesinAndroid
August30th,2012ByWolframRittmeyer
ChristopheVersieux(Waza_be)postedarantaboutandroiddevelopers'badhabittostorefilesdirectlyontherootofthesdcard.Icompletelyagreewiththepost.It'sbadusagetocreateapp-specificfoldersdirectlyattheroot.Ifyouinstallalotofapps,thesdcard'srootgetsclutteredfast.
Onecommentalsomentionedthatmosttutorialsdonotcovertheapp-specificfolders,soletmecorrectthatwithashorttutorialonhowtodoitcorrectly.
App-specificfilesvs.app-independentfiles
Ifyouneedtostorefilestherearegenerallytwousagetypes:
Appindependentdata
Appspecificdata
Iwillcoverbothtypesinmoredetailinthefollowingsections.ButinshortIwouldcharacterizethosetypesasfollows:App-specificfilesarethosethatonlyareusefulforaslongastheappisinstalled(e.g.ebooksinaproprietaryformat).App-independentfilesontheotherhandarethosethattheusercaresaboutregardlessofthespecificappthatcreatedthem(e.g.photos).
App-independentfiles
Thistypeofdataisstuffyouruserverylikelycaresabout,evenifyourappisnolongerinstalledonthedevice.Examplesarephotosshot,imagesprocessedorsketched,code-filesedited,audiofilesboughtandsoon.
Formostofthesetypes,Androidprovidesspecialdirectories.AfulllistofdirectoriesthatAndroidprovidesoutoftheboxcanbeseeninthedocumentationoftheEnvironmentclass.Thosefieldsallstartwith"DIRECTORY".E.g.DIRECTORY_MUSICorDIRECTORY_PICTURES.
Thosefilesalwayshavetobestoredonthesdcard(ortheequivalentpartitionfordevicesthathavenosdcardslotliketheGoogleNexusline).Thereasonis,thatthosefilestendtobequitelarge,thattheyneedtobeworld-readableandthattheymustnotbestoredinadirectorythatget'scleanedupwhenyourappgetsuninstalled.Iwillcoverexternalstorageinmoredetailinthefollowingsections.
YoucangetaccesstotherootofthesdcardbycallingthegetExternalStorageDirectory()methodontheEnvironmentclass.
AndyoucanusegetExternalStoragePublicDirectory(Stringtype)todirectlygetaFileobjectforanyofthesupportedtypes:
Environment.getExternalStoragePublicDirectory
(Environment.DIRECTORY_MOVIES);
It'stheusualJavaIOAPIfromhereon.
App-specificfiles
Thistypeoffilesisforanykindofdatathatonlythisspecificappcanorshouldmakeuseof.Thiscouldbeproprietaryfileslikeebooks,mediafilesthatshouldnotbeavailablethroughthenormalmediaplayers(e.g.thumbnailsforCDcovers),downloadedmagazines,databasefiles,preferencesandsoon.
App-specificfilescanbestoredinternallyorexternally(onthesdcard)andtheAndroidAPIhelpsyoutofindtheappropriatedirectories.
What'sniceforapp-specificfoldersthatfollowacertainnamingconventionisAndroid'scleanupmechanism.Androidtakescaretodeletethesefolderwhenusersuninstallyourapp.ThiswayAndroidgetsridofunnecessaryfilesandusersdonothavetocleanupmanuallyafteranydeinstallation.
Internalstorageversusexternalstorage
Youshouldknowthattherearetwoapp-specificfoldersforanyapp.Theinternalonewhichyoucanuseforprivatefilesandtheexternalone.ExternalstoragereferstothesdcardofAndroiddevicesortheequivalentpartitionthatdeviceswithnosdcardoptionoffer(e.g.theNexusline).
Internalstoragespacecanbelimited
Especiallyforlargerfilesyoushouldprefertheexternalstorageoption.Youshoulddosobecauseinternalstoragespacecanbeverylimiteddependingonthedeviceofyouruser.AprobablyextremeexampleismyoldLGOptimusOnethathasonlyabout300MBofinternalstorage.Butwitha16GBsdcardIhaveplentyofexternalstorage.Evenifthisdeviceisoneoftheworstexamplesregardinginternalstorage,thereareplentyofdevicesouttherethatalsocomewithlittleinternalstorage.Noteveryoneuseshigh-endphones.
Permissionsforwritingtoexternalstorage
Wheneveryouwanttoaccessfilesontheexternalstorageyouneedpermissionstodoso.Addthispermissionstoyourmanifestfile:
Theneedtodeclarethispermissionsisaslightdrawbackcomparedtointernalstorage.Someusersmaybewary-especiallyifthisaddstoanalreadylonglistofpermissions.Butifyouexplainthisinyourappdescriptionyoushouldbefine.
Note:ForreadingfilesofthesdcardnopermissionswereneededpriortoJellyBean.SoyoucanleavethisoneoutifyourbuildtargetislowerthanAPIlevel16.
Externalstoragemightbeunavailable
Thebiggestproblemwithexternalstorageis,thatitmightbeunmountedwhenyouneedit.That'sobviouslythecasewhenthesdcardisejectedbutalsowhenyourdeviceismountedforfileaccesstoyourcomputer.Becauseofthis,youalwayshavetocheck,iftheexternalstorageiscurrentlyavailable:
if(Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)){
//youcangoon
}
Sometimestheexternalstoragemightbemountedread-only.Ifyouonlyneedtoreaddatathefollowingcheckisbettersuitedforyou:
if(Environment.getExternalStorageState().startsWith(
Environment.MEDIA_MOUNTED)){
//youcangoon
}
ThisworkssincethevalueofthefinalfieldEnvironment.MEDIA_MOUNTED_READ_ONLYis"mounted_ro".Iactuallydonotlikecode,thatusesknowledgeoffinalfields'value.Inmyopinionitwouldhavebeenbetter,hadGooglechosentouseanintegersothatwecouldusefinalfieldsasbitmaskstotestforthestate.
Internalapp-specificdirectories
Androidcreatesadirectoryprivatetoyourappforyou.Yoursharedpreferencesgoinhere,aswellasyourSQLitedatabases,nativelibrariesorcachedfiles.
Allapp-specificfilesarewithinafoldernamed
/data/data/your.package.name/
Withinthisfoldersomecommonsub-foldersmightexist-dependingonwhatyourappneeds:
databases-forSQLitedatabases
shared_prefs-foryourpreferences
cache-forcachefilesanddata
lib-fornativelibraries
files-forfilesthatdonotfitintoothercategories
TheContextclassprovidessomemethodsyoucanusetocreatenewdirectories,openInputStreamsandsoon.Thefollowingtableliststhesemethods:
Methodstohelpyouwithinternalstorage
Method
Whentouse
deleteFile(Stringname)
Deletesthefilewiththegivenname
fileList()
Returnsalistoffiles
getDir(Stringname,intmode)
Returnsafileobjecttothisdirectory.Ifthedirectorydoesn'texistyet,itgetscreated.
getFilesDir()
ReturnsaFileobjectpointingtothefilesdirectory
openFileInput(Stringname)
OpensanInputStreamobjecttothefilewiththegivenname
openFileOutput(Stringname,intmode)
OpensanOutputStreamobjecttothefilewiththegivenname.Thefilegetscreatedifitdoesnotexists
Somemethodsuseamodeparameter.ThiscanbeanyofthefollowingconstantsoftheContextclass:
MODE_APPEND
MODE_PRIVATE
MODE_WORLD_READABLE
MODE_WORLD_WRITEABLE
Theseareintvaluesandyoucanusetheoroperator("|")tocombinethem-e.g.toappendtoaworldreadablefile:
openFileOutput("yourWritableFile",
Context.MODE_APPEND|Context.MODE_WORLD_READABLE);
Externalapp-specificdirectories
ThisiswhereWaza_be'srantcomesintoplay-becausetoomanyappsignorethecorrecthandlingofapp-specificdirectoriesonexternalstorage.
Allexternalapp-specificfilesshouldbestoredwithinafoldernamed
Android/data/your.package.name/
NotethatIusearelativepath.Thispathisrelativetotherootofthesdcard.Theconventionofwheresdcardsaremounted,changedbetweenAndroidreleases.
It'salwaysgoodpracticetouseAPIcallsinsteadofhard-codedvalues,butthefactthatthemount-pointhaschangedinthepastshouldmakeyouevenmorecautious.
Nowforexternalfilesthereexistsonlyonemethodyoucanuse:
getExternalFilesDir(Stringtype)
IfyoupassinanullvaluetheFileobjectwillpointtothefilesdirectory.IfyouaddanyofthedirectoryconstantsoftheEnvironmentclass,youwillgetaFileobjectpointingtoasub-directorywithinyourfilesdirectory.Ifthedirectorydoesn'texitsyet,Androidcreatesitforyou.Iftheexternalmediaisnotmounted,themethodreturnsnull.
Note:ThismethodhasonlybeenintroducedwithAPILevel8(thatisFroyoorAndroid2.2).InthenextsectionIbrieflytouchontheissuesyoufacewhendealingwitholderdevices.
Olderdevices
Therearestilldevicesoutthereonolderversions,whichyoumightwanttosupport.Inthiscaseusingthenamingconventionshownaboveisstillagoodidea.
Alas,neitherthemethodgetExternalFilesDir(Stringtype)exists,nordoesAndroidcleanupafteranappuninstall.Butusingthesamenamingconventionstillavoidstoomanyirritatingfoldersontherootofyoursdcard.
Cache
Manytimesyouneedtocachedatayoudownloadedfromthenetorcreatedwithinyourapp.Androidallowsyoutouseinternalaswellasexternalstoragespacetousethecache.Butusingtheexternalstoragecanberisky,sinceyourcachemightbeunavailablewhenyouneedit.
TheContextobjecthastwomethodstogetaFileobjectforeithertheinternalortheexternalcachedirectory:
getCacheDir()
getExternalCacheDir()
Youhavetotakecareofthecachesizeyourself.Androiddeletesallfilesinbothdirectoriesonanuninstallationofyourapp,butotherwiseit'suptoyoutocleanupanycachefilesnolongerneeded.
IfAndroidisrunninglowoninternalstorageitcleansupcachefilesfirstbuttheAPIstatesexplicitlythatyoushouldnotrelyonAndroidtocleanupforyou!
WiththeexternalcachestorageAndroiddoesn'tcareatall.Eveniftheexternalstorageisfull,nocachefileswillbedeleted.
Namingofthefolder
Theofficialnamingconventionforthefoldercontainsyourpackagename.ChristopheVersieux(Waza_be)himselfmentionedthatheusedtousetheappnameinstead,sinceusersaremorefamiliarwiththepackagenameoftheapp.
Eventhoughfamiliarityissomethingtoconsider,Idonotagreewiththisstatement.FirstofalltheAPIcallusesthepackagename,sowhynotuseit.Onlywiththismethodyoucanrelytobeonthesafeside.SecondlyAndroidonlycleansupafolderusingthepackagename.Andfinallyyoucouldgetscrewedsinceappnamesdonothavetobeunique.Inthiscaseyoumightendupdoingstuffinyourfolderthatclasheswiththeintentionsoftheotherapp.
Beawareofthe".nomedia"-switch
Android'sMediaScannerregularlyscansthesdcardforanymediafilesandaddsthesetothepubliclistofmediafiles.ThusimageswillshowupintheGalleryappormusicfilesinaudioplayers.
Butthat'snotalwayswhatyouwant.Sometimesthosefilesreallyshouldbepresentedbyyourapponly.That'swhere".nomedia"comesintoplay.Ifafoldercontainsafilenamed".nomedia"itwillbeskippedbytheMediaScannerandanymediafileswillthusnotshowupinthepublicmedialist.
That'sanotherreasontousethestandardapp-specificfolder.Itcontainsthefile".nomedia"withinthedatadirectorysothatanymediafilesyouaddtoyourapp-specificdirectorywillnotshowup.
Lessonslearned
Inthistutorialyouhaveheardaboutthedifferencebetweenapp-specificandapp-independentfilesandhowtoapplythisknowledgetoAndroid.
Alsoyouhaveseenhowtouseapp-specificfilesonAndroid,andhowtoleveragetheinternalstorageaswellastheexternalstorage.
InafollowuppostIwillcoverhowtoaddapp-independentmediafilestothecorrespondingcontentproviders,sothattheyshowupimmediatelyinthelistofpublicmediafiles.Staytuned.
Edited:
Minorchangesduetocommentsby+AlexandreRomanand+CyrilMottiertomyG+announcementofthispost.
WolframRittmeyerlivesinGermanyandhasbeendevelopingwithJavaformanyyears.
HehasbeeninterestedinAndroidforquiteawhileandhasbeenbloggingaboutallkindoftopicsaroundAndroid.
YoucanfindhimonGoogle+andTwitter.
Tags:Android,ExternalStorage,getExternalFilesDir(),getExternalStorageDirectory(),internalStorage,SDcard,Storage
«AndroidQuickTip:FormattingTextwithHtml.fromHtml()
AddingFilestoAndroid’sMediaLibraryUsingtheMediaScanner»