2016-02-12 62 views
0

我已經構建了一個Android TV Live頻道應用程序,並且通常它運行良好。然而,有時候,我會收到來自用戶的是給了我一個錯誤,如下面的崩潰報告:偶爾會得到「處理調諧請求的時間太長」錯誤

02-11 13:32:21.135 29165-29165/? E/AndroidRuntime: FATAL EXCEPTION: main 
    Process: com.felkertech.sample.channelsurfer, PID: 29165 
    java.lang.RuntimeException: Too much time to handle tune request. (2160ms > 2000ms) Consider handling the tune request in a separate thread. 
    at android.media.tv.ITvInputSessionWrapper.executeMessage(ITvInputSessionWrapper.java:166) 
    at com.android.internal.os.HandlerCaller$MyHandler.handleMessage(HandlerCaller.java:37) 
    at android.os.Handler.dispatchMessage(Handler.java:102) 
    at android.os.Looper.loop(Looper.java:135) 
    at android.app.ActivityThread.main(ActivityThread.java:5254) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at java.lang.reflect.Method.invoke(Method.java:372) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698) 

我真的不知道我該怎麼解決這個問題的錯誤沒有引用我的任何代碼。另外,我不能一致地重現此錯誤。我的onTune方法的一部分。請注意,它從另一個類調用一個方法來實際獲得視頻:

@Override 
public boolean onTune(Uri channelUri) { 
    notifyVideoUnavailable(TvInputManager.VIDEO_UNAVAILABLE_REASON_TUNING); 
    setOverlayViewEnabled(true); 
    Log.d(TAG, "Tuning to " + channelUri.toString()); 
    String[] projection = {TvContract.Channels.COLUMN_DISPLAY_NAME, TvContract.Channels.COLUMN_ORIGINAL_NETWORK_ID, 
      TvContract.Channels.COLUMN_SERVICE_ID, TvContract.Channels.COLUMN_TRANSPORT_STREAM_ID, 
      TvContract.Channels.COLUMN_INPUT_ID, TvContract.Channels.COLUMN_DISPLAY_NUMBER}; 
    //Now look up this channel in the DB 
    try (Cursor cursor = tvInputProvider.getContentResolver().query(channelUri, projection, null, null, null)) { 
     if (cursor == null || cursor.getCount() == 0) { 
      return false; 
     } 
     cursor.moveToNext(); 
     Channel channel = new Channel() 
       .setNumber(cursor.getString(cursor.getColumnIndex(TvContract.Channels.COLUMN_DISPLAY_NUMBER))) 
       .setName(cursor.getString(cursor.getColumnIndex(TvContract.Channels.COLUMN_DISPLAY_NAME))) 
       .setOriginalNetworkId(cursor.getInt(cursor.getColumnIndex(TvContract.Channels.COLUMN_ORIGINAL_NETWORK_ID))) 
       .setTransportStreamId(cursor.getInt(cursor.getColumnIndex(TvContract.Channels.COLUMN_TRANSPORT_STREAM_ID))) 
       .setServiceId(cursor.getInt(cursor.getColumnIndex(TvContract.Channels.COLUMN_SERVICE_ID))) 
       .setVideoHeight(1080) 
       .setVideoWidth(1920); 
     this.currentChannel = channel; 
     TvInputManager mTvInputManager = (TvInputManager) tvInputProvider.getApplicationContext().getSystemService(Context.TV_INPUT_SERVICE); 
     if(mTvInputManager.isParentalControlsEnabled()) { 
      TvContentRating blockedRating = null; 
      for(int i=0;i<tvInputProvider.getProgramRightNow(channel).getContentRatings().length;i++) { 
       blockedRating = (mTvInputManager.isRatingBlocked(tvInputProvider.getProgramRightNow(channel).getContentRatings()[i]) && blockedRating == null)?tvInputProvider.getProgramRightNow(channel).getContentRatings()[i]:null; 
      } 
      if(blockedRating != null) { 
       notifyContentBlocked(blockedRating); 
      } 
     } 
     notifyContentAllowed(); 
     return tvInputProvider.onTune(channel); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
    return false; 
} 

tvInputPlayer.onTune

public boolean onTune(Channel channel) { 
    this.currentChannel = channel; 
    this.lastTune = new Date(); 
    Toast.makeText(SampleTvInputProvider.this, "Tuning to "+channel.getName()+" with program "+getProgramRightNow(channel).getTitle()+" at "+getProgramRightNow(channel).getInternalProviderData(), Toast.LENGTH_SHORT).show(); 
    Log.d(TAG, "Tuning to " + channel.getName()); 
    Log.d(TAG, "Playing "+getProgramRightNow(channel).getTitle()); 
    Log.d(TAG, "Play the video "+getProgramRightNow(channel).getInternalProviderData()); 

    //Only my local channels will have the ability to be time shifted, so I should update that every tuning. 
    //Timeshifting only works for API >= 23 
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 
     if (isLocal()) { 
      getSession().notifyTimeShiftStatusChanged(TvInputManager.TIME_SHIFT_STATUS_AVAILABLE); 
     } else { 
      //If it's not a local channel, I cannot pause or seek in the program 
      getSession().notifyTimeShiftStatusChanged(TvInputManager.TIME_SHIFT_STATUS_UNAVAILABLE); 
     } 
    } 

    play(getProgramRightNow(channel).getInternalProviderData()); 
    if(currentChannel.getNumber().equals("4")) { 
     Handler h = new Handler() { 
      @Override 
      public void handleMessage(Message msg) { 
       super.handleMessage(msg); 
       setOverlayEnabled(true); 
      } 
     }; 
     h.sendEmptyMessageDelayed(0, 16); 
    } 
    return true; 
} 

的方法play負載在ExoPlayer的URL。我覺得這可能是潛在的緩衝會導致ExoPlayer稍微滯後以造成這個問題,但我不知道如何解決這個問題。

有誰知道嗎?

謝謝。

回答

1

我也有類似的問題,最近並通過定時的代碼塊我孤立它來查詢:

tvInputProvider.getContentResolver().query(..... 

這個查詢偶爾會於直播頻道應用的啓動超過2秒,如果通道是第一個調整。 我刪除了查詢(通過保留我自己的表),並避免了問題。

+0

謝謝你讓我知道瓶頸在哪裏。我決定把我的查詢放在一個AsyncTask中,然後在'onTune'中運行。無論哪種方式,它將調優置於UI線程之外,似乎運行沒有問題。 –