WindowLeaked из диалога - PullRequest
       16

WindowLeaked из диалога

0 голосов
/ 04 марта 2012

У меня типичное исключение WindowLeaked

03-03 21: 03: 26.441: ОШИБКА / WindowManager (631): активность com.myapp.Player просочилась в окно com.android.internal.policy.impl.PhoneWindow $ DecorView @ 45136c38, который был первоначально добавлен здесь 03-03 21: 03: 26.441: ОШИБКА / WindowManager (631): android.view.WindowLeaked: действие com.myapp.Player утекло окно com.android.internal.policy.impl.PhoneWindow$DecorView@45136c38, который был первоначально добавлен здесь 03-03 21: 03: 26.441: ОШИБКА / WindowManager (631): в android.view.ViewRoot. (ViewRoot.java:247) 03-03 21: 03: 26.441: ОШИБКА / WindowManager (631): в android.view.WindowManagerImpl.addView (WindowManagerImpl.java:148) 03-03 21: 03: 26.441: ОШИБКА / WindowManager (631): в android.view.WindowManagerImpl.addView (WindowManagerImpl.java:91) 03-03 21: 03: 26.441: ОШИБКА / WindowManager (631): в android.view.Window $ LocalWindowManager.addView (Window.java:424) 03-03 21: 03: 26.441:ОШИБКА / WindowManager (631): на android.app.Dialog.show (Dialog.java:241) 03-03 21:03: 26.441: ОШИБКА / WindowManager (631): в android.app.AlertDialog $ Builder.show (AlertDialog.java:802) 03-03 21: 03: 26.441: ОШИБКА / WindowManager (631): в android.widget.VideoView$ 4.onError (VideoView.java:387) 03-03 21: 03: 26.441: ОШИБКА / WindowManager (631): в android.media.MediaPlayer $ EventHandler.handleMessage (MediaPlayer.java:1264) 03-03 21:03:26.441: ОШИБКА / WindowManager (631): на android.os.Handler.dispatchMessage (Handler.java:99) 03-03 21: 03: 26.441: ОШИБКА / WindowManager (631): на android.os.Looper.loop (Looper.java: 123) 03-03 21: 03: 26.441: ОШИБКА / WindowManager (631): на android.app.ActivityThread.main (ActivityThread.java:4627) 03-03 21: 03: 26.441: ОШИБКА / WindowManager (631): at java.lang.reflect.Method.invokeNative (собственный метод) 03-03 21: 03: 26.441: ERROR / WindowManager (631): at java.lang.reflect.Method.invoke (Method.java:521) 03-03 21: 03: 26.441: ОШИБКА / WindowManager (631): на com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run (ZygoteInit.java:868) 03-03 21: 03: 26.441: ОШИБКА / WindowManager (631):в com.android.internal.os.ZygoteInit.main (ZygoteInit.java:626) 03-03 21: 03: 26.441: ОШИБКА / WindowManager (631): в dalvik.system.NativeStart.main (собственный метод)

Ни один из ответов, которые я читал до сих пор, кажется, не решает проблему.Вот код:

mVideoView.setOnErrorListener(new OnErrorListener() {
    @Override
    public boolean onError(MediaPlayer arg0, int arg1, int arg2) {
        Toast.makeText(Player.this, "Sorry, unable to play this video", Toast.LENGTH_LONG).show();
        progressDialog.dismiss();
        if (mToken != null) {
            MusicUtils.unbindFromService(mToken);
        }
        finish();
        return false;
    }
});

Единственное предположение, которое мне оставалось, было то, что тост держался за активность, но все, что я читаю, похоже, говорит, что тост не имеет значения.Я даже попытался с помощью getBaseContext (), а затем попытался поставить тост после finish (), чтобы увидеть, будет ли он работать.У меня нет идей, поэтому любая помощь будет потрясающей.

ОБНОВЛЕНИЕ: Вот еще код

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        extras = getIntent().getExtras();
        media_url = extras.getString("media_url");
        setContentView(R.layout.video_player);
        //Start progress dialog so user knows something is going on
        progressDialog = ProgressDialog.show(this, "", "Loading...", true);
        mVideoView = (VideoView) findViewById(R.id.surface_view);

        runOnUiThread(new Runnable(){
            public void run() {
                playVideo();
            }
        });
    }

    private void playVideo() {
        try {
            if (media_url == null || media_url.length() == 0) {
                progressDialog.dismiss();
                Toast.makeText(VideoPlayer.this, "File URL/media_url is empty",
                        Toast.LENGTH_LONG).show();

            } else {
                // If the path has not changed, just start the media player
                if (media_url.equals(current) && mVideoView != null) {
                    mVideoView.start();
                    mVideoView.requestFocus();
                    return;
                }
                current = media_url;
                mVideoView.setVideoURI(Uri.parse(media_url));
                ctlr=new MediaController(VideoPlayer.this);
                ctlr.setMediaPlayer(mVideoView);
                mVideoView.setMediaController(ctlr);
                mVideoView.requestFocus();
                mVideoView.setOnPreparedListener(new OnPreparedListener() {

                    public void onPrepared(MediaPlayer arg0) {
                        progressDialog.dismiss();
                        mVideoView.start();
                    }
                });
                mVideoView.setOnErrorListener(new OnErrorListener() {

                    @Override
                    public boolean onError(MediaPlayer arg0, int arg1, int arg2) {
                        Toast.makeText(VideoPlayer.this, "Sorry, unable to play this video",
                                Toast.LENGTH_LONG).show();
                        progressDialog.dismiss();
                        if (mToken != null) {
                            MusicUtils.unbindFromService(mToken);
                        }
                        finish();
                        return false;
                    }
                });


            }
        } catch (Exception e) {
            Log.e(TAG, "error: " + e.getMessage(), e);
            if (mVideoView != null) {
                mVideoView.stopPlayback();
            }
            finish();
        }
    }

    private void startPlayback() {

        if(mService == null)
            return;
        Intent intent = getIntent();
        String filename = "";
        Uri uri = intent.getData();
        if (uri != null && uri.toString().length() > 0) {
            String scheme = uri.getScheme();
            if ("file".equals(scheme)) {
                filename = uri.getPath();
            } else {
                filename = uri.toString();
            }
            try {
                mService.stop();
                mService.openFileAsync(filename);
                mService.play();
                setIntent(new Intent());
            } catch (Exception ex) {
                Log.e(tag, "couldn't start playback: " + ex);
            }
        }
    }

    private ServiceConnection osc = new ServiceConnection() {
        public void onServiceConnected(ComponentName classname, IBinder obj) {
            mService = IMediaPlaybackService.Stub.asInterface(obj);
            startPlayback();
        }
        public void onServiceDisconnected(ComponentName classname) {
            mService = null;
        }
     };

Ошибка возникает, когда это видео, которое может использовать устройство. 't play

Ответы [ 2 ]

2 голосов
/ 08 марта 2012

Может быть, вы могли бы попытаться показать свой тост через runOnUiThread ?

Что-то вроде:

    @Override
    public boolean onError(MediaPlayer arg0, int arg1, int arg2) {
       Player.this.runOnUiThread(new Runnable() {
           void run() {
               Toast.makeText(Player.this, "Sorry, unable to play this video", Toast.LENGTH_LONG).show();
               progressDialog.dismiss();
               if (mToken != null) {
                    MusicUtils.unbindFromService(mToken);
                }
                finish();
           }
        );
        return false;
    }

EDIT

Вот еще ... ниже приведен код (в Froyo) для VideoView.

Похоже, что ошибка происходит от AlertDialog.Builder ... но, основываясь на вашем коде, она даже не должна туда попасть, поскольку ошибка должна обрабатываться выше, когда mOnErrorListener не равен нулю ...

Можете ли вы проверить, вызывается ли ваш обработчик ошибок? Может, постараться не вызывать финиш () там?

 private MediaPlayer.OnErrorListener mErrorListener =
        new MediaPlayer.OnErrorListener() {
        public boolean onError(MediaPlayer mp, int framework_err, int impl_err) {
            Log.d(TAG, "Error: " + framework_err + "," + impl_err);
            mCurrentState = STATE_ERROR;
            mTargetState = STATE_ERROR;
            if (mMediaController != null) {
                mMediaController.hide();
            }

            /* If an error handler has been supplied, use it and finish. */
            if (mOnErrorListener != null) {
                if (mOnErrorListener.onError(mMediaPlayer, framework_err, impl_err)) {
                    return true;
                }
            }

            /* Otherwise, pop up an error dialog so the user knows that
             * something bad has happened. Only try and pop up the dialog
             * if we're attached to a window. When we're going away and no
             * longer have a window, don't bother showing the user an error.
             */
            if (getWindowToken() != null) {
                Resources r = mContext.getResources();
                int messageId;

                if (framework_err == MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK) {
                    messageId = com.android.internal.R.string.VideoView_error_text_invalid_progressive_playback;
                } else {
                    messageId = com.android.internal.R.string.VideoView_error_text_unknown;
                }

                new AlertDialog.Builder(mContext)
                        .setTitle(com.android.internal.R.string.VideoView_error_title)
                        .setMessage(messageId)
                        .setPositiveButton(com.android.internal.R.string.VideoView_error_button,
                                new DialogInterface.OnClickListener() {
                                    public void onClick(DialogInterface dialog, int whichButton) {
                                        /* If we get here, there is no onError listener, so
                                         * at least inform them that the video is over.
                                         */
                                        if (mOnCompletionListener != null) {
                                            mOnCompletionListener.onCompletion(mMediaPlayer);
                                        }
                                    }
                                })
                        .setCancelable(false)
                        .show();
            }
            return true;
        }
    };

БОЛЬШЕ РЕДАКТИРОВАТЬ:

Измените обработчик onError на return true;

Тогда обработчик ошибок «по умолчанию» не будет пытаться создать этот AlertDialog

0 голосов
/ 04 марта 2012

Событие прослушивателя ошибок, вероятно, не возвращается к вам в потоке пользовательского интерфейса (петлителя). Вам необходимо опубликовать событие в обработчике (зарегистрированном в потоке пользовательского интерфейса), чтобы обработчик показывал Toast и закрывал диалог прогресса.

...