【问题标题】:App can´t play a video from the SD-Card despite the fact that the code looks fine尽管代码看起来不错,但应用程序无法播放 SD 卡中的视频
【发布时间】:2016-06-14 15:34:18
【问题描述】:

我使用以下代码通过 Android 的 Video View 播放 SD 卡中的视频。我在外部存储根目录中放置了一个名为 Video.mp4 的视频文件。但是,当在我的智能手机上启动我的应用程序并使用下面的 Video.java 代码切换到我的视频活动时,我看到一个带有 OK 按钮的通知,指出无法播放视频。 (德语:“Video kann nicht wiedergegeben werden。”)

我的 AndroidManifest.xml 中是否缺少权限?

提前感谢任何提示和帮助。

package com.noureddine_ouertani.www.wocelli50;

import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.widget.MediaController;
import android.widget.VideoView;


public class Video extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_video);
        getSupportActionBar().setHomeButtonEnabled(true);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        VideoView v = (VideoView) findViewById(R.id.videoView);

        v.setVideoURI(Uri.parse(Environment.getExternalStorageDirectory().getPath() + "/Video.mp4"));
        //Set media controller buttons
        v.setMediaController(new MediaController(this));
        v.requestFocus();
        v.start(); //start Playback

    }
}

编辑: @Alexandre Martin:感谢您的回答。在我的应用程序中嵌入视频没有一般问题。当我创建一个原始文件夹并将视频 testvideo.mp4 放入其中时,然后替换

v.setVideoURI(Uri.parse(Environment.getExternalStorageDirectory().getPath() + "/Video.mp4"));

 v.setVideoURI(Uri.parse("android.resource://com.noureddine_ouertani.www.wocelli50/"+ R.raw.testvideo));

在我的代码中,一切正常,我看到我的视频在我的应用程序中播放。 备注:我不得不将 Video.mp4 重命名为 testvideo.mp4,因为从 raw 文件夹调用的视频不允许使用大写字母。 我的问题只是在我的 SD 卡上获取视频的路径。

@Lonnie Zamora:感谢您的回答。这似乎不是格式或编码问题。 testvideo.mp4 只是 Video.mp4 重命名并放在我的原始文件夹中。它与下面的代码配合得很好:

package com.noureddine_ouertani.www.wocelli50;

import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.MediaController;
import android.widget.VideoView;


public class Video extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_video);
        getSupportActionBar().setHomeButtonEnabled(true);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        VideoView v = (VideoView) findViewById(R.id.videoView);

        v.setVideoURI(Uri.parse("android.resource://com.noureddine_ouertani.www.wocelli50/"+ R.raw.testvideo));
        //Set media controller buttons
        v.setMediaController(new MediaController(this));
        v.requestFocus();
        v.start(); //start Playback

    }
}

@CommonsWare:感谢您的回答。我试过你的建议,但没有解决问题。

最好的问候,

编辑 2: @CommonsWare 这似乎不是缺少权限或缺少权限请求的问题。我实现了以下运行时权限逻辑并看到“视频正在播放。不需要权限请求。”这对我来说意味着 (Manifest.permission.READ_EXTERNAL_STORAGE == PackageManager.PERMISSION_GRANTED) 是真的

package com.noureddine_ouertani.www.wocelli50;

import android.Manifest;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.widget.MediaController;
import android.widget.Toast;
import android.widget.VideoView;

public class Video extends AppCompatActivity {

    final int REQUEST_READ_EXTERNAL_STORAGE = 1;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_video);


        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {



            // Should we show an explanation?
            if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_EXTERNAL_STORAGE)) {
                Toast.makeText(getApplicationContext(), "Show explanation for requesting the permission to read the SD-card.", Toast.LENGTH_SHORT).show();
                // Show an expanation to the user *asynchronously* -- don't block
                // this thread waiting for the user's response! After the user
                // sees the explanation, try again to request the permission.

            } else {

                // No explanation needed, we can request the permission.
                Toast.makeText(getApplicationContext(), "No explanation needed, we can request the permission.", Toast.LENGTH_SHORT).show();
                ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, REQUEST_READ_EXTERNAL_STORAGE);

                // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
                // app-defined int constant. The callback method gets the
                // result of the request.
        }
        } else {
            playmyvideo();
            Toast.makeText(getApplicationContext(), "Video is playing. No permissioon request was needed.", Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        switch (requestCode) {
            case REQUEST_READ_EXTERNAL_STORAGE: {
                // If request is cancelled, the result arrays are empty.
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    playmyvideo();
                    Toast.makeText(getApplicationContext(), "Video is playing after permissioon was granted.", Toast.LENGTH_SHORT).show();

                } else {
                    Toast.makeText(getApplicationContext(), "permission denied,Disable the functionality that depends on this permission.", Toast.LENGTH_SHORT).show();
                    // permission denied, boo! Disable the
                    // functionality that depends on this permission.
                }
                return;
            } 

            // other 'case' lines to check for other
            // permissions this app might request
        }
    }

    public void playmyvideo(){

        getSupportActionBar().setHomeButtonEnabled(true);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        VideoView v = (VideoView) findViewById(R.id.videoView);
        v.setVideoURI(Uri.parse(Environment.getExternalStorageDirectory().getPath() + "/testvideo.mp4"));
        //v.setVideoURI(Uri.parse("android.resource://com.noureddine_ouertani.www.wocelli50/"+ R.raw.testvideo));

        v.setMediaController(new MediaController(this));
        v.requestFocus();
        v.start(); //start Playback
        }
    }

【问题讨论】:

  • 关于Android Media Playback,它解释了如何读取音频和视频文件,它只需要互联网许可:developer.android.com/guide/topics/media/…
  • 使用日志或 toast 来验证路径是否正确
  • 确保您的视频使用 H.264 编码器进行编码。
  • 见 EDIT 和 EDIT 2

标签: android video sd-card


【解决方案1】:

替换

 Uri.parse(Environment.getExternalStorageDirectory().getPath() + "/Video.mp4")

(这是无效的,因为它缺少一个方案)

与:

Uri.fromFile(new File(Environment.getExternalStorageDirectory(), "Video.mp4"))

【讨论】:

  • 查看原帖中的编辑
  • @NoureddineOuertani:“我的 AndroidManifest.xml 中缺少权限吗?” -- 好吧,您至少需要READ_EXTERNAL_STORAGE,如果您的targetSdkVersion 为23 或更高,则可能需要您实现运行时权限逻辑。见developer.android.com/training/permissions/requesting.html
  • 我在我的 AndroidManifest.xml 中使用了权限READ_EXTERNAL_STORAGE。我的目标SDK确实是23。我刚刚检查了我的build.gradle(Module:app)......我将实现一个运行时权限逻辑并在这里写它是否解决了问题。
  • 见原帖中的 EDIT 2
  • 访问外部 SD 卡的解决方案:v.setVideoURI(Uri.parse("/storage/sdcard1/testvideo.mp4")); 而不是 v.setVideoURI(Uri.parse(Environment.getExternalStorageDirectory().getPath() + "/testvideo.mp4")); 原因:Environment.getExternalStorageDirectory().getPath() == "/storage/emulated/0" Environment.getExternalStorageDirectory().getPath() 在我的智能手机上提供到内部存储芯片的路径(HUAWEI P8) 像 SD 卡一样安装,但不是外部 SD 卡。
【解决方案2】:

解决方案 @all 访问外部SD卡的解决方案:

v.setVideoURI(Uri.parse("/storage/sdcard1/testvideo.mp4")); 

而不是

v.setVideoURI(Uri.parse(Environment.getExternalStorageDirectory().getPath() + "/testvideo.mp4")); 

原因:

Environment.getExternalStorageDirectory().getPath() == "/storage/emulated/0" 

Environment.getExternalStorageDirectory().getPath() 为我的智能手机 (HUAWEI P8) 上的内部存储芯片提供路径,该芯片像 SD 卡一样安装,但不是外部 SD 卡不过。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多