为什么新的 MediaStore 文件是空的?

发布于 2025-01-14 03:21:36 字数 2181 浏览 3 评论 0原文

我正在尝试升级我的应用程序以使用范围存储。 (是的,我应该 一年前完成的。)旧版本写入目录中的文件 相对于Environment.getExternalStorageDirectory()。新版本 从 MediaStore.Audio.Media.getContentUri() 写入 uri。我的代码没有 在媒体存储目标目录中创建文件时出现问题,但是 文件为空。

我的代码如下。我正在 targetSdkVersion 29 下编译。我已经设置好了 所以我可以通过设置来比较旧版本和新版本 useMediaStore 为 true 或 false。两个版本都调用相同的 doSave() 常规。

doSave 启动一个异步进程来写入文件,显示 进度条,并报告结果。在流程的工作结束时 OutputStream.write 被调用,我们跟踪字节数 书面。整个文件写入后,我们调用OutputStream.close(),并且 报告写入的字节数。

当 userMediaStore 为 false 时,fileName 的计算结果为 /storage/emulated/0/MyApp/mySoundFile.mp3 并使用以下命令创建文件 预期长度。当 useMediaStore 为 true 时,uri 的计算结果为 content://media/external_primary/audio/media/112,结果是 与/音乐相同。该文件已创建,但它是空的。 doSave() 运行 两种情况都相同,并报告写入的字节数相同。

奇怪的是 MediaStore 版本偶尔可以工作 正确。然后我改变了一些东西,它就停止工作了,然后把 代码返回到原来的位置并不能恢复该功能。

public static boolean useMediaStore = true;
public void onClick( DialogInterface dialog, int whichButton )
{
    try
    {
        String fileName = "mySoundFile.mp3";
        if ( useMediaStore )
        {
            ContentValues values = new ContentValues();
            values.put( MediaStore.Audio.Media.DISPLAY_NAME, fileName );
            values.put( MediaStore.Images.Media.MIME_TYPE, "audio/mpeg" );
            Uri audioCollection = Build.VERSION.SDK_INT >= 29 ?
                MediaStore.Audio.Media .getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
                : MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
            Uri uri = Utils.getContentResolver().insert( audioCollection, values );
            OutputStream stream = Utils.getContentResolver().openOutputStream( uri );
            doSave( getActivity(), stream );
        }
        else
        {
            File outputDir = new File( Environment.getExternalStorageDirectory(), "MyApp" );
            if ( outputDir != null && ( outputDir.exists() || outputDir.mkdirs() ) )
            {
                File outputFile = new File( outputDir, fileName );
                OutputStream stream = new FileOutputStream( outputFile );
                doSave( getActivity(), stream );
            }
        }
    }
    catch ( IOException e )
    {
        Log.i( "MyApp", "save failed" );
    }
}

I'm trying to upgrade my app to use use scoped storage. (Yes, I should have
done this a year ago.) The old version writes to a File in a directory
relative to Environment.getExternalStorageDirectory(). The new version
writes to a uri from MediaStore.Audio.Media.getContentUri(). My code has no
problem creating files in the mediastore destination directory, but the
files are empty.

My code is below. I'm compiling under targetSdkVersion 29. I've set it up
so I can compare the old version and the new version by setting
useMediaStore to either true or false. Both versions call the same doSave()
routine.

doSave starts an asynchronous process to write the files, display a
progress bar, and report the result. At the working end of the process
OutputStream.write is called, and we keep track of the number of bytes
written. After the entire file is written, we call OutputStream.close(), and
report the number of bytes written.

When userMediaStore is false, fileName evaluates to
/storage/emulated/0/MyApp/mySoundFile.mp3 and the file gets created with the
expected length. When useMediaStore is true, uri evaluates to
content://media/external_primary/audio/media/112, which turns out to be the
same as /Music. The file is created but it is empty. doSave() runs the
same in either case, and reports same number of bytes written.

The curious thing about it is that occasionally the MediaStore version works
correctly. Then I change something and it stops working, and putting the
code back to where it was doesn't restore the function.

public static boolean useMediaStore = true;
public void onClick( DialogInterface dialog, int whichButton )
{
    try
    {
        String fileName = "mySoundFile.mp3";
        if ( useMediaStore )
        {
            ContentValues values = new ContentValues();
            values.put( MediaStore.Audio.Media.DISPLAY_NAME, fileName );
            values.put( MediaStore.Images.Media.MIME_TYPE, "audio/mpeg" );
            Uri audioCollection = Build.VERSION.SDK_INT >= 29 ?
                MediaStore.Audio.Media .getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
                : MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
            Uri uri = Utils.getContentResolver().insert( audioCollection, values );
            OutputStream stream = Utils.getContentResolver().openOutputStream( uri );
            doSave( getActivity(), stream );
        }
        else
        {
            File outputDir = new File( Environment.getExternalStorageDirectory(), "MyApp" );
            if ( outputDir != null && ( outputDir.exists() || outputDir.mkdirs() ) )
            {
                File outputFile = new File( outputDir, fileName );
                OutputStream stream = new FileOutputStream( outputFile );
                doSave( getActivity(), stream );
            }
        }
    }
    catch ( IOException e )
    {
        Log.i( "MyApp", "save failed" );
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

下雨或天晴 2025-01-21 03:21:36

正如blackapps指出的,解决方案是将IS_PENDING添加到ContentValues中。
现在可以正确运行的代码是:

private static Uri contentUri = null;
public void onClick( DialogInterface dialog, int whichButton )
{
    try
    {
        String fileName = "mySoundFile.mp3";
        ContentValues values = new ContentValues();
        values.put( MediaStore.Audio.Media.DISPLAY_NAME, fileName );
        values.put( MediaStore.Images.Media.MIME_TYPE, "audio/mpeg" );
        values.put( MediaStore.Audio.Media.IS_PENDING, 1 );
        Uri audioCollection = Build.VERSION.SDK_INT >= 29 ?
            MediaStore.Audio.Media .getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
            : MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
        contentUri = Utils.getContentResolver().insert( audioCollection, values );
        OutputStream stream = Utils.getContentResolver().openOutputStream( contentUri );
        doSave( getActivity(), stream );
    }
    catch ( IOException e )
    {
        Log.i( "MyApp", "save failed" );
    }
}
protected void onPostExecute( Boolean success ) // part of the ASyncTask that does the saving
{
    if ( success )
    {
        ContentValues details = new ContentValues();
        details.put( MediaStore.Audio.Media.IS_PENDING, 0 );
        Utils.getContentResolver().update( contentUri, details, null, null );
    }
}

As pointed out by blackapps, the solution is to add IS_PENDING to the ContentValues.
The code that now works correctly is:

private static Uri contentUri = null;
public void onClick( DialogInterface dialog, int whichButton )
{
    try
    {
        String fileName = "mySoundFile.mp3";
        ContentValues values = new ContentValues();
        values.put( MediaStore.Audio.Media.DISPLAY_NAME, fileName );
        values.put( MediaStore.Images.Media.MIME_TYPE, "audio/mpeg" );
        values.put( MediaStore.Audio.Media.IS_PENDING, 1 );
        Uri audioCollection = Build.VERSION.SDK_INT >= 29 ?
            MediaStore.Audio.Media .getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
            : MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
        contentUri = Utils.getContentResolver().insert( audioCollection, values );
        OutputStream stream = Utils.getContentResolver().openOutputStream( contentUri );
        doSave( getActivity(), stream );
    }
    catch ( IOException e )
    {
        Log.i( "MyApp", "save failed" );
    }
}
protected void onPostExecute( Boolean success ) // part of the ASyncTask that does the saving
{
    if ( success )
    {
        ContentValues details = new ContentValues();
        details.put( MediaStore.Audio.Media.IS_PENDING, 0 );
        Utils.getContentResolver().update( contentUri, details, null, null );
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文