偶尔会出现 "Too much time to handle tune request" 错误
Occasionally getting "Too much time to handle tune request" error
我构建了一个 Android 电视直播频道应用程序,总的来说它运行良好。但是,有时我会收到用户的崩溃报告,其中显示如下错误:
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
方法的一部分。请注意,它确实调用了另一个 class 的方法来实际获取视频:
@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 稍微滞后以产生此问题的地方,但我不知道如何解决此问题。
有人知道吗?
谢谢。
我最近遇到了类似的问题,通过对代码块进行计时,我将其隔离到查询中:
tvInputProvider.getContentResolver().query(.....
如果您的频道是第一个调谐的频道,则此查询有时会在实时频道应用程序启动时超过 2 秒。
我删除了查询(通过保留我自己的 table)并避免了问题。
我构建了一个 Android 电视直播频道应用程序,总的来说它运行良好。但是,有时我会收到用户的崩溃报告,其中显示如下错误:
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
方法的一部分。请注意,它确实调用了另一个 class 的方法来实际获取视频:
@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 稍微滞后以产生此问题的地方,但我不知道如何解决此问题。
有人知道吗?
谢谢。
我最近遇到了类似的问题,通过对代码块进行计时,我将其隔离到查询中:
tvInputProvider.getContentResolver().query(.....
如果您的频道是第一个调谐的频道,则此查询有时会在实时频道应用程序启动时超过 2 秒。 我删除了查询(通过保留我自己的 table)并避免了问题。