2013-02-22 6 views
27

多くのデバッグの後、私はついにこのエラーの原因を突き止めました!ガベージコレクション!ガベージコレクションの原因:MediaPlayerが公開されずにファイナライズされる

私はビデオをメディアビューで再生しています。バックグラウンドでは、Rest APIから新しいビデオを探しています。

すべての今して私は、ガベージコレクションの実行を参照してください。

その後
02-22 13:14:57.969: D/dalvikvm(16888): GC_EXPLICIT freed 152K, 4% free 6746K/6979K, paused 2ms+2ms 

とストレート:

02-22 13:14:57.969: W/MediaPlayer-JNI(16888): MediaPlayer finalized without being released 

だから私は5秒ごとにSystem.gc()を呼び出すことによってそれをテストしました。

最初のGCが呼び出されるとすぐに、それが発生します。

02-22 13:19:47.813: D/dalvikvm(17060): GC_EXPLICIT freed 167K, 5% free 6745K/7047K, paused 2ms+2ms ---- I call GC 
02-22 13:19:47.813: W/MediaPlayer-JNI(17060): MediaPlayer finalized without being released ---- VIDEO PLAY INTERRUPTED 

私はJavaとAndroidの開発者にとっては本当に新しいので、私と一緒に裸にしてください!

どうしてですか?それを防ぐことはできますか?

private void playMedia(int playListIndex) throws IOException { 
     File mediadir = getDir("tvr", Context.MODE_PRIVATE); 
     filelist = mediadir.listFiles(); 
     Log.i("media player", "play media!"); 
     String path = filelist[playListIndex].getAbsolutePath(); 
     FileInputStream fileInputStream = new FileInputStream(path); 
     final Uri uri = Uri.parse(path); 
     String filename = filelist[playListIndex].getName(); 
     if (filename.contains("image")) { 
      imageView = (ImageView)findViewById(R.id.imageView); 
      imageView.setVisibility(View.VISIBLE); 
      imageView.setImageURI(uri); 
      mHandler.postDelayed(new Runnable() { 
       public void run() { 
        imageView.setVisibility(View.GONE); 
        imageView.setImageURI(uri); 
        onCompletion(null); 
       } 
      }, 4000); 
     } else if (filename.contains("video")) { 

      MediaPlayer pl = new MediaPlayer(); 
      pl.setOnCompletionListener(this); 
      pl.setDisplay(holder); 
      pl.setDataSource(fileInputStream.getFD()); 
      pl.prepare(); 
      pl.start(); 
     } 
    } 

そして、それが行われます:

@Override 
    public void onCompletion(MediaPlayer mp) { 
     Log.i("media player", "play next please!"); 
     if (mp != null) { 
      mp.release(); 
     } 
//  play next video 
     currentMedia++; 
     if (currentMedia > playList.size() - 1) { 
      currentMedia = 0; 
     } 
     try { 
      playMedia(currentMedia); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 


    } 
+0

あなたはmediaplayerを実装した場所でコードを表示してください。 – Opiatefuchs

+0

こんにちは、コードを追加しました – Harry

答えて

65

これは、メソッドのスコープ内でメディアプレーヤーを作成するためです。したがって、メソッドが完了すると、範囲外になります。これは参照がないことを意味するので、ガベージコレクションのためにはOKです。

これは、onCompletionを呼び出す前にGCによって解放されることができることを意味します。したがって、クリアされる前に解放されません。代わりに、メディアプレーヤーへの参照をクラスのメンバー変数として保存する必要があります。

+1

アグ・ザン!本当にありがとう!これは今、私はそれが何かばかげたことがわかった作品! – Harry

+0

私は同じ問題を抱えていましたが、それは開発者の不注意によって引き起こされましたが、何かにあなたがこの種のエラーを見つけるのが問題になることがよくあります;-)ありがとう! – Robert

+2

私がこれまで読んだことのある最高の答えの1つ、ポイント、そしてJava、スコープ、Gcについて非常に洞察力のあるものです。ありがとうございました! – sirvon

11

JavaのGCは専用メモリを管理し、ビデオを再生

。したがって、他のリソース(ファイル、ソケットなど)が使用されている場合は、それらを手動で管理する必要があります。 MediaPlayerのの場合には、documentationは、と述べ:

はまた、推奨されるMediaPlayerのオブジェクトがもはや使用された後、呼解放()直ちにように内部プレイヤエンジンによって使用されるリソースは、メディア・プレイヤーに関連付けられていますオブジェクトをすぐに解放することができます。リソースには、ハードウェアアクセラレーションコンポーネントなどのシングルトンリソースが含まれ、release()の呼び出しに失敗すると、MediaPlayerオブジェクトの後続インスタンスがソフトウェア実装にフォールバックするか、完全に失敗する可能性があります。

MediaPlayerインスタンスが完了したら、そのインスタンスでrelease()を明示的に呼び出す必要があります。これを行うための良い場所は、アクティビティを含むライフサイクルメソッドである可能性があります。 onDestroy()。それ以外の場合は、MediaPlayerインスタンスがガベージコレクションされると(最終的に参照しなくなった後の任意の時点で)、finalizerはrelease()を呼び出さなかったことに気づき、あなたが見ている警告を出力します。

+0

こんにちは、ありがとう!ビデオが再生された後に私はrelease()を呼び出しています – Harry

+0

それは、私はrelease()を呼び出していた。これは、最初のビデオの再生が完了する前であっても、gc()を呼び出すと、最初の5秒で発生します。 – Harry

+0

コードがあります。T. Kileyの答えがあります。 MediaPlayerを作成した後でMediaPlayerを参照していないので、早くガベージコレクションされています。 –

関連する問題