首页 > 编程知识 正文

mtp模式是什么意思,建议前往安卓存储访问框架查看文件

时间:2023-05-04 11:38:40 阅读:41029 作者:2212

请注明文章的错误和作者

作者: Xandy

资料来源: http://blog.csdn.net/xl19862005

一、mtp概述

安卓在3.0及更高版本中加入了对mtp的支持,相对于mass storage模式,由于mtp优势,目前大多数手机都是在连接到PC后通过mtp方式访问文件。

这里简单说明一下mtp的好处。

1、启动器和Responder可以同时保存文件。 对于mass storage模型,这一优势非常明显。

将responder设备连接到PC时,它通过vfs间接访问存储分区中的文件,而不是直接访问设备中的存储分区。 作为启动器端的PC设备,无需在意要访问的responder存储分区是什么文件系统,可以通过公共vfs对不同文件系统的存储设备进行读写

2、在mtp模式下启动器可以知道Responder支持的媒体文件格式

3、文件访问权限可控。 这是笔者根据android下的mtp框架独自追加的,也是本文应该说的重点。

二.安卓MTP启动流程

这里要提到的是,在android设备启动后,mediascannerreceiver (Android _ src/providers/media provider/src/com/Android/providers ) 当MediaScannerReceiver.java ()接收到启动完成广播(Android.intent.action.boot _ completed )时,MeidaScannerService将启动

本节介绍本机android系统中的错误。 打开电源后,用android设备拍照或截图后,将设备连接到PC时,找不到刚拍的照片或截图的照片。 这是因为在MediaScannerService启动为BOOT_COMPLETED时只扫描一次,然后新添加的文件尚未更新到数据库中,因此重新启动系统后在PC上发现新添加的文件

为了解决这个错误,我向MediaScannerReceiver添加了对USB_STATE状态广播的监听,所以每次重新拔插USB时都会进行扫描。

从上图可知,MtpService启动后也需要去数据库(MtpDatabase )取文件,因此通过修改数据库的搜索规则,可以实现在连接到PC后仅显示指定的文件/文件夹的功能

三.修改文件过滤器代码

首先,用MTP数据库(Android _ src/frameworks/base/media/Java/Android/MTP/MTP database.Java ) )创建数据库查询

私有资源创建对象查询(intstorageid,int format,int parent ) throwsremoteexception { string where; String[] whereArgs; if (存储id==0x ffffff )//queryallstoresif (格式==0)/queryallformatsif (parent==0) )//query all }else{if(parent==0xfffffff )/allobjectsinrootofstoreparent=0; } where=PARENT_WHERE; where args=new string [ ] { integer.tostring (parent ); } else {//queryspecificformatif (parent==0) )//queryallobjectswhere=format _ where; where args=new string [ ] { integer.tostring (格式); } else { if

(parent == 0xFFFFFFFF) { // all objects in root of store parent = 0; } where = FORMAT_PARENT_WHERE; whereArgs = new String[] { Integer.toString(format), Integer.toString(parent) }; } } } else { // query specific store if (format == 0) { // query all formats if (parent == 0) { // query all objects where = STORAGE_WHERE; whereArgs = new String[] { Integer.toString(storageID) }; } else { if (parent == 0xFFFFFFFF) { // all objects in root of store parent = 0; where = STORAGE_PARENT_WHERE; whereArgs = new String[] { Integer.toString(storageID), Integer.toString(parent) }; } } else { // query specific format if (parent == 0) { // query all objects where = STORAGE_FORMAT_WHERE; whereArgs = new String[] { Integer.toString(storageID), Integer.toString(format) }; } else { if (parent == 0xFFFFFFFF) { // all objects in root of store parent = 0; } where = STORAGE_FORMAT_PARENT_WHERE; whereArgs = new String[] { Integer.toString(storageID), Integer.toString(format), Integer.toString(parent) }; } } } // if we are restricting queries to mSubDirectories, we need to add the restriction // onto our "where" arguments if (mSubDirectoriesWhere != null) { if (where == null) { where = mSubDirectoriesWhere; whereArgs = mSubDirectoriesWhereArgs; } else { where = where + " AND " + mSubDirectoriesWhere; // create new array to hold whereArgs and mSubDirectoriesWhereArgs String[] newWhereArgs = new String[whereArgs.length + mSubDirectoriesWhereArgs.length]; int i, j; for (i = 0; i < whereArgs.length; i++) { newWhereArgs[i] = whereArgs[i]; } for (j = 0; j < mSubDirectoriesWhereArgs.length; i++, j++) { newWhereArgs[i] = mSubDirectoriesWhereArgs[j]; } whereArgs = newWhereArgs; } } return mMediaProvider.query(mPackageName, mObjectsUri, ID_PROJECTION, where, whereArgs, null, null); }

而方法query的定义如下:

public Cursor query(String callingPkg, Uri url, String[] projection, String selection, String[] selectionArgs, String sortOrder, IcancellationSignal cancellationSignal)throws RemoteExceptioin;

不难理解,方法createObjectQuery中获得的where 字串是用于到数据库里查询与where匹配的文件的,这里还要说明一点的是mSubDirectoriersWhere,可以看到当这个subDirectoriersWhere不为空时,作了如下合并到where字串

where = where + " AND " + mSubDirectoriesWhere;

那么可以通过增加对这个mSubDirectoriesWhere的赋值(赋以指定需要到数据库里查询的文件夹名),就可以达到想要的文件过滤功能!
而mSubDirectoriesWhere只在MtpDatabase的构造方法里进行赋值:

public MtpDatabase(Context context, Stirng volumeName, String storagePath, String[] subDirectories){ …… if(subDirectories != null){ StringBuilder builder = new StringBuilder(); int count = subDirectories.lenght; for(int i=0;i<count;i++){ builder.append.......... …… } …… mSubDirectoriesWhere = builer.toString(); }}

那么只要在创建 MtpDatabase的时候传入这个subDirectories String数组就可以达到想要的功能了!
在MtpService(android_src/packages/providers/MediaProvider/src/com/android/providers/media/MtpService.java)中增加如下代码:

private static final String[] MTP_DIRECTORIES_PRIVATE = new String[]{ Environment.DIRECTORY_DCIM, Environment.DIRECTORY_PICTURES, Environment.DIRECTORY_MOVIES, Environment.XXXXXX, ……};……@Overridepublic int onStartCommand(Intent intent, int flags, int startId){ …… if(!mPtpMode){ int num = MTP_DIRECTORIES_PRIVATE.length; subdirs = new String[num]; for(int j=0;j<num;j++){ File file = Environment.getExternalStoragePublicDirectory(MTP_DIRECTORIES_PRIVATE[j]); file.mkdirs(); subdirs[j] = file.getPath(); } } …… //最后在这里创建MtpDatabase,并传入subdirs到前面提到的where mDatabase = new MtpDatabase(this, MediaProvider.EXTERNAL_VOLUME, primary.getPath(), subdirs); ……}

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。