Android mediaScannerConnection.scanFile failing to

2019-05-25 10:27发布

问题:

Should I be using something other than the MediaScannerConnection.scanFile method to refresh the gallery?

After saving a new jpg I run media scanner to refresh the gallery app like so

        MediaScannerConnection.scanFile(this,
                new String[] { fullname }, null,
                new MediaScannerConnection.OnScanCompletedListener() {
            public void onScanCompleted(String path, Uri uri) {
                Log.d("ExternalStorage", "@@@@ Scanned " + path + ":");
                Log.d("ExternalStorage", "@@@@ -> uri=" + uri);
            }
       });

The output of the log shows the following correct output

@@@@ Scanned /data/data/com.mypackage/files/skit_106_01.jpg:

@@@@ -> uri=content://media/external/images/media/95

The gallery app shows no media available

This code has been working perfectly for some time now. It was only when I created an Android avd against version 4.4.2 for further testing that the problem has surfaced.

The code I have seems to be the recommended way of refreshing the gallery app according to Androids documentation so maybe this issue is related to the way I am saving the file, the code for which is as follows.

UPDATE

The code checks for external storage availability and will write to external storage and if external storage is not available it will write the file to internal storage.

    private void doSave(String fname, boolean doShare) {
        fname = "skit_"+mCurrentSkitId +
                "_"+mSkitManager.getCurrentFrameCount(
                        mCurrentSkitId)+1;
        Log.d(TAG, "@@@@ doSave fName = " + fname + " Current skit id = " + mCurrentSkitId);
        CharSequence text = getResources().getString(R.string.saved_as)
                + " " + fname;
        try {
            Bitmap b = mMainView.getSaveBitmap();
            if (b == null) {
                text = getResources().getString(R.string.save_fail_1);
                ;
                Toast.makeText(this, text, Toast.LENGTH_LONG).show();
                return;
            }
            fname = FileUtils.replaceInvalidFileNameChars(fname);
            String value = fname;
            File folder = FileUtils.getWritableFolder(this);
            /*
             * String folder =
             * Environment.getExternalStorageDirectory().toString() +
             * "/Pictures"; try { folder =
             * Environment.getExternalStoragePublicDirectory
             * (Environment.DIRECTORY_PICTURES).toString(); } catch
             * (NoSuchFieldError e) {
             * 
             * }
             */
            String ext = ".jpg";
            if (mPrefs.getString("format", "JPG").equals("PNG"))
                ext = ".png";
            String fullname = folder.getAbsolutePath() + File.separator + value
                    + ext;
            Map<String, String> hm = new HashMap<String, String>();
            hm.put("filename", fullname);
            FileOutputStream fos;
            if (folder == getFilesDir())
                fos = openFileOutput(value + ext, Context.MODE_WORLD_WRITEABLE);
            else {
                File f2 = new File(fullname);
                fos = new FileOutputStream(f2);
            }
            b.compress(CompressFormat.JPEG, 95, fos);
            fos.close();
            String[] str = new String[1];
            str[0] = fullname;
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.FROYO) {
                MediaScannerConnection.scanFile(this,
                        new String[] { fullname }, null,
                        new MediaScannerConnection.OnScanCompletedListener() {
                    public void onScanCompleted(String path, Uri uri) {
                        Log.d("ExternalStorage", "@@@@ Scanned " + path + ":");
                        Log.d("ExternalStorage", "@@@@ -> uri=" + uri);
                    }
               });
            }
            text = text + value + ext + " "
                    + getResources().getString(R.string.saved_end);
            ;
            mLastSaveName = value;
            setDetailTitle();
            mSkitManager.createFrame(mCurrentSkitId, fullname);
        } catch (Exception e) {
            Map<String, String> hm = new HashMap<String, String>();
            hm.put("text", e.toString());
            e.printStackTrace();
            text = getResources().getString(R.string.save_fail_2)
                    + e.toString();
        } catch (Error e) {
            Map<String, String> hm = new HashMap<String, String>();
            hm.put("text", e.toString());
            e.printStackTrace();
            text = getResources().getString(R.string.save_fail_2)
                    + e.toString();
        }
        Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
    }

The code that does the check for external storage availability looks like this

public static File getWritableFolder(Context context) {
    File folder = context.getFilesDir();
    if (externalStorageAvailable()) {
        try {
            folder = Environment
                    .getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
            if (!folder.exists() || !folder.canWrite()) {
                folder = Environment
                        .getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
            }
            if (!folder.exists() || !folder.canWrite()) {
                folder = Environment.getExternalStorageDirectory();
            }
        } catch (Exception e) {
            folder = Environment.getExternalStorageDirectory();
        } catch (Error e) {
            folder = Environment.getExternalStorageDirectory();
        }
        if (!folder.exists() || !folder.canWrite()) {
            folder = context.getFilesDir();
        }
    }
    return folder;
}

private static boolean externalStorageAvailable() {
    boolean mExternalStorageAvailable;
    boolean mExternalStorageWriteable;
    String state = Environment.getExternalStorageState();

    if (state.equals(Environment.MEDIA_MOUNTED)) {
        // We can read and write the media
        mExternalStorageAvailable = mExternalStorageWriteable = true;
    } else if (state.equals(Environment.MEDIA_MOUNTED_READ_ONLY)) {
        // We can only read the media
        mExternalStorageAvailable = true;
        mExternalStorageWriteable = false;
    } else {
        // Something else is wrong. It may be one of many other states, but
        // all we need
        // to know is we can neither read nor write
        mExternalStorageAvailable = mExternalStorageWriteable = false;
    }
    return mExternalStorageAvailable && mExternalStorageWriteable;
}

If anyone is able to pick holes in any of the above that might help to solve this issue then that would be great.

回答1:

i was having mixed results with MediaScannerConnection so i used the sendBroadcast method instead. I do not know if the sendBroadcast method is not standard/should not be used but it works for me.

public void galleryAddPic(File currentPhotoPath) {  
    Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
    Uri contentUri = Uri.fromFile(currentPhotoPath);
    mediaScanIntent.setData(contentUri);
    this.sendBroadcast(mediaScanIntent);
}

Also regarding the MediaScannerConnection : https://stackoverflow.com/a/4825615/1497188