在真实Android设备上测试应用时的URI无效,但在模拟器

时间:2016-01-08 06:58:36

标签: android uri emulation filepath

我有一个应用程序可以提取上传图像的GPS坐标(通过ExifInterface) - 为了做到这一点,它必须将图像的Uri转换为其文件路径。它适用于在仿真器(两个仿真器,不同的Android版本)上进行测试,但在真正的Android设备上进行测试时不起作用。

真实设备上的错误输出:

01-08 19:39:35.203: D/fr.free.nrw.commons.upload.ShareActivity(16980): Uri: content://media/external/images/media/10716
01-08 19:39:35.203: W/Image(16980): java.lang.IllegalArgumentException: Invalid URI: content://media/external/images/media/10716
01-08 19:39:35.203: W/Image(16980):     at android.provider.DocumentsContract.getDocumentId(DocumentsContract.java:752)
01-08 19:39:35.203: W/Image(16980):     at fr.free.nrw.commons.upload.FilePathConverter.getFilePath(FilePathConverter.java:31)
01-08 19:39:35.203: W/Image(16980):     at fr.free.nrw.commons.upload.ShareActivity.onCreate(ShareActivity.java:193)
01-08 19:39:35.203: W/Image(16980):     at android.app.Activity.performCreate(Activity.java:6289)
01-08 19:39:35.203: W/Image(16980):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1119)
01-08 19:39:35.203: W/Image(16980):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2655)
01-08 19:39:35.203: W/Image(16980):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2767)
01-08 19:39:35.203: W/Image(16980):     at android.app.ActivityThread.access$900(ActivityThread.java:177)
01-08 19:39:35.203: W/Image(16980):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1449)
01-08 19:39:35.203: W/Image(16980):     at android.os.Handler.dispatchMessage(Handler.java:102)
01-08 19:39:35.203: W/Image(16980):     at android.os.Looper.loop(Looper.java:145)
01-08 19:39:35.203: W/Image(16980):     at android.app.ActivityThread.main(ActivityThread.java:5951)
01-08 19:39:35.203: W/Image(16980):     at java.lang.reflect.Method.invoke(Native Method)
01-08 19:39:35.203: W/Image(16980):     at java.lang.reflect.Method.invoke(Method.java:372)
01-08 19:39:35.203: W/Image(16980):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
01-08 19:39:35.203: W/Image(16980):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)

调用FilePathConverter的ShareActivity中的相关代码:

    mediaUriString = mediaUri.toString();
    Log.d(TAG, "Uri: " + mediaUriString);
    //convert image Uri to file path
    FilePathConverter uriObj = new FilePathConverter(this, mediaUri);
    String filePath = uriObj.getFilePath();

将图像Uri转换为文件路径的FilePathCoverter代码:

public class FilePathConverter {

    private Uri uri;
    private Context context;

    public FilePathConverter(Context context, Uri uri) {
        this.context = context;
        this.uri = uri;
    }

    public String getFilePath(){

        String filePath ="";

        try {
            // Will return "image:x*"
            String wholeID = DocumentsContract.getDocumentId(uri);

            // Split at colon, use second item in the array
            String id = wholeID.split(":")[1];
            String[] column = {MediaStore.Images.Media.DATA};

            // where id is equal to
            String sel = MediaStore.Images.Media._ID + "=?";
            Cursor cursor = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                    column, sel, new String[]{id}, null);

            int columnIndex = cursor.getColumnIndex(column[0]);

            if (cursor.moveToFirst()) {
                filePath = cursor.getString(columnIndex);
            }
            cursor.close();

            Log.d("Image", "File path: " + filePath);
            return filePath;
        } catch (IllegalArgumentException e) {
            Log.w("Image", e);
            return null;
        }
    }
}

如果需要,可以在GitHub找到整个代码库。我能找到的最接近的答案是How to use ExifInterface with a stream or URI,但它也不起作用。

我的模拟器上的输出:

01-08 08:11:48.421: D/fr.free.nrw.commons.upload.ShareActivity(2188): Uri: content://com.android.providers.media.documents/document/image%3A24
01-08 08:11:48.421: D/fr.free.nrw.commons.upload.ShareActivity(2188): Ext storage dir: /storage/sdcard
01-08 08:11:48.429: D/fr.free.nrw.commons.upload.ShareActivity(2188): Filepath: /storage/sdcard/Download/20151231_234740.jpg
01-08 08:11:48.429: D/fr.free.nrw.commons.upload.ShareActivity(2188): Calling GPSExtractor
01-08 08:11:48.436: D/fr.free.nrw.commons.upload.ShareActivity(2188): Decimal coords of image: -36.85254286111111|174.7669525

真实设备上的输出:

01-08 21:07:59.558: D/fr.free.nrw.commons.upload.ShareActivity(30904): Uri: content://media/external/images/media/10777
01-08 21:07:59.558: D/fr.free.nrw.commons.upload.ShareActivity(30904): Ext storage dir: /storage/emulated/0

2 个答案:

答案 0 :(得分:13)

如果你想从uri获得真正的路径而不是使用这种方法。

 @override
    public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState){
            Log.v("222","oncreateview");
            View v = inflater.inflate(R.layout.fragment_crime, parent, false);
            Log.v("inflater?","inflater?");
            mTitleField = (EditText)v.findViewById(R.id.crime_title);
            mTitleField.addTextChangedListener(new TextWatcher() {
                @Override
                public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

                }

                @Override
                public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                mCrime.setmTitle(charSequence.toString());
                }

                @Override
                public void afterTextChanged(Editable editable) {

                }
            });

答案 1 :(得分:1)

试试这个,

input[type='text']:not(#txtSearch), input[type=password], textarea { //My styles }

因为你的模拟器不能有SD卡。

供参考。     How to get my Android device Internal Download Folder path