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

android之Uri

2016-04-22 21:03 786 查看
一.URI简介

概念:统一资源标识符(Uniform Resource Identifier)

组成部分:

    1.访问资源的命名机制(scheme)

    2.存放资源的主机名(authority)

    3.资源自身的名称,由路径表示(path)

格式:scheme:// authority//path,其中authority中又包括了host和port两部分。

例如:

content://com.example.project:200/folder/subfolder/etc

 \---------/ \----------------------------/ \----/ \------------------------/

 Scheme          host             port              path

            \------------------------------------/

                            Authority

用处:uri主要用来表示一个资源。这个资源有很多种类,包括图片,视频,文件等。

针对资源的种类,uri用以下几种scheme标识:

      1.Content:主要操作的是ContentProvider,所以它代表的是数据库中的某个资源

      2.http:一个网站资源

      3.file:本地机器上的某个资源

      4.git:git仓库中某个资源

      5.ftp:服务器上的某个资源

      6.ed2k:(电驴协议)

      7.等等……….

以上的资源例子如下:
http://write.blog.csdn.net/postedit/7313543,
file:///c:/WINDOWS/clock.avi
git://github.com/user/project-name.git ftp://user1:1234@地址 ed2k://|file|%5BMAC%E7%89%88%E6%9E%81%E5%93%81%E9%A3%9E%E8%BD%A69%EF%BC%9A%E6%9C%80%E9%AB%98%E9%80%9A%E7%BC%89%5D.%5BMACGAME%5DNeed.For.Speed.Most.Wanted.dmg|4096933888|2c55f0ad2cb7f6b296db94090b63e88e|h=ltcxuvnp24ufx25h2x7ugfaxfchjkwxa|/

在Android中,由于很多资源(音频、视频、图片、以及个人通信录信息)都存入了数据库,所以Android中对资源的使用一般是通过ContentProivder访问数据库,见得比较多的就是Content这种类型的uri。所以我们这里也只是着重讲Content类型的uri。

二.uri详解

1.Authority部分:

在看Authority之前,让我们先了解一下ContentProvider。

ContentProvider在android中的作用是对外共享数据, 也就是说你可以通过ContentProvider把应用中的数据共享给其他应用访问,其他应用可以通过ContentProvider对你应用中的数据进行添删改查。那么其他的应用该怎么找到这个ContentProvider?答案在AndroidManifest.xml中配置:
package="com.android.providers.telephony"
<provider android:name="TelephonyProvider"
android:authorities="telephony"
android:exported="true"
android:singleUser="true"
android:multiprocess="false" />
在这里,规定了这个TelephonyProvider内容提供者对外提供的主机(authorities)为telephony。

   好了,让我们回去看看content://com.example.project:200/folder/subfolder/etc这个例子。host主要是用com.example.project来表示,这根本就是一个包名啊。但是通过AndroidManifest.xml配置后,就看到了最常见的uri:

所有SIM卡信息的Uri: content:// telephony/siminfo

某张SIM卡的Uri: content:// telephony/siminfo/2

所有图片Uri: content://media/external

某个图片的Uri:content://media/external/images/media/4

2.path部分:

path部分就简单了,既然Authority指定了一个ContentProvider。那么如果我们需要某个具体的资源,就需要通过查询数据库表,在表中存储的位置等等信息了。所以content:// telephony/siminfo/2中siminfo代表的是数据库表名,2代表的是表中某个具体的数值。

三.Uri及它的工具类

1.Uri.java

Uri主要的结构如下:

Uri的内部类:

------- StringUri  子孙类,使用不明

------- OpaqueUri 子孙类,使用不明

------- HierarchicalUri子孙类,Builder构建Uri的实例对象主要是使用了这个类。

------- Builder 静态类,用于获取Uri实例对象。

------- ….

由于Uri的构造方法是私有的,所以它提供了Builder这个静态类用于获取Uri的实例对象。除了获取对象外,它还提供了很多实用的方法,比如:

Public Uri Build()-------获取Uri的实例对象

Public Builder encodedPath(String path)--------根据path构建Builder对象

public Builder authority(String authority)-------根据authority构建Builder对象

…….

Uri的主要方法:
public static Uri withAppendedPath(Uri baseUri, String pathSegment)
public boolean isPathPrefixMatch(Uri prefix)
public static String encode(String s, String allow)
Uri的两个操作工具类:UriMatcher和ContentUris

2.UriMatcher.java

构造方法:
private ArrayList<UriMatcher> mChildren;
public UriMatcher(int code)
{
mCode = code;
mWhich = -1;
mChildren = new ArrayList<UriMatcher>();
mText = null;
}

UriMatcher维护了一个ArrayList用于保存所有加进来的UriMatcher对象。执行添加操作的方法如下:

public void addURI(String authority, String path, int code)
{
if (code < 0) {
throw new IllegalArgumentException("code " + code + " is invalid: it must be positive");
}

String[] tokens = null;
if (path != null) {
String newPath = path;
// Strip leading slash if present.
if (path.length() > 0 && path.charAt(0) == '/') {
newPath = path.substring(1);
}
tokens = PATH_SPLIT_PATTERN.split(newPath);
}

int numTokens = tokens != null ? tokens.length : 0;
UriMatcher node = this;
for (int i = -1; i < numTokens; i++) {
String token = i < 0 ? authority : tokens[i];
ArrayList<UriMatcher> children = node.mChildren;
int numChildren = children.size();
UriMatcher child;
int j;
for (j = 0; j < numChildren; j++) {
child = children.get(j);
if (token.equals(child.mText)) {
node = child;
break;
}
}
if (j == numChildren) {
// Child not found, create it
child = new UriMatcher();
if (token.equals("#")) {
child.mWhich = NUMBER;
} else if (token.equals("*")) {
child.mWhich = TEXT;
} else {
child.mWhich = EXACT;
}
child.mText = token;
node.mChildren.add(child);
node = child;
}
}
node.mCode = code;
}
Code为匹配码,每个插入到ArrayList中的UriMatcher我们都可以设置一个匹配码,为之后执行match()方法时能返回。

一个匹配的方法:
public int match(Uri uri){…}
我们来分析一下在源码TelephonyProvider中它的使用:

首先,TelephonyProvider创建了一个静态块,用于添加UriMatcher:
private static final UriMatcher s_urlMatcher = new UriMatcher(UriMatcher.NO_MATCH);
static {
s_urlMatcher.addURI("telephony", "carriers", URL_TELEPHONY);
s_urlMatcher.addURI("telephony", "carriers/current", URL_CURRENT);
s_urlMatcher.addURI("telephony", "carriers/#", URL_ID);
s_urlMatcher.addURI("telephony", "carriers/restore", URL_RESTOREAPN);
s_urlMatcher.addURI("telephony", "carriers/preferapn", URL_PREFERAPN);
s_urlMatcher.addURI("telephony","carriers/preferapn_no_update", URL_PREFERAPN_NO_UPDATE);
s_urlMatcher.addURI("telephony", "siminfo", URL_SIMINFO);
s_urlMatcher.addURI("telephony","carriers/subId/*", URL_TELEPHONY_USING_SUBID);
s_urlMatcher.addURI("telephony", "carriers/current/subId/*", URL_CURRENT_USING_SUBID);
s_urlMatcher.addURI("telephony", "carriers/restore/subId/*", URL_RESTOREAPN_USING_SUBID);
s_urlMatcher.addURI("telephony", "carriers/preferapn/subId/*", URL_PREFERAPN_USING_SUBID);
s_urlMatcher.addURI("telephony", "carriers/preferapn_no_update/subId/*",
URL_PREFERAPN_NO_UPDATE_USING_SUBID);
}
这样,在对象s_urlMatcher内部维护了一个ArrayList, TelephonyProvider内容提供者中提供了增删改查的方法,我们来看看其中的一个方法update();
public Cursor query(Uri url, String[] projectionIn, String selection,
String[] selectionArgs, String sort) {
int match = s_urlMatcher.match(url);
switch (match) {
case URL_TELEPHONY_USING_SUBID: {
subIdString = url.getLastPathSegment();
…
case URL_TELEPHONY: {
break;
}

case URL_CURRENT_USING_SUBID: {
subIdString = url.getLastPathSegment();
}
…
}
SQLiteDatabase db = mOpenHelper.getReadableDatabase();
Cursor ret = null;
try {
ret = qb.query(db, projectionIn, selection, selectionArgs, null, null, sort);
} catch (SQLException e) {
loge("got exception when querying: " + e);
}
if (ret != null)
ret.setNotificationUri(getContext().getContentResolver(), url);
return ret;
}
可以看到,如果我们需要查询这个数据库中的数据时,传过来的uri需要跟s_urlMatcher内部的ArrayList进行匹配查找,如果存在此uri,则从数据库中查询并返回相应的数据,如果不存在此uri,那么将得不到任何数据。因此,当我们使用TelephonyProvider查询数据库时,并不是你提供什么uri,就给你返回什么数据。

3.ContentUris

ContentUris中的源码较少,它的主要实现都是在Uri.Builder中,如下:

public static long parseId(Uri contentUri) {
String last = contentUri.getLastPathSegment();
return last == null ? -1 : Long.parseLong(last);
}
public static Uri.Builder appendId(Uri.Builder builder, long id) {
return builder.appendEncodedPath(String.valueOf(id));
}
public static Uri withAppendedId(Uri contentUri, long id) {
return appendId(contentUri.buildUpon(), id).build();
}
用法如下:

withAppendedId(uri, id)用于为路径加上ID部分:

Uri uri = Uri.parse("content://com.xxx.provider.myprovider/person");

Uri resultUri = ContentUris.withAppendedId(uri, 10);

//生成后的Uri为:content://com.xxx.provider.myprovider/person/10

parseId(uri)方法用于从路径中获取ID部分:

Uri uri = Uri.parse("content://com.xxx.provider.myprovider/person/10")

long personid = ContentUris.parseId(uri);//获取的结果为:10

=============================================分割线======================================================

Uri的总结也就这些,最后,记录一下常用的几个Uri:

显示网页:

  1. Uri uri = Uri.parse("http://www.google.com");

  2. Intent it = new Intent(Intent.ACTION_VIEW,uri);

  3. startActivity(it);

显示地图:

1. Uri uri = Uri.parse("geo:38.899533,-77.036476");

  2. Intent it = new Intent(Intent.Action_VIEW,uri);

  3. startActivity(it);

路径规划:

  1. Uri uri = Uri.parse("http://maps.google.com/maps?f=d&saddr=startLat%20startLng&daddr=endLat%20endLng&hl=en");

  2. Intent it = new Intent(Intent.ACTION_VIEW,URI);

  3. startActivity(it);

拨打电话:

调用拨号程序

  1. Uri uri = Uri.parse("tel:xxxxxx");

  2. Intent it = new Intent(Intent.ACTION_DIAL, uri);  

  3. startActivity(it);  

  1. Uri uri = Uri.parse("tel.xxxxxx");

  2. Intent it =new Intent(Intent.ACTION_CALL,uri);

  3. 要使用这个必须在配置文件中加入<uses-permission id="Android.permission.CALL_PHONE" />

发送SMS/MMS

调用发送短信的程序

  1. Intent it = new Intent(Intent.ACTION_VIEW);

  2. it.putExtra("sms_body", "The SMS text");

  3. it.setType("vnd.android-dir/mms-sms");

  4. startActivity(it);  

发送短信

  1. Uri uri = Uri.parse("smsto:0800000123");

  2. Intent it = new Intent(Intent.ACTION_SENDTO, uri);

  3. it.putExtra("sms_body", "The SMS text");

  4. startActivity(it);  

发送彩信

  1. Uri uri = Uri.parse("content://media/external/images/media/23");

  2. Intent it = new Intent(Intent.ACTION_SEND);

  3. it.putExtra("sms_body", "some text");

  4. it.putExtra(Intent.EXTRA_STREAM, uri);

  5. it.setType("image/png");

  6. startActivity(it);

发送Email

  1.

  2. Uri uri = Uri.parse("mailto:xxx@abc.com");

  3. Intent it = new Intent(Intent.ACTION_SENDTO, uri);

  4. startActivity(it);

  1. Intent it = new Intent(Intent.ACTION_SEND);

  2. it.putExtra(Intent.EXTRA_EMAIL, "me@abc.com");

  3. it.putExtra(Intent.EXTRA_TEXT, "The email body text");

  4. it.setType("text/plain");

  5. startActivity(Intent.createChooser(it, "Choose Email Client"));  

  1. Intent it=new Intent(Intent.ACTION_SEND);  

  2. String[] tos={"me@abc.com"};  

  3. String[] ccs={"you@abc.com"};  

  4. it.putExtra(Intent.EXTRA_EMAIL, tos);  

  5. it.putExtra(Intent.EXTRA_CC, ccs);  

  6. it.putExtra(Intent.EXTRA_TEXT, "The email body text");  

  7. it.putExtra(Intent.EXTRA_SUBJECT, "The email subject text");  

  8. it.setType("message/rfc822");  

  9. startActivity(Intent.createChooser(it, "Choose Email Client"));

添加附件

  1. Intent it = new Intent(Intent.ACTION_SEND);

  2. it.putExtra(Intent.EXTRA_SUBJECT, "The email subject text");

  3. it.putExtra(Intent.EXTRA_STREAM, "file:///sdcard/mysong.mp3");

  4. sendIntent.setType("audio/mp3");

  5. startActivity(Intent.createChooser(it, "Choose Email Client"));

播放多媒体

  1.  

  2. Intent it = new Intent(Intent.ACTION_VIEW);

  3. Uri uri = Uri.parse("file:///sdcard/song.mp3");

  4. it.setDataAndType(uri, "audio/mp3");

  5. startActivity(it);

  1. Uri uri = Uri.withAppendedPath(MediaStore.Audio.Media.INTERNAL_CONTENT_URI, "1");

  2. Intent it = new Intent(Intent.ACTION_VIEW, uri);

  3. startActivity(it);  

Uninstall 程序

  1. Uri uri = Uri.fromParts("package", strPackageName, null);

  2. Intent it = new Intent(Intent.ACTION_DELETE, uri);

  3. startActivity(it);

//调用相册

public static final String MIME_TYPE_IMAGE_JPEG = "image/*";

public static final int ACTIVITY_GET_IMAGE = 0;

Intent getImage = new Intent(Intent.ACTION_GET_CONTENT);

getImage.addCategory(Intent.CATEGORY_OPENABLE);

getImage.setType(MIME_TYPE_IMAGE_JPEG);

startActivityForResult(getImage, ACTIVITY_GET_IMAGE);

//调用系统相机应用程序,并存储拍下来的照片

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

time = Calendar.getInstance().getTimeInMillis();

intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(Environment

.getExternalStorageDirectory().getAbsolutePath()+"/tucue", time + ".jpg")));

startActivityForResult(intent, ACTIVITY_GET_CAMERA_IMAGE);

uninstall apk

/**未测试

Uri uninstallUri = Uri.fromParts("package", "xxx", null);

returnIt = new Intent(Intent.ACTION_DELETE, uninstallUri);

*/

Uri packageURI = Uri.parse("package:"+wistatmap);  

Intent uninstallIntent = new Intent(Intent.ACTION_DELETE, packageURI);  

startActivity(uninstallIntent);

install apk

Uri installUri = Uri.fromParts("package", "xxx", null);

returnIt = new Intent(Intent.ACTION_PACKAGE_ADDED, installUri);

play audio

Uri playUri = Uri.parse("file:///sdcard/download/everything.mp3");

returnIt = new Intent(Intent.ACTION_VIEW, playUri);

//发送附件

Intent it = new Intent(Intent.ACTION_SEND);  

it.putExtra(Intent.EXTRA_SUBJECT, "The email subject text");  

it.putExtra(Intent.EXTRA_STREAM, "file:///sdcard/eoe.mp3");  

sendIntent.setType("audio/mp3");  

startActivity(Intent.createChooser(it, "Choose Email Client"));

//搜索应用

Uri uri = Uri.parse("market://search?q=pname:pkg_name");  

Intent it = new Intent(Intent.ACTION_VIEW, uri);  

startActivity(it);  

//where pkg_name is the full package path for an application

//进入联系人页面

Intent intent = new Intent();

intent.setAction(Intent.ACTION_VIEW);

intent.setData(People.CONTENT_URI);

startActivity(intent);

//查看指定联系人

Uri personUri = ContentUris.withAppendedId(People.CONTENT_URI, info.id);//info.id联系人ID

Intent intent = new Intent();

intent.setAction(Intent.ACTION_VIEW);

intent.setData(personUri);

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