我正在开发播放媒体的cordova插件。(视频)
我尝试使用Android的mediaPlayer类播放视频。
没有错误,我成功地完成了准备步骤。
但是在“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;
}
}
告诉我为什么。
您正在尝试启动MediaPlayer,而不是从主线程启动。只需调用runOnUiThread函数,一切都应该正常。
我有一个错误,只有创建视图层次结构的原始线程才能接触它的视图。但我不知道如何在多线程中处理ui,比如列表视图,我也不知道该放在哪里。
这个类有一个例外:“只有创建视图层次结构的原始线程才能接触其视图”。 我知道这可能是因为我使用了async,但我是android开发的新手,即使阅读了Stackoverflow上的其他案例,我也没能安排好它。欢迎光临! 我的班级: 这是我尝试使用onPostExecute后的日志:
我正在使用MultipartEntityBuilder将图像发送到php服务器,我将图片和视频发送到设备摄像头的目录中,我需要将文件保存在新的ArrayList上并将其发送到php服务器。 总是报告错误: 我的代码 更新
我在Android中构建了一个简单的音乐播放器。每首歌的视图都包含一个SeekBar,实现如下: 这很好用。现在我想要一个计时器来计算歌曲进度的秒/分钟。因此,我在布局中放置了一个文本视图,在onCreate()中使用findViewById()获取它,并在。设置进度(pos): 但最后一行给了我一个例外: Android看法ViewRoot$CalledFromErrorThreadExcept
这是我所有的代码。
我正在为小应用程序设计UnitTest。这个应用程序说明您使用的是什么命理数字出生日期。我有一个问题,我该调用检查数字并将值放入TextView的方法。我有一个错误 ' 我的布局:` 我想测试的方法:'