我正在开发用于播放Media的cordova插件。(视频)
我尝试使用适用于Android的mediaPlayer Class播放视频。
没有错误,我成功完成了准备步骤。
但在" onPrepared"功能,我尝试使用" mediaController.show()& mediaPlayer.start()" API,
有错误[logcat]:
E/AndroidRuntime: FATAL EXCEPTION: JavaBridge
Process: yongju.example.media, PID: 3779
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6891)
at android.view.ViewRootImpl.recomputeViewAttributes(ViewRootImpl.java:3247)
at android.view.ViewGroup.recomputeViewAttributes(ViewGroup.java:1324)
at android.view.ViewGroup.recomputeViewAttributes(ViewGroup.java:1324)
at android.view.ViewGroup.recomputeViewAttributes(ViewGroup.java:1324)
at android.view.View.setFlags(View.java:11580)
at android.view.View.setKeepScreenOn(View.java:7554)
at android.view.SurfaceView$1.handleMessage(SurfaceView.java:135)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.os.HandlerThread.run(HandlerThread.java:61)
有我的代码[cordova插件]:
package com.cordova.plugin.toast;
import org.apache.cordova.CordovaWebView;
import org.json.JSONArray;
import org.json.JSONException;
import android.content.Context;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Looper;
import android.util.Log;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaActivity;
import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaPlugin;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.MediaController;
import android.media.MediaPlayer;
import android.view.SurfaceHolder;
import android.os.Handler;
import android.widget.VideoView;
import java.io.IOException;
public class Media extends CordovaPlugin implements SurfaceHolder.Callback, MediaPlayer.OnPreparedListener, MediaController.MediaPlayerControl {
class MediaPlayerState {
protected String NONE = "NONE";
protected String IDLE = "IDLE";
protected String READY = "READY"; // prepared
protected String PLAYING = "PLAYING";
protected String PAUSED = "PAUSED";
}
private MediaPlayerState mPlayerState = new MediaPlayerState();
private static final String TAG = "Media";
private FrameLayout fraLayout;
private CordovaWebView webView;
private MediaPlayer mediaPlayer;
private MediaController mcontroller;
private VideoView videoView;
private SurfaceHolder surfaceHolder;
private String src, state;
private CordovaActivity nowActivity;
private Context context;
private CallbackContext callbackContext;
@Override
public void initialize(CordovaInterface cordova, CordovaWebView webView) {
super.initialize(cordova, webView);
this.webView = webView;
nowActivity = (CordovaActivity)this.cordova.getActivity();
context = this.cordova.getActivity().getApplicationContext();
}
@Override
public boolean execute(String action, JSONArray args, final CallbackContext callbackContext) throws JSONException {
this.callbackContext = callbackContext;
if (action.equals("create")) {
Log.v(TAG, "**************Success 'create'**************");
createVideoContainer();
}
else if (action.equals("open")) {
Log.v(TAG, "**************Success 'open'**************");
openVideoStream(args);
}
else if (action.equals("play")) {
Log.v(TAG, "**************Success 'play'**************");
playVideoStream(args);
}
else if (action.equals("stop")) {
Log.v(TAG, "**************Success 'stop'**************");
stopVideoStream(args);
}
else if (action.equals("pause")) {
Log.v(TAG, "**************Success 'pause'**************");
pauseVideoStream(args);
}
else {
return false;
}
return true;
}
private void createVideoContainer() {
state = mPlayerState.NONE;
fraLayout = (FrameLayout) this.webView.getView().getParent();
FrameLayout.LayoutParams fraLayoutParam = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
fraLayoutParam.setMargins(80, 80, 80, 80);
videoView = new VideoView(cordova.getActivity());
videoView.setLayoutParams(fraLayoutParam);
videoView.setVisibility(View.VISIBLE);
surfaceHolder = videoView.getHolder();
surfaceHolder.addCallback(this);
mcontroller = new MediaController(this.cordova.getActivity());
}
private void openVideoStream(JSONArray args) throws JSONException {
String id = args.getString(0);
src = args.getString(1);
Log.v(TAG, "media::open() - id =" + id);
}
private void playVideoStream(JSONArray args) throws JSONException {
String id = args.getString(0);
Log.v(TAG, "media::play() - id =" + id);
if(state == mPlayerState.IDLE) {
// If 'prepared' is not completed, must again 'prepare'
}
else{
mediaPlayer.start();
state = mPlayerState.PLAYING;
}
}
private void pauseVideoStream(JSONArray args) throws JSONException {
String id = args.getString(0);
Log.v(TAG, "media::pause() - EVENT_STATE -> PAUSED");
mediaPlayer.pause();
state = mPlayerState.PAUSED;
}
private void stopVideoStream(JSONArray args) throws JSONException {
String id = args.getString(0);
Log.v(TAG, "media::stop() - EVENT_STATE -> IDLE");
mediaPlayer.stop();
state = mPlayerState.IDLE;
//videoView.setVisibility(View.INVISIBLE);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
Log.v(TAG, "*********************************************************media::surfaceCreated - Start MediaPlayer Object create : " + src);
if (mediaPlayer == null) {
mediaPlayer = new MediaPlayer();
}
else {
mediaPlayer.reset();
}
state = mPlayerState.IDLE;
try {
String fileName = "android.resource://yongju.example.media/raw/sample";
Uri fileUri = Uri.parse(fileName);
mediaPlayer.setDataSource(context, fileUri); // for testing In local file
mediaPlayer.setDisplay(holder); // Call Screen
} catch (IOException e) {
e.printStackTrace();
}
mediaPlayer.setOnCompletionListener(completionListener);
mediaPlayer.setOnVideoSizeChangedListener(sizeChangeListener);
mediaPlayer.setOnPreparedListener(this);
mediaPlayer.setScreenOnWhilePlaying(true);
//mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.prepareAsync(); // Ready for loading Video
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Log.v(TAG, "*********************************************************media::surfaceChanged");
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.v(TAG, "*********************************************************media::surfaceDestroyed");
mediaPlayer.release();
}
MediaPlayer.OnCompletionListener completionListener = new MediaPlayer.OnCompletionListener() {
/**
* Listener for playing video is completed
* @param mediaPlayer : Now mediaPlayer that is controlled
*/
@Override
public void onCompletion(MediaPlayer mediaPlayer) {
}
};
MediaPlayer.OnVideoSizeChangedListener sizeChangeListener = new MediaPlayer.OnVideoSizeChangedListener() {
@Override
public void onVideoSizeChanged(MediaPlayer mediaPlayer, int width, int height) {
}
};
@Override
public void onPrepared(MediaPlayer mp) {
Log.v(TAG, "*********************************************************media::prepare completed");
state = mPlayerState.READY;
mcontroller.setMediaPlayer(this);
mcontroller.setAnchorView(videoView);
mcontroller.setEnabled(true);
cordova.getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
if (cordova.getActivity().isFinishing() == false) {
mcontroller.show();
mp.start();
}
}
});
}
@Override
public void start() {
mediaPlayer.start();
}
@Override
public void pause() {
mediaPlayer.pause();
}
@Override
public int getDuration() {
return 0;
}
@Override
public int getCurrentPosition() {
return mediaPlayer.getDuration();
}
@Override
public void seekTo(int pos) {
mediaPlayer.seekTo(pos);
}
@Override
public boolean isPlaying() {
return mediaPlayer.isPlaying();
}
@Override
public int getBufferPercentage() {
return 0;
}
@Override
public boolean canPause() {
return true;
}
@Override
public boolean canSeekBackward() {
return true;
}
@Override
public boolean canSeekForward() {
return true;
}
@Override
public int getAudioSessionId() {
return 0;
}
}
return mediaPlayer.getDuration();
}
@Override
public void seekTo(int pos) {
mediaPlayer.seekTo(pos);
}
@Override
public boolean isPlaying() {
return mediaPlayer.isPlaying();
}
@Override
public int getBufferPercentage() {
return 0;
}
@Override
public boolean canPause() {
return true;
}
@Override
public boolean canSeekBackward() {
return true;
}
@Override
public boolean canSeekForward() {
return true;
}
@Override
public int getAudioSessionId() {
return 0;
}
}
Plz告诉我原因。
答案 0 :(得分:0)
您正试图从主线程启动MediaPlayer。只需调用runOnUiThread函数,一切都应该没问题。
答案 1 :(得分:0)
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
//your implementetion
}
});