Uri与UriMatcher

一.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|/

二.Uri源码

位置:frameworks\base\core\java\android\net\Uri.java

android中对Uri分为两大类:Hierarchical和opaque
Hierarchical:以”//”分级的Uri,比如:http://google.com,content://com.example.project:200/
opaque:没有使用”//”分级的Uri,比如:mailto:nobody@google.com

根据这个分类设定,Uri这个抽象类的实现类和继承关系如下:
这里写图片描述

//Uri是一个抽象类,支持序列化。提供了各种函数用于获取组成Uri的各个部分(scheme,authority,path)
public abstract class Uri implements Parcelable, Comparable<Uri> {
   //私有构造函数
   private Uri() {}
    /**
         * Returns true if this URI is hierarchical like "http://google.com".
     * Absolute URIs are hierarchical if the scheme-specific part starts with
     * a '/'. Relative URIs are always hierarchical.
     */
    //当前uri是否是Hierarchical类型
    public abstract boolean isHierarchical();   
    /**
     * Returns true if this URI is opaque like "mailto:nobody@google.com". The
     * scheme-specific part of an opaque URI cannot start with a '/'.
     */
    //当前uri是否是Opaque类型
    public boolean isOpaque() {
        return !isHierarchical();
    }    
    /**
     * Gets the scheme of this URI. Example: "http"
     *
     * @return the scheme or null if this is a relative URI
     */
    @Nullable
    public abstract String getScheme();    
    /**
     * Gets the decoded authority part of this URI. For
     * server addresses, the authority is structured as follows:
     * {@code [ userinfo '@' ] host [ ':' port ]}
     *
     * <p>Examples: "google.com", "bob@google.com:80"
     *
     * @return the authority for this URI or null if not present
     */
    @Nullable
    public abstract String getAuthority();    
    /**
     * Gets the decoded user information from the authority.
     * For example, if the authority is "nobody@google.com", this method will
     * return "nobody".
     *
     * @return the user info for this URI or null if not present
     */
    @Nullable
    public abstract String getUserInfo();    
    /**
     * Gets the encoded host from the authority for this URI. For example,
     * if the authority is "bob@google.com", this method will return
     * "google.com".
     *
     * @return the host for this URI or null if not present
     */
    @Nullable
    public abstract String getHost();    
    /**
     * Gets the port from the authority for this URI. For example,
     * if the authority is "google.com:80", this method will return 80.
     *
     * @return the port for this URI or -1 if invalid or not present
     */
    public abstract int getPort();    
    /**
     * Gets the decoded path.
     *
     * @return the decoded path, or null if this is not a hierarchical URI
     * (like "mailto:nobody@google.com") or the URI is invalid
     */
    @Nullable
    public abstract String getPath();    
    /**
     * Creates a Uri from a file. The URI has the form
     * "file://<absolute path>". Encodes path characters with the exception of
     * '/'.
     *
     * <p>Example: "file:///tmp/android.txt"
     *
     * @throws NullPointerException if file is null
     * @return a Uri for the given file
     */
    //提供获取Uri对象的静态函数。返回代表File的uri
    public static Uri fromFile(File file) {
        if (file == null) {
            throw new NullPointerException("file");
        }

        PathPart path = PathPart.fromDecoded(file.getAbsolutePath());
        return new HierarchicalUri(
                "file", Part.EMPTY, path, Part.NULL, Part.NULL);
    }    

    /**
     * Creates a Uri which parses the given encoded URI string.
     *
     * @param uriString an RFC 2396-compliant, encoded URI
     * @throws NullPointerException if uriString is null
     * @return Uri for this given uri string
     */
    //提供获取Uri对象的静态函数。返回传入的string包装成uri
    public static Uri parse(String uriString) {
        return new StringUri(uriString);
    }    
    /**
     * Creates an opaque Uri from the given components. Encodes the ssp
     * which means this method cannot be used to create hierarchical URIs.
     *
     * @param scheme of the URI
     * @param ssp scheme-specific-part, everything between the
     *  scheme separator (':') and the fragment separator ('#'), which will
     *  get encoded
     * @param fragment fragment, everything after the '#', null if undefined,
     *  will get encoded
     *
     * @throws NullPointerException if scheme or ssp is null
     * @return Uri composed of the given scheme, ssp, and fragment
     *
     * @see Builder if you don't want the ssp and fragment to be encoded
     */
    //提供获取Uri对象的静态函数。根据提供的参数返回Opaque类型的uri
    public static Uri fromParts(String scheme, String ssp,
            String fragment) {
        if (scheme == null) {
            throw new NullPointerException("scheme");
        }
        if (ssp == null) {
            throw new NullPointerException("ssp");
        }

        return new OpaqueUri(scheme, Part.fromDecoded(ssp),
                Part.fromDecoded(fragment));
    }    

以上是Uri.java中比较常用的几个函数。至于其子类OpaqueUri,HierarchicalUri ,StringUri,实现上并不是太难,不做展开。这里需要特殊说明的是Uri的内部类Builder,这个Builder是一个辅助类,用于Uri对象的构建,并发不安全。

    public static final class Builder {

        private String scheme;
        private Part opaquePart;
        private Part authority;
        private PathPart path;
        private Part query;
        private Part fragment;

        /**
         * Constructs a new Builder.
         */
        //Builder的构造函数
        public Builder() {}
        //提供了众多的函数去获取Builder对象。
        public Builder scheme(String scheme) {
            this.scheme = scheme;
            return this;
        }    
        ......
        /**
         * Constructs a Uri with the current attributes.
         *
         * @throws UnsupportedOperationException if the URI is opaque and the
         *  scheme is null
         */
        //获取Uri对象
        public Uri build() {
            if (opaquePart != null) {
                if (this.scheme == null) {
                    throw new UnsupportedOperationException(
                            "An opaque URI must have a scheme.");
                }

                return new OpaqueUri(scheme, opaquePart, fragment);
            } else {
                // Hierarchical URIs should not return null for getPath().
                PathPart path = this.path;
                if (path == null || path == PathPart.NULL) {
                    path = PathPart.EMPTY;
                } else {
                    // If we have a scheme and/or authority, the path must
                    // be absolute. Prepend it with a '/' if necessary.
                    if (hasSchemeOrAuthority()) {
                        path = PathPart.makeAbsolute(path);
                    }
                }

                return new HierarchicalUri(
                        scheme, authority, path, query, fragment);
            }
        }         
        ......
   }   

Builder 对象的构建有多种方式,可以根据组成Uri的各个部分花式获取Builder 对象,具体可以详细看源码。之后使用Builder 对象调用build()函数即可获得Uri对象。至于获取的Uri对象的类型是Hierarchical,还是opaque,或者是content,file,git等等,就看你是传入什么参数去获取Builder 对象了。


三. UriMatcher的源码

位置:frameworks\base\core\java\android\content\UriMatcher.java

Uri与UriMatcher的关系:
Uri保存了资源文件的路径,代表了资源文件。一个应用内有很多资源,如果我们想把其中一部分资源共享给其他应用,并集中起来管理,方便查询和匹配,这就需要另外一个类来协调,这个类就是UriMatcher。

public class UriMatcher
{
    public static final int NO_MATCH = -1; //没有匹配到uri,返回-1
    private static final int EXACT = 0;
    private static final int NUMBER = 1; //此处用来代表通配符"#"
    private static final int TEXT = 2; //此处用来代表任意字符"*"
    //mCode是UriMatcher用来标识Uri的,如果匹配到Uri,则返回此mCode,否则返回NO_MATCH
    private int mCode;
    private int mWhich;//用来标识特殊字符的,比如通配符"#",任意字符"*"
    private String mText;//用来保存Uri的某个组成部分的。比如Scheme等
    private ArrayList<UriMatcher> mChildren;//使用ArrayList来保存完整的Uri
    /**
     * Creates the root node of the URI tree.
     *
     * @param code the code to match for the root URI
     */
    public UriMatcher(int code)
    {
        mCode = code;
        mWhich = -1;
        mChildren = new ArrayList<UriMatcher>();
        mText = null;
    }

    private UriMatcher()
    {
        mCode = NO_MATCH;
        mWhich = -1;
        mChildren = new ArrayList<UriMatcher>();
        mText = null;
    }

    /**
     * Add a URI to match, and the code to return when this URI is
     * matched. URI nodes may be exact match string, the token "*"
     * that matches any text, or the token "#" that matches only
     * numbers.
     * <p>
     * Starting from API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2},
     * this method will accept a leading slash in the path.
     *
     * @param authority the authority to match
     * @param path the path to match. * may be used as a wild card for
     * any text, and # may be used as a wild card for numbers.
     * @param code the code that is returned when a URI is matched
     * against the given components. Must be positive.
     */
    /*保存Uri。把Uri分段成authority和path两部分,当成参数传入addURI()函数中。
    *必须传入code,且不小于0,否则抛出异常。
    */
    public void addURI(String authority, String path, int code)
    {
        if (code < 0) {
            throw new IllegalArgumentException("code " + code + " is invalid: it must be positive");
        }
        //把path按照"/"分割并保存到string数组tokens 中。
        String[] tokens = null;
        if (path != null) {
            String newPath = path;
            // Strip leading slash if present.
            if (path.length() > 1 && path.charAt(0) == '/') {
                newPath = path.substring(1);
            }
            tokens = newPath.split("/");
        }

        int numTokens = tokens != null ? tokens.length : 0;
        UriMatcher node = this;
        //循环tokens数组
        for (int i = -1; i < numTokens; i++) {
            //先把authority保存到当前UriMatcher对象的ArrayList集合mChildren中
            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;
                }
            }
            //新构建UriMatcher对象,把分割的path分别保存进去,形成单链表结构
            if (j == numChildren) {
                // Child not found, create it
                child = new UriMatcher();
                //如果path分割后得到通配符"#",mWhich赋值为NUMBER
                if (token.equals("#")) {
                    child.mWhich = NUMBER;
                //如果path分割后得到通配符"*",mWhich赋值为TEXT
                } else if (token.equals("*")) {
                    child.mWhich = TEXT;
                } else {
                    child.mWhich = EXACT;
                }
                child.mText = token;//保存分割的path或者authority
                //新构建的UriMatcher对象保存到当前操作节点的ArrayList集合中
                node.mChildren.add(child);
                node = child;//操作节点后移
            }
        }
        node.mCode = code;
    }

    /**
     * Try to match against the path in a url.
     *
     * @param uri       The url whose path we will match against.
     *
     * @return  The code for the matched node (added using addURI), 
     * or -1 if there is no matched node.
     */
    //循环链表结构的UriMatcher去匹配Uri,匹配到返回mCode,否则返回NO_MATCH
    public int match(Uri uri)
    {
        final List<String> pathSegments = uri.getPathSegments();
        final int li = pathSegments.size();

        UriMatcher node = this;

        if (li == 0 && uri.getAuthority() == null) {
            return this.mCode;
        }
        //循环Uri的构成(authority+path)
        for (int i=-1; i<li; i++) {
            //获取authority或者path的分割部分
            String u = i < 0 ? uri.getAuthority() : pathSegments.get(i);
            ArrayList<UriMatcher> list = node.mChildren;
            if (list == null) {
                break;
            }
            node = null;
            int lj = list.size();
            //循环当前UriMatcher的ArrayList集合
            for (int j=0; j<lj; j++) {
                UriMatcher n = list.get(j);
          which_switch:
          //匹配authority或者path的分割部分
                switch (n.mWhich) {
                    case EXACT:
                        if (n.mText.equals(u)) {
                            node = n;
                        }
                        break;
                    case NUMBER:
                        int lk = u.length();
                        for (int k=0; k<lk; k++) {
                            char c = u.charAt(k);
                            if (c < '0' || c > '9') {
                                break which_switch;
                            }
                        }
                        node = n;
                        break;
                    case TEXT:
                        node = n;
                        break;
                }
                if (node != null) {
                    break;
                }
            }
            if (node == null) {
                return NO_MATCH;
            }
        }

        return node.mCode;
    }
}

从代码上看,UriMatcher的存储结构如下:
这里写图片描述


四. UriMatcher的实际使用

位置:packages\providers\TelephonyProvider\src\com\android\providers\telephony\TelephonyProvider.java

TelephonyProvider借助SQLiteOpenHelper创建了telephony.db数据库,并新建了一些table。希望通过TelephonyProvider共享一些数据给其他应用。这些共享数据的Uri被保存到了UriMatcher中,当其他应用使用Uri通过TelephonyProvider访问这些共享数据时,需要先匹配一下Uri是否在UriMatcher中,如果存在,则允许访问,如果不存在,则不允许访问。避免了该应用内所有数据都被公开的可能。

public class TelephonyProvider extends ContentProvider
{
    //数据库与表
    private static final String DATABASE_NAME = "telephony.db";
    private static final String CARRIERS_TABLE = "carriers";
    private static final String CARRIERS_TABLE_TMP = "carriers_tmp";
    private static final String SIMINFO_TABLE = "siminfo";
    private static final String SIMINFO_TABLE_TMP = "siminfo_tmp";  
    private static final UriMatcher s_urlMatcher = new UriMatcher(UriMatcher.NO_MATCH);

    ...... 
    //Uri加入到UriMatcher中
    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", "carriers/preferapnset", URL_PREFERAPNSET);

        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.addURI("telephony", "carriers/preferapnset/subId/*",
                URL_PREFERAPNSET_USING_SUBID);

        s_urlMatcher.addURI("telephony", "carriers/update_db", URL_UPDATE_DB);
        s_urlMatcher.addURI("telephony", "carriers/delete", URL_DELETE);

        // Only called by DevicePolicyManager to manipulate DPC records.
        s_urlMatcher.addURI("telephony", "carriers/dpc", URL_DPC);
        // Only called by DevicePolicyManager to manipulate a DPC record with certain _ID.
        s_urlMatcher.addURI("telephony", "carriers/dpc/#", URL_DPC_ID);
        // Only called by Settings app, DcTracker and other telephony components to get APN list
        // according to whether DPC records are enforced.
        s_urlMatcher.addURI("telephony", "carriers/filtered", URL_FILTERED);
        // Only called by Settings app, DcTracker and other telephony components to get a
        // single APN according to whether DPC records are enforced.
        s_urlMatcher.addURI("telephony", "carriers/filtered/#", URL_FILTERED_ID);
        // Only Called by DevicePolicyManager to enforce DPC records.
        s_urlMatcher.addURI("telephony", "carriers/enforce_managed", URL_ENFORCE_MANAGED);

        s_currentNullMap = new ContentValues(1);
        s_currentNullMap.put(CURRENT, "0");

        s_currentSetMap = new ContentValues(1);
        s_currentSetMap.put(CURRENT, "1");
    }     
    //更该telephony.db数据库
    @Override
    public synchronized int update(Uri url, ContentValues values, String where, String[] whereArgs)
    {
        int count = 0;
        int uriType = URL_UNKNOWN;
        int subId = SubscriptionManager.getDefaultSubscriptionId();

        checkPermission();
        syncBearerBitmaskAndNetworkTypeBitmask(values);

        SQLiteDatabase db = getWritableDatabase();
        //uri匹配才可以更新数据库
        int match = s_urlMatcher.match(url);
        switch (match)
        {    
            case URL_TELEPHONY:
            {
                if (!values.containsKey(EDITED)) {
                    values.put(EDITED, CARRIER_EDITED);
                }

                // Replace on conflict so that if same APN is present in db with edited
                // as UNEDITED or USER/CARRIER_DELETED, it is replaced with
                // edited USER/CARRIER_EDITED
                count = db.updateWithOnConflict(CARRIERS_TABLE, values, where +
                                " and " + IS_NOT_OWNED_BY_DPC, whereArgs,
                        SQLiteDatabase.CONFLICT_REPLACE);
                break;
            }        
            ......
            case URL_SIMINFO: {
                count = db.update(SIMINFO_TABLE, values, where, whereArgs);
                uriType = URL_SIMINFO;
                break;
            }

            default: {
                throw new UnsupportedOperationException("Cannot update that URL: " + url);
            }
        }            
        ......
        return count;
    }        

五.常用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. 要使用这个必须在配置文件中加入

发送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, “[url=]file:///sdcard/mysong.mp3[/url]”);
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(“[url=]file:///sdcard/song.mp3[/url]”);
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(“[url=]file:///sdcard/download/everything.mp3[/url]”);
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, “[url=]file:///sdcard/eoe.mp3[/url]”);
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);

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值