How to Correctly Store App-Specific Files in Android

文章推薦指數: 80 %
投票人數:10人

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»



請為這篇文章評分?