1. 程式人生 > >Android--Uri轉實際路徑詳解

Android--Uri轉實際路徑詳解

通過Uri得到實際路徑,網上方法有很多,但我前幾天試了一下,發現返回的值都是null,後來才發現,Uri的格式在Android4.4之後有了很大的改動。

content://media/extenral/images/media/17766(4.4前)
content://com.android.providers.media.documents/document/image:2706(4.4後)

  1. 4.4之前的方法
    4.4之前的方法網上都有很多,大多數都是基於cursor來實現的。這裡主要講4.4之後的。
  2. 4.4之後的方法
    程式碼在這裡有了,大家可以對照來看。
    http://www.2cto.com/kf/201502/376975.html


    Uri分為三個部分
    content://com.android.providers.media.documents/document/image:2706
    scheme:content://
    authority: com.android.providers.media.documents
    path:document/image:2706

    所以要得到uri對應的檔案路徑
    1、先找到檔案是屬於什麼型別(通過authority來判斷,原始碼中就根據authority的值來分為external_document,media等),可以通過getAuthority()來得到。
    2、解析檔案path的結構,這裡拿MediaDocument舉例
    String docId=DocumentContract.getDocumentId(uri);
    進入這個函式,發現包含getPathSegments(),這就是將uri中的path解析成多個部分,如document和image:2706,image是型別,2706就是ID啦。
    之後當然是判斷型別咯,看看是image還是video還是audio,然後生成一個contentUri,這個時候的後面的就代表的是路徑而不是id了。
    例如,contentUri=content://+authority+/external/image/media
    現在已經知道了,uri對應的id是2706,之後怎麼得到它的資訊呢?對,跟4.4版本之前的一樣也是用cursor,所以有:

 cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
  這是個比較關鍵的函式,cursor相當於一個數據庫裡的游標,ContentResolver是內容解析物件,我們可以把要解析的內容想象成一個數據庫,下面講講這幾個引數的含義:
  uri,就是contentUri了,包含路徑的
  projection,官方解釋是a list of which columns return,意思就是返回哪些列,原始碼中是_data,意思就是返回_data列
  selection,原始碼中是_id=?
  selectionArgs,原始碼中是2706,即圖片id,聯合上面的引數就是在資料庫尋找_id=2706的資料

好了,我們現在可以看到,返回的cursor,就是指向_id=2706的資料中的_data列的資料,其實這個資料就是我們需要的path了。
下面輸出path

int column_index=cursor.getColumnIndex("_data")
String data=cursor.getString(column_index)

好了,其實也蠻簡單的。。。但是我做了好久哎。。