2017-11-15 23 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을 알 수 있습니다 : I라는 그 모든 방법은

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입니다 수업. 현재로서는, 초 단위로 변환하는 방법 만 보유하고 있으므로 TextView MP3를 스트리밍하는 현재 진행 상태 항목을 업데이트 할 수 있습니다.

내가받는 특정 오류는 onDrag 메서드에서 발생하는 NullPointerException입니다. 이유를 이해할 수없는 것 같습니다.

죄송합니다. 중복 인 경우 다른 곳에서는 찾을 수 없습니다.

편집 좀 내 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 

편집 2 내 문제를 해결했다고 생각합니다. 가장 최근의 오류를 조사하자 마자 MainActivity에서 MediaPlayer를 호출하지 않았다는 것을 알게되었습니다. 따라서 아무것도로드되지 않고 스트리밍되지 않았습니다. Here은 내 솔루션의 일부를 발견 한 곳입니다.

playbutton이 작동하지 않고 스트림이 자동으로 시작되는 문제가 계속 발생하지만이 문제는 간단하고 쉽게 해결할 수 있습니다. 그러나 나는 여전히 내 코드에 "잘못된"것이 있는지 알고 싶어합니다.

답변

1

이렇게하는 것이 일반적입니까? 또는 모든 코드와 메소드를 각각의 활동에 포함시켜야합니까? 아니면 자신의 클래스로 옮기고 해당 활동이 필요로하는 곳에서 액세스 할 수 있습니까?

일반적으로 일반적인 소프트웨어 엔지니어링 원칙과 모범 사례를 사용하십시오. 특정 목적에 초점을 맞추고 봉사하는 수업을 디자인하십시오. 새로운 Architecture Components 라이브러리를 살펴 봐야합니다. 여기에는 "라이프 사이클 인식"클래스를 만들 수있는 도구가 있습니다. 이러한 클래스는 리소스를 관리하여 Activity를 오염시키는 것이 아니라 자신의 리소스에 대한 라이프 사이클 이벤트를 처리 할 책임이 있습니다.

코멘트

일반적으로, 당신은 활동의 라이프 사이클 외부의 Activity 클래스의 필드를 초기화하지 않아야합니다. 뷰와 같이 라이프 사이클의 특정 시간에만 사용할 수있는 리소스에 의존 할 때 문제가 발생할 수 있습니다. 이 경우 Streaming 객체를 선언과 함께 인라인으로 초기화해도 아무런 문제가 발생하지 않을 것입니다. 여전히 onCreate()을 "생성자"로 취급하는 습관을 얻는 것이 가장 좋습니다.이 방법 대신 모두 초기화를 수행하십시오.

+0

감사합니다. 이것은 정확하게 내가 알고 싶어하는 것이 었습니다. 그래서 지금부터 내 onCreate 안에 모든 필드 (MediaPlayer, Textviews 등)를 유지해야합니까? 보통 외부 수업이 필요하지 않습니까? 적어도 내 TextViews 및 Button과의 상호 작용에 관해서는? – brettsalyer

+0

@brettsalyer 일반적으로 Activity 나 Fragment 하위 클래스에서 내 견해를 유지합니다. 내가 생각할 수있는 유일한 예외는보기를 사용해야하는 사용자 지정 목록 어댑터 클래스입니다. MediaPlayer로 아무 것도하지 않았지만 다른 클래스에서 사용하는 것이 도움이 될 수 있습니다. 핵심은 활동 라이프 사이클 내에서 작업하는지 확인하는 것입니다. –