2017-11-15 9 views
0

今、私はAndroidの開発にもっと精通しています。もちろん、Android Studioを使用しています。プロジェクトとして、MediaPlayerクラスのURLからストリーミングを処理するアプリケーションを作成しています。Android Studioコーディングコンベンション&可能なコンテキストエラー?

私はこの機能を持っていて、まさに私が必要とするものです。しかし、自分のMainActivityが独自のクラスに格納できるメソッドや変数でうまくいかないようにしました。

  • それがこれを行うには、従来のです:

    私はこれについてカップルの質問がありますか?または、それぞれのアクティビティの中にすべてのコードとメソッドを保持する必要がありますか、それともそれらを自分のクラスに移動し、アクティビティが必要な場所からアクセスするのが普通ですか?

  • 私は別のクラスに移動する際に正しく動作するのMediaPlayerを得るの問題を抱えています。私はそのメソッドを呼び出すときには、メソッドContextを与えなければならないことを読んだ。だから私はContextを渡したオブジェクトを使ってメソッドを呼び出しました。

私はこの種の開発にはかなり新しいので、ヒント、良い習慣、役立つヒントはいつでも歓迎します。

public class Streaming extends AppCompatActivity { 

private SeekBar musicSeek; 
private TextView currentTime; 
private TextView totalTime; 
private ImageButton play_pause; 
private Handler seekHandler = new Handler(); 
private MediaPlayer mp = new MediaPlayer(); 
Context context; 
Utilities util = new Utilities(); 

//Default Constructor 
public Streaming(){} 
//Contructor 
public Streaming(Context context){ 
    this.context = context; 
} 
//Method to run the runnable to update the seekbar 
public void updateSeekBar(){ 
    seekHandler.postDelayed(mUpdateTimeTask, 100); 
} 

public void prepareStreaming() throws IOException { 
    mp.setAudioStreamType(AudioManager.STREAM_MUSIC); 
    mp.setDataSource("http://tricountynaz.net/media/audio/2017-11-08-The%20Compassion%20of%20the%20Christ.mp3"); 
    mp.prepare(); 
} 

public void startStreaming(){ 
    mp.start(); 
} 

public void pauseStreaming(){ 
    mp.pause(); 
} 

//Runnable to update the seekbar with the current position. 
private Runnable mUpdateTimeTask = new Runnable() { 
    public void run() { 
     int totalDuration = mp.getDuration(); 
     int currentPosition = (mp.getCurrentPosition()); 


     //Displaying Total Duration time 
     totalTime = (TextView)((Activity)context).findViewById(R.id.totalTime); 
     totalTime.setText(util.milliSecondsToTimer(totalDuration)); 
     // Displaying time completed playing 
     currentTime = (TextView)((Activity)context).findViewById(R.id.currentTime); 
     currentTime.setText(util.milliSecondsToTimer(currentPosition)); 
     //Set the bars total duration, based on the song duration (converted to seconds) 
     musicSeek = (SeekBar)((Activity)context).findViewById(R.id.music_seek); 
     musicSeek.setMax(totalDuration/1000); 
     // Updating progress bar 
     musicSeek.setProgress(mp.getCurrentPosition()/1000); 

     // Running this thread after 100 milliseconds 
     seekHandler.postDelayed(this, 100); 
    } 
}; 

//What happens when the user interacts with the button 
public void onPlayClick(){ 
    play_pause = (ImageButton)((Activity)context).findViewById(R.id.playButton); 
    play_pause.setOnClickListener(new View.OnClickListener() { 

     @Override 
     public void onClick(View view) { 
      play_pause.setImageResource(R.drawable.ic_pause_name); 

      try { 
       prepareStreaming(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 

      if (mp.isPlaying()) { 
       pauseStreaming(); 
       play_pause.setImageResource(R.drawable.ic_play_name); 


      } else { 
       //mediaPlayer.start(); 
       startStreaming(); 
      } 
     } 
    }); 
} 

//Handles when the user interacts with the seekbar 
public void onDrag(){ 
    musicSeek.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 
     @Override 
     public void onProgressChanged(SeekBar seekBar, int i, boolean b) { 
      if(b) { 
       //seeks to the current position of the slider when the user (b) interacts. 
       mp.seekTo(i*1000); 
       musicSeek.setProgress(i); 
      } 
     } 

     @Override 
     public void onStartTrackingTouch(SeekBar seekBar) { 

     } 

     @Override 
     public void onStopTrackingTouch(SeekBar seekBar) { 

     } 
    });} 

あなたはUtilitiesに気づくでしょう:私はと呼ばれるこれらのメソッドのすべて、あなたがここで見ることができます

public class MainActivity extends AppCompatActivity { 

    Streaming stream = new Streaming(this); 
@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    stream.updateSeekBar(); 
    stream.onPlayClick(); 
    stream.onDrag(); 

} 

:ここ

は、私がStreamingクラスに入れメソッドを呼び出して、私のMainActivityですクラス。これは現在のところ、秒に変換するメソッドしか保持していないので、MP3のストリームの現在の進行状況を更新することができます(TextView)。

私は受け付けており、特定のエラーがonDrag方法から来るNullPointerExceptionです。なぜ私は理解できないようです。

申し訳ありませんが重複している場合は、他の場所でこれを見つけることができませんでした。

EDIT私は少し私のonDrag方法を変更でした:

//Handles when the user interacts with the seekbar 
public void onDrag(){ 
    musicSeek = (SeekBar)((Activity)context).findViewById(R.id.music_seek); 
    musicSeek.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 
     @Override 
     public void onProgressChanged(SeekBar seekBar, int i, boolean b) { 
      if(b) { 
       //seeks to the current position of the slider when the user (b) interacts. 
       mp.seekTo(i*1000); 
       musicSeek.setProgress(i); 
      } 
     } 

これは、今、私がログにこのエラーが出た以外、NullPointerExceptionが解決しました:

E/MediaPlayerNative: Attempt to call getDuration in wrong state: mPlayer=0x0, mCurrentState=0 

EDIT 2私は私の問題を解決したと思う。最近のエラーを調べたところ、私はMainActivityでMediaPlayerを呼び出すことはなかったことに気付きました。したがって、ロードされていないものも何もストリーミングされていませんでした。 Hereは、私が私の解決策の一部を見つけた場所です。

私のplaybuttonがまだ動作していないという問題と、ストリームが自動的に開始されますが、これは小さな問題で簡単に解決できると思います。しかし、私はまだ自分のコードで何か「間違っている」かどうかを知ることに興味があります。

答えて

1

それがこれを行うには、従来のですか?または、それぞれのアクティビティの中にすべてのコードとメソッドを保持する必要がありますか、それともそれらを自分のクラスに移動し、アクティビティが必要な場所からアクセスするのが普通ですか?

確かに一般的なソフトウェアエンジニアリングの原則とベストプラクティスを使用しています。集中し、特定の目的に役立つクラスを設計する。新しいArchitecture Componentsライブラリを見てください。これには、「ライフサイクル対応」クラスを作成するためのツールがあります。これらのクラスは、リソースを管理してアクティビティを汚染するのではなく、自分のリソースのライフサイクルイベントを処理する責任があります。

コメント

一般的に、あなたは活動のライフサイクルの外Activityクラスのフィールドを初期化するべきではありません。ライフサイクルの特定の時点(ビューなど)でのみ利用可能なリソースに依存する場合、この問題が発生する可能性があります。この場合、Streamingオブジェクトをその宣言でインラインで初期化しても問題は発生しません。それでも、 "コンストラクタ"としてonCreate()を扱う習慣を覚えておき、代わりにこのメソッドで初期化を行うのが最善です。

+0

ありがとうございます!これはまさに私が知りたいものでした。だから今から私のonCreate内のすべてのフィールド(MediaPlayer、Textviewsなど)を保持する必要がありますか?通常、外部のクラスは必要ありませんか?少なくとも、それは私のTextViewsとButtonsとのやりとりになるのですか? – brettsalyer

+0

@brettsalyer私は通常、アクティビティまたはフラグメントのサブクラスに自分のビューを保持します。これについて私が考えることができる唯一の例外は、ビューを使用するカスタムリストアダプタクラスです。私はMediaPlayerで何もしていませんが、別のクラスで使用するとどのように役立つのか分かります。重要な点は、アクティビティのライフサイクルの中で作業することです。 –

関連する問題