您的位置:首页 > 移动开发 > Android开发

Android开发总结笔记 四大组件之ContentPovider(下) 1-2-9

2015-10-23 10:05 459 查看
在ContentProvider的官方文档中,可以看到。有上图的三个有趣的东西CalendarProvider:月历提供者,针对系统的月历提供的API,我们可以对日历,时间,事件等做一些增删改查的操作ContactsProvider:通讯录提供者,有很多针对通讯录的一些APIStorageAccessFramework:存储访问框架,4.4(Kitkat)以后添加的一个东西。方便用户访问一些文档、图片、音频、视频等CalendarProvider和ContactsProvider就不详细说了,看下StorageAccessFramework(SAF)吧先来看下他是个什么东西。
Intentintent=newIntent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("image/*");
startActivity(intent);
事实上这个就是系统的一个软件,用来获取文件的URI下面的直接上文档吧。SAF的组成Documentprovider:一个特殊的ContentProvider,让一个存储服务(GoogleDrive)可以对外展示自己所管理的文件。它是DocumentProvider的子类,另外,document-provider的存储格式和传统的文件存储格式一致。Clientapp:一个普通客户端软件,通触发ACTION_OPEN_DOCUMENTACTION_CREATE_DOCUMENT就可以接收到来自于Documentprovider返回的内容,比如选择一个图片,然后返回一个UriPicker:类似文件管理器的页面,而且是系统级的,提供访问客户端的过滤条件一些特性用户可以浏览所有documentprovider提供的内容,而不是仅仅是单一的应用程序拥有数据持久化能力,可以增删改查documentprovider维护的内容支持多用户以及临时性的服内容服务,比如USBstorageproviders,只有当驱动安装成功才会出现概述SAF的核心是实现了DocumentsProvider的子类,事实上也还是一个ContentProvider,在DocumentsProvider中,文件是以传统的目录树组织起来的不过那只是对外的一种形式,如何去存储数据,取决于你自己,只要的对外的接口能偶通过DocumentProvider的api访问就可以了下面是一个展示一个photo应用使用SAF的流程图(可能)

从上图可以看出,Picker就是调用者和内容提供者的一个桥梁

咱们来试试获取一下Uri
publicclassMainActivityextendsAppCompatActivity{
@Override
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
privatevoidinit(){
Intentintent=newIntent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("image/*");
startActivityForResult(intent,0x00);
}
@Override
protectedvoidonActivityResult(intrequestCode,intresultCode,Intentdata){
if(requestCode==0x00&&resultCode==RESULT_OK){
if(null!=data){
Uriuri=data.getData();
Log.i("data",uri+"");
}
}
}
}
当我点击其中一张图片之后,界面自动关闭,然后日志打出OK,成功获取到了Uri通过这个Uri我们可以做很多的事情根据uri获取文件参数
publicvoiddumpImageMetaData(Uriuri){
Cursorcursor=getContentResolver()
.query(uri,null,null,null,null,null);
try{
if(cursor!=null&&cursor.moveToFirst()){
StringdisplayName=cursor.getString(
cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
Log.e("HeHe","DisplayName:"+displayName);
intsizeIndex=cursor.getColumnIndex(OpenableColumns.SIZE);
Stringsize=null;
if(!cursor.isNull(sizeIndex)){
size=cursor.getString(sizeIndex);
}else{
size="Unknown";
}
Log.e("HeHe","Size:"+size);
}
}finally{
cursor.close();
}
}
根据Uri获取Bitmap
privateBitmapgetBitmapFromUri(Uriuri)throwsIOException{
ParcelFileDescriptorparcelFileDescriptor=
getContentResolver().openFileDescriptor(uri,"r");
FileDescriptorfileDescriptor=parcelFileDescriptor.getFileDescriptor();
Bitmapimage=BitmapFactory.decodeFileDescriptor(fileDescriptor);
parcelFileDescriptor.close();
returnimage;
}
根据Uri获取输入流
privateStringreadTextFromUri(Uriuri)throwsIOException{
InputStreaminputStream=getContentResolver().openInputStream(uri);
BufferedReaderreader=newBufferedReader(newInputStreamReader(
inputStream));
StringBuilderstringBuilder=newStringBuilder();
Stringline;
while((line=reader.readLine())!=null){
stringBuilder.append(line);
}
fileInputStream.close();
parcelFileDescriptor.close();
returnstringBuilder.toString();
}
根据Uri创建新文件以及删除文件创建
privatevoidcreateFile(StringmimeType,StringfileName){
Intentintent=newIntent(Intent.ACTION_CREATE_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType(mimeType);
intent.putExtra(Intent.EXTRA_TITLE,fileName);
startActivityForResult(intent,WRITE_REQUEST_CODE);
}
删除前提是Document.COLUMN_FLAGS包含SUPPORTS_DELETE
DocumentsContract.deleteDocument(getContentResolver(),uri);
自定义DocumentProvider(API19以上)
<manifest...>
...
<uses-sdk
android:minSdkVersion="19"
android:targetSdkVersion="19"/>
....
<provider
android:name="com.example.android.storageprovider.MyCloudProvider"
android:authorities="com.example.android.storageprovider.documents"
android:grantUriPermissions="true"
android:exported="true"
android:permission="android.permission.MANAGE_DOCUMENTS"
android:enabled="@bool/atLeastKitKat">
<intent-filter>
<actionandroid:name="android.content.action.DOCUMENTS_PROVIDER"/>
</intent-filter>
</provider>
</application>
</manifest>
至少实现下面几个方法queryRoots()queryChildDocuments()queryDocument()openDocument()下面是一个访问文件的系统的DocumentProvider的大致写法
publicCursorqueryRoots(String[]projection)throwsFileNotFoundException{
//Createacursorwitheithertherequestedfields,orthedefault
//projectionif"projection"isnull.
finalMatrixCursorresult=
newMatrixCursor(resolveRootProjection(projection));
//Ifuserisnotloggedin,returnanemptyrootcursor.Thisremovesour
//providerfromthelistentirely.
if(!isUserLoggedIn()){
returnresult;
}
//It'spossibletohavemultipleroots(e.g.formultipleaccountsinthe
//sameapp)--justaddmultiplecursorrows.
//Constructonerowforarootcalled"MyCloud".
finalMatrixCursor.RowBuilderrow=result.newRow();
row.add(Root.COLUMN_ROOT_ID,ROOT);
row.add(Root.COLUMN_SUMMARY,getContext().getString(R.string.root_summary));
//FLAG_SUPPORTS_CREATEmeansatleastonedirectoryundertherootsupports
//creatingdocuments.FLAG_SUPPORTS_RECENTSmeansyourapplication'smost
//recentlyuseddocumentswillshowupinthe"Recents"category.
//FLAG_SUPPORTS_SEARCHallowsuserstosearchalldocumentstheapplication
//shares.
row.add(Root.COLUMN_FLAGS,Root.FLAG_SUPPORTS_CREATE|
Root.FLAG_SUPPORTS_RECENTS|
Root.FLAG_SUPPORTS_SEARCH);
//COLUMN_TITLEistheroottitle(e.g.Gallery,Drive).
row.add(Root.COLUMN_TITLE,getContext().getString(R.string.title));
//Thisdocumentidcannotchangeonceit'sshared.
row.add(Root.COLUMN_DOCUMENT_ID,getDocIdForFile(mBaseDir));
//ThechildMIMEtypesareusedtofiltertherootsandonlypresenttothe
//userrootsthatcontainthedesiredtypesomewhereintheirfilehierarchy.
row.add(Root.COLUMN_MIME_TYPES,getChildMimeTypes(mBaseDir));
row.add(Root.COLUMN_AVAILABLE_BYTES,mBaseDir.getFreeSpace());
row.add(Root.COLUMN_ICON,R.drawable.ic_launcher);
returnresult;
}
@Override
publicCursorqueryChildDocuments(StringparentDocumentId,String[]projection,
StringsortOrder)throwsFileNotFoundException{
finalMatrixCursorresult=new
MatrixCursor(resolveDocumentProjection(projection));
finalFileparent=getFileForDocId(parentDocumentId);
for(Filefile:parent.listFiles()){
//Addsthefile'sdisplayname,MIMEtype,size,andsoon.
includeFile(result,null,file);
}
returnresult;
}
@Override
publicCursorqueryDocument(StringdocumentId,String[]projection)throws
FileNotFoundException{
//Createacursorwiththerequestedprojection,orthedefaultprojection.
finalMatrixCursorresult=new
MatrixCursor(resolveDocumentProjection(projection));
includeFile(result,documentId,null);
returnresult;
}
文档的内容基本上也就这些了。Android4.4获取资源路径的问题因为SAF的出现,所以4.4以上和以下的版本获取出来的Uri会变得不一样网上找的一套解决方案Android4.4获取资源路径的问题
publicstaticStringgetPath(finalContextcontext,finalUriuri){
finalbooleanisKitKat=Build.VERSION.SDK_INT>=Build.VERSION_CODES.KITKAT;
//DocumentProvider
if(isKitKat&&DocumentsContract.isDocumentUri(context,uri)){
//ExternalStorageProvider
if(isExternalStorageDocument(uri)){
finalStringdocId=DocumentsContract.getDocumentId(uri);
finalString[]split=docId.split(":");
finalStringtype=split[0];
if("primary".equalsIgnoreCase(type)){
returnEnvironment.getExternalStorageDirectory()+"/"+split[1];
}
//TODOhandlenon-primaryvolumes
}
//DownloadsProvider
elseif(isDownloadsDocument(uri)){
finalStringid=DocumentsContract.getDocumentId(uri);
finalUricontentUri=ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"),Long.valueOf(id));
returngetDataColumn(context,contentUri,null,null);
}
//MediaProvider
elseif(isMediaDocument(uri)){
finalStringdocId=DocumentsContract.getDocumentId(uri);
finalString[]split=docId.split(":");
finalStringtype=split[0];
UricontentUri=null;
if("image".equals(type)){
contentUri=MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
}elseif("video".equals(type)){
contentUri=MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
}elseif("audio".equals(type)){
contentUri=MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
}
finalStringselection="_id=?";
finalString[]selectionArgs=newString[]{
split[1]
};
returngetDataColumn(context,contentUri,selection,selectionArgs);
}
}
//MediaStore(andgeneral)
elseif("content".equalsIgnoreCase(uri.getScheme())){
returngetDataColumn(context,uri,null,null);
}
//File
elseif("file".equalsIgnoreCase(uri.getScheme())){
returnuri.getPath();
}
returnnull;
}
/**
*GetthevalueofthedatacolumnforthisUri.Thisisusefulfor
*MediaStoreUris,andotherfile-basedContentProviders.
*
*@paramcontextThecontext.
*@paramuriTheUritoquery.
*@paramselection(Optional)Filterusedinthequery.
*@paramselectionArgs(Optional)Selectionargumentsusedinthequery.
*@returnThevalueofthe_datacolumn,whichistypicallyafilepath.
*/
publicstaticStringgetDataColumn(Contextcontext,Uriuri,Stringselection,
String[]selectionArgs){
Cursorcursor=null;
finalStringcolumn="_data";
finalString[]projection={
column
};
try{
cursor=context.getContentResolver().query(uri,projection,selection,selectionArgs,
null);
if(cursor!=null&&cursor.moveToFirst()){
finalintcolumn_index=cursor.getColumnIndexOrThrow(column);
returncursor.getString(column_index);
}
}finally{
if(cursor!=null)
cursor.close();
}
returnnull;
}
/**
*@paramuriTheUritocheck.
*@returnWhethertheUriauthorityisExternalStorageProvider.
*/
publicstaticbooleanisExternalStorageDocument(Uriuri){
return"com.android.externalstorage.documents".equals(uri.getAuthority());
}
/**
*@paramuriTheUritocheck.
*@returnWhethertheUriauthorityisDownloadsProvider.
*/
publicstaticbooleanisDownloadsDocument(Uriuri){
return"com.android.providers.downloads.documents".equals(uri.getAuthority());
}
/**
*@paramuriTheUritocheck.
*@returnWhethertheUriauthorityisMediaProvider.
*/
publicstaticbooleanisMediaDocument(Uriuri){
return"com.android.providers.media.documents".equals(uri.getAuthority());
}

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: