0

Я занимаюсь разработкой плагин Cordova для воспроизведения медиа (видео)FATAL ИСКЛЮЧЕНИЕ:. JavaBridge - только исходный поток, который создал иерархию вида может коснуться его мнения

Я стараюсь играть видео с помощью медиаплеера класса для Android.

Не было ошибок, мне удалось подготовиться.

Но в "onPrepared" функции, я стараюсь использовать "mediaController.show() & mediaPlayer.start()" апи,

Существует ошибка [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

Вы пытаетесь запустить MediaPlayer не из основного потока. Просто вызовите функцию runOnUiThread, и все должно быть в порядке.

+0

Я пытаюсь использовать эту функцию, но результат тот же .... –

+0

Есть ли у вас какой-нибудь другой совет для меня ?? PLZ помочь мне .. –

+0

Можете ли вы обновить код, чтобы я мог видеть изменения? Если вы все еще получаете эту ошибку, это означает, что вы все равно пытаетесь выполнить медиаплеер в фоновом потоке. –