2012-01-29 2 views
0

) shoutcast를 스트리밍하는 데 사용하는 서비스에 오류/예외가 발생합니다. 음악 스트림이 작동하지 않는 등의 예외가 생성되면 ui 스레드에서 오류를 표시하고 싶습니다.Android 서비스 오류 (ui

어떻게 할 수 있습니까? 현재 코드는 다음과 같습니다.

UI 클래스 :

private OnClickListener btnStopListener = new OnClickListener() { 
    public void onClick(View v) { 

     if (MyService.isRunning()) { 

      doUnbindService(); 
      stopService(new Intent(MainActivity.this, MyService.class)); 

      btnStop.setBackgroundResource(R.drawable.player_play); 

      barLoader.setVisibility(View.GONE); 

     } else { 

      Intent intent = new Intent(MainActivity.this, MyService.class); 

      intent.putExtra("streamUrl", strLinkUrl); 

      startService(intent); 

      doBindService(); 

     } 

    } 
}; 

void doBindService() { 
    bindService(new Intent(this, MyService.class), mConnection, 
      Context.BIND_AUTO_CREATE); 
    mIsBound = true; 

} 

void doUnbindService() { 
    if (mIsBound) { 
     // If we have received the service, and hence registered with it, 
     // then now is the time to unregister. 
     if (mService != null) { 
      try { 
       Message msg = Message.obtain(null, 
         MyService.MSG_UNREGISTER_CLIENT); 
       msg.replyTo = mMessenger; 
       mService.send(msg); 
      } catch (RemoteException e) { 
       // There is nothing special we need to do if the service has 
       // crashed. 
      } 
     } 
     // Detach our existing connection. 
     unbindService(mConnection); 
     mIsBound = false; 

    } 
} 

서비스 클래스 :

public class MyService extends Service implements 

OnPreparedListener, OnErrorListener { 공공 문자열 txtBTitle, txtBChannel, txtBDescription, txtBTitleNow, txtBImageUrl, txtBLinkUrl, 개인 티피 케이션의 나노 미터;

private static boolean isRunning = false; 

private Timer timer1 = new Timer(); 

String strTitle,strArtist; 

MediaPlayer mediaPlayer = new MediaPlayer(); 


ArrayList<Messenger> mClients = new ArrayList<Messenger>(); // Keeps track of all current registered clients. 

int mValue = 0; // Holds last value set by a client. 
static final int MSG_REGISTER_CLIENT = 1; 
static final int MSG_UNREGISTER_CLIENT = 2; 
static final int MSG_SET_INT_VALUE = 3; 
static final int MSG_SET_STRING_VALUE = 4; 

String strUrl; 

final Messenger mMessenger = new Messenger(new IncomingHandler()); // Target we publish for clients to send messages to IncomingHandler. 


@Override 
public IBinder onBind(Intent intent) { 
    return mMessenger.getBinder(); 
} 


class IncomingHandler extends Handler { // Handler of incoming messages from clients. 
    @Override 
    public void handleMessage(Message msg) { 
     switch (msg.what) { 
     case MSG_REGISTER_CLIENT: 
      mClients.add(msg.replyTo); 
      break; 
     case MSG_UNREGISTER_CLIENT: 
      mClients.remove(msg.replyTo); 
      break; 
     case MSG_SET_INT_VALUE: 
      // incrementby = msg.arg1; 
      break; 
     default: 
      super.handleMessage(msg); 
     } 
    } 
} 


private void sendMessageToUI(int intvaluetosend) { 
    for (int i=mClients.size()-1; i>=0; i--) { 
     try { 
      // Send data as an Integer 
      mClients.get(i).send(Message.obtain(null, MSG_SET_INT_VALUE, intvaluetosend, 0)); 

      //Send data as a String 
      Bundle b = new Bundle(); 
      b.putString("str1",strTitle+"\n"+strArtist); 

      b.putString("strUrl", strUrl); 


      Message msg = Message.obtain(null, MSG_SET_STRING_VALUE); 
      msg.setData(b); 
      mClients.get(i).send(msg); 

     } catch (RemoteException e) { 
      // The client is dead. Remove it from the list; we are going through the list from back to front so this is safe to do inside the loop. 
      mClients.remove(i); 
     } 
    } 
} 


@Override 
public void onCreate() { 
    super.onCreate(); 
    Log.i("MyService", "Service Started."); 
    showNotification(); 

    isRunning = true; 
} 
private void showNotification() { 
    nm = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); 
    // In this sample, we'll use the same text for the ticker and the expanded notification 
    CharSequence text = getText(R.string.service_started); 
    // Set the icon, scrolling text and timestamp 
    Notification notification = new Notification(R.drawable.icon, text, System.currentTimeMillis()); 
    // The PendingIntent to launch our activity if the user selects this notification 
    PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class).putExtra("fromWhere", "fromService"), 0); 
    // Set the info for the views that show in the notification panel. 
    notification.setLatestEventInfo(this, getText(R.string.service_label), text, contentIntent); 
    // Send the notification. 
    // We use a layout id because it is a unique number. We use it later to cancel. 
    nm.notify(R.string.service_started, notification); 
} 
@Override 
public int onStartCommand(Intent intent, int flags, int startId) { 



    strUrl = intent.getExtras().getString("streamUrl"); 

    Log.i("ZealDeveloper", strUrl); 


    if(!mediaPlayer.isPlaying()){ 

    mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); 
    try { 
     mediaPlayer.setDataSource(strUrl); 
     mediaPlayer.setOnPreparedListener(this); 

    } catch (IllegalArgumentException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (IllegalStateException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
    mediaPlayer.prepareAsync(); // might take long! (for buffering, etc) 
    // mediaPlayer.start(); 

    } 

    timer1.scheduleAtFixedRate(new TimerTask(){ public void run() {onMetaParser();} 

    }, 0, 100000L); 

    Log.i("MyService", "Received start id " + startId + ": " + intent); 


    return START_STICKY; // run until explicitly stopped. 
} 

public static boolean isRunning() 
{ 
    return isRunning; 
} 




//Meta Parser 
private void onMetaParser() { 
    // TODO Auto-generated method stub 

    URL url; 

    try { 
     url = new URL(strUrl); 
     IcyStreamMeta icy = new IcyStreamMeta(url); 

     try{ 
     strTitle = icy.getTitle(); 
     } 
     catch (NullPointerException e) { 
      strTitle=""; 
     } 
     try{ 
     strArtist = icy.getArtist(); 
     } 
     catch (NullPointerException e) { 
      strArtist = ""; 
     } 
     System.out.println("Title : " + strTitle + strUrl); 


     System.gc(); 

    // txtTitleNow.setText(T); 

    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

} 


@Override 
public void onDestroy() { 
    super.onDestroy(); 

    if (mediaPlayer.isPlaying()) { 
     mediaPlayer.release();  
    } 


    if (timer1 != null) {timer1.cancel(); 

    Log.i("ZealDeveloper", "Timer 1 Cancled");} 

    nm.cancel(R.string.service_started); // Cancel the persistent notification. 


    Log.i("MyService", "Service Stopped."); 
    isRunning = false; 


    try { 

     timer1.cancel(); 
     mediaPlayer.release(); 
     mediaPlayer = null; 

    } catch (Exception e) { 

     e.printStackTrace(); 


    } 

} 

@Override 
public void onPrepared(MediaPlayer mp) { 
    // TODO Auto-generated method stub 
    mp.start(); 

    sendMessageToUI(0); 

} 


@Override 
public boolean onError(MediaPlayer mp, int what, int extra) { 
    // TODO Auto-generated method stub 

    mediaPlayer.release(); 
    timer1.cancel();  
    return false;}} 

스택 추적 :

01-30 11:03:32.470: W/System.err(311): java.io.FileNotFoundException: http://xxxxxstream 
01-30 11:03:32.480: E/MediaPlayer(311): error (1, -1004) 
01-30 11:03:32.490: W/System.err(311): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:1162) 
01-30 11:03:32.500: W/System.err(311): at com.sikhnetRadio.test.IcyStreamMeta.retreiveMetadata(IcyStreamMeta.java:91) 
01-30 11:03:32.500: W/System.err(311): at com.sikhnetRadio.test.IcyStreamMeta.refreshMeta(IcyStreamMeta.java:79) 
01-30 11:03:32.500: W/System.err(311): at com.sikhnetRadio.test.IcyStreamMeta.getMetadata(IcyStreamMeta.java:72) 
01-30 11:03:32.500: W/System.err(311): at com.sikhnetRadio.test.IcyStreamMeta.getTitle(IcyStreamMeta.java:60) 
01-30 11:03:32.500: W/System.err(311): at com.sikhnetRadio.test.MyService.onMetaParser(MyService.java:192) 
01-30 11:03:32.510: W/System.err(311): at com.sikhnetRadio.test.MyService.access$0(MyService.java:182) 
01-30 11:03:32.510: W/System.err(311): at com.sikhnetRadio.test.MyService$1.run(MyService.java:163) 
01-30 11:03:32.510: W/System.err(311): at java.util.Timer$TimerImpl.run(Timer.java:289) 
01-30 11:03:32.610: E/MediaPlayer(311): Error (1,-1004) 
+0

일반적인 오류는 MediaPlayer를 (0, -1004) – ZealDeveloper

+0

당신이 테스트 장치/에뮬레이터의 API를 무엇입니까? –

+0

오류의 실제 스택 추적을 게시 할 수 있습니까? – jlindenbaum

답변

5

두 가지 옵션

1

) 당신은 기존의 자바 형 수신기 (당신의 활동은 무시)하고 Ibinder 인터페이스를 통해 서비스를 전달하는 인터페이스를 만들 수 있습니다.

2) this과 비슷한 액티비티에서 브로드 캐스트 리시버를 구현하십시오. 여기에서는 Intentservice에 대한 작업이 완료되었으므로 servie에 대해 동일한 작업을 수행하는 것이 어렵지 않을 것입니다.

1

타이머는 UI에서 스레드로부터 안전하지 않습니다. 대신 Handler를 사용해야합니다.

예를 들어 필자는 내 유틸리티 클래스 인 Clock을 제안합니다. 나는 직장에서 나 자신을 사용한다. 풍부한 논평을하고 있습니다. 내가 무엇입니까

import java.text.SimpleDateFormat; 
import java.util.ArrayList; 
import java.util.Date; 
import android.os.Handler; 
import android.widget.TextView; 
/** 
* The class for creating and refreshing many different fields on different layouts, 
* that can hold actual time and/or date in different formats 
* The formats should be as in http://developer.android.com/reference/java/text/SimpleDateFormat.html. 
* Only present and visible fields are being actualized, so there is no need to clean the clock list after closing an activity 
* 
* Examples of use: 
* 
*  Clock.registerClock((TextView) findViewById(R.id.TimeField), "HH:mm"); 
*  Clock.registerClock((TextView) findViewById(R.id.DateField), "d.M.yyyy EEE"); 
*  Clock.start(10000L); 
* 
* @author Petr Gangnus 
*/ 
public final class Clock { 
    /** 
    * the handler that works instead of timer and supports UI 
    */ 
    static private Handler handler = new Handler(); 
    /** 
    * the interval of the time refreshing 
    */ 
    static private long refreshStep; 

    /** 
    * pairs TextView clockFace + time/date format 
    */ 
    private TextView clockFace; 
    private String format; 
    private Clock(TextView clockFace, String format){ 
     this.clockFace=clockFace; 
     this.format=format; 
    } 
    // here is the list of views containing the visual timers that should be held actual 
    static private ArrayList<Clock> clocks=new ArrayList<Clock>(); 
    /** 
    * fills all timer fields by actual time value, according to their formats. 
    */ 
    static private Runnable mUpdateTimeTask = new Runnable() { 
     public void run() { 
      for(Clock clock:clocks){ 
       showActualTimeDate(clock); 
      } 
      handler.postDelayed(this,refreshStep); 
     } 
    }; 

    //============================================ public members ==================================================================== 
    /** 
    * add a clock to the list of updating clocks 
    * @param clockFace - the place where the time or date will be shown 
    * @param format - the format of the time/date 
    * @return 
    */ 
    public static boolean registerClock(TextView clockFace, String format){ 
     if (clockFace==null) return false; 
     if(clocks.contains(clockFace)){ 
      // old clockFace 
      clocks.get(clocks.indexOf(clockFace)).format=format; 
     } else { 
      // new clockFace 
      clocks.add(new Clock(clockFace, format)); 
     } 
     return true; 
    } 
    /** 
    * remove a clock from the updating list 
    * @param clockFace 
    * @return 
    */ 
    public static boolean unRegisterClock(TextView clockFace){ 
     if (clockFace==null) return false; 
     if(clocks.contains(clockFace)){ 
      // found clockFace 
      clocks.remove(clocks.indexOf(clockFace)); 
     } else { 
      // not found clockFace 
      return false; 
     } 
     return true; 
    } 
    /** 
    * put in the "place" the actual date/time in the appropriate "format" 
    * @param place 
    * @param format 
    */ 
    public static void showActualTimeDate(Clock clock){ 
     if (clock.clockFace==null) return; 
     if (clock.clockFace.getVisibility()!=TextView.VISIBLE) return; 
     Date thisDate=new Date(); 
     SimpleDateFormat df=new SimpleDateFormat(clock.format); 
     clock.clockFace.setText(df.format(thisDate)); 
    } 
    /** 
    * start the ticking for all clocks 
    * @param step the tick interval 
    */ 
    public static void start(long step) { 
     refreshStep=step; 
     handler.removeCallbacks(mUpdateTimeTask); 
     handler.postDelayed(mUpdateTimeTask, 0); 
    } 
    /** 
    * Stopping ticking all clocks (not removing them) 
    * the calling could be put somewhere in onStop 
    */ 
    public static void stop() { 
     handler.removeCallbacks(mUpdateTimeTask); 
    } 
} 
+0

현재 코드로 구현하는 좋은 예가 있습니까? Thnx – ZealDeveloper

+1

예, 내 시계 클래스가 있습니다. 개발자 사이트의 예보다 훨씬 좋습니다. 심지어 거기에 오류가 있습니다. 수정 된 답변을 1 분 안에보십시오. – Gangnus

+0

Thnx, 확실히 이것을 구현하려고합니다. – ZealDeveloper