Create the PC channel on pairing and add each app to it upon launch

This commit is contained in:
Cameron Gutman 2019-07-12 00:23:13 -07:00
parent d9c0830198
commit fd53122cb3
6 changed files with 163 additions and 177 deletions

View File

@ -19,7 +19,6 @@ import com.limelight.utils.Dialog;
import com.limelight.utils.ServerHelper; import com.limelight.utils.ServerHelper;
import com.limelight.utils.ShortcutHelper; import com.limelight.utils.ShortcutHelper;
import com.limelight.utils.SpinnerDialog; import com.limelight.utils.SpinnerDialog;
import com.limelight.utils.TvChannelHelper;
import com.limelight.utils.UiHelper; import com.limelight.utils.UiHelper;
import android.app.Activity; import android.app.Activity;
@ -51,7 +50,6 @@ public class AppView extends Activity implements AdapterFragmentCallbacks {
private AppGridAdapter appGridAdapter; private AppGridAdapter appGridAdapter;
private String uuidString; private String uuidString;
private ShortcutHelper shortcutHelper; private ShortcutHelper shortcutHelper;
private TvChannelHelper tvChannelHelper;
private ComputerDetails computer; private ComputerDetails computer;
private ComputerManagerService.ApplistPoller poller; private ComputerManagerService.ApplistPoller poller;
@ -67,10 +65,10 @@ public class AppView extends Activity implements AdapterFragmentCallbacks {
private final static int START_WITH_QUIT = 4; private final static int START_WITH_QUIT = 4;
private final static int VIEW_DETAILS_ID = 5; private final static int VIEW_DETAILS_ID = 5;
private final static int CREATE_SHORTCUT_ID = 6; private final static int CREATE_SHORTCUT_ID = 6;
private final static int ADD_TO_TV_CHANNEL = 7;
public final static String NAME_EXTRA = "Name"; public final static String NAME_EXTRA = "Name";
public final static String UUID_EXTRA = "UUID"; public final static String UUID_EXTRA = "UUID";
public final static String NEW_PAIR_EXTRA = "NewPair";
private ComputerManagerService.ComputerManagerBinder managerBinder; private ComputerManagerService.ComputerManagerBinder managerBinder;
private final ServiceConnection serviceConnection = new ServiceConnection() { private final ServiceConnection serviceConnection = new ServiceConnection() {
@ -187,9 +185,6 @@ public class AppView extends Activity implements AdapterFragmentCallbacks {
shortcutHelper.disableShortcut(details.uuid, shortcutHelper.disableShortcut(details.uuid,
getResources().getString(R.string.scut_not_paired)); getResources().getString(R.string.scut_not_paired));
//Delete channel of PC for now
tvChannelHelper.deleteChannel(details.uuid);
// Display a toast to the user and quit the activity // Display a toast to the user and quit the activity
Toast.makeText(AppView.this, getResources().getText(R.string.scut_not_paired), Toast.LENGTH_SHORT).show(); Toast.makeText(AppView.this, getResources().getText(R.string.scut_not_paired), Toast.LENGTH_SHORT).show();
finish(); finish();
@ -258,7 +253,6 @@ public class AppView extends Activity implements AdapterFragmentCallbacks {
inForeground = true; inForeground = true;
shortcutHelper = new ShortcutHelper(this); shortcutHelper = new ShortcutHelper(this);
tvChannelHelper = new TvChannelHelper(this);
UiHelper.setLocale(this); UiHelper.setLocale(this);
@ -275,9 +269,8 @@ public class AppView extends Activity implements AdapterFragmentCallbacks {
label.setText(computerName); label.setText(computerName);
// Add a launcher shortcut for this PC (forced, since this is user interaction) // Add a launcher shortcut for this PC (forced, since this is user interaction)
shortcutHelper.createAppViewShortcut(uuidString, computerName, uuidString, true); shortcutHelper.createAppViewShortcut(uuidString, computerName, uuidString, true, getIntent().getBooleanExtra(NEW_PAIR_EXTRA, false));
shortcutHelper.reportShortcutUsed(uuidString); shortcutHelper.reportShortcutUsed(uuidString);
tvChannelHelper.createTvChannel(uuidString, computerName);
// Bind to the computer manager service // Bind to the computer manager service
bindService(new Intent(this, ComputerManagerService.class), serviceConnection, bindService(new Intent(this, ComputerManagerService.class), serviceConnection,
@ -356,9 +349,7 @@ public class AppView extends Activity implements AdapterFragmentCallbacks {
} }
menu.add(Menu.NONE, VIEW_DETAILS_ID, 3, getResources().getString(R.string.applist_menu_details)); menu.add(Menu.NONE, VIEW_DETAILS_ID, 3, getResources().getString(R.string.applist_menu_details));
if (tvChannelHelper.isSupport()) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
menu.add(Menu.NONE, ADD_TO_TV_CHANNEL, 4, getResources().getString(R.string.applist_menu_tv_channel));
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// Only add an option to create shortcut if box art is loaded // Only add an option to create shortcut if box art is loaded
// and when we're in grid-mode (not list-mode). // and when we're in grid-mode (not list-mode).
ImageView appImageView = info.targetView.findViewById(R.id.grid_image); ImageView appImageView = info.targetView.findViewById(R.id.grid_image);
@ -434,10 +425,6 @@ public class AppView extends Activity implements AdapterFragmentCallbacks {
} }
return true; return true;
case ADD_TO_TV_CHANNEL:
tvChannelHelper.addGameToChannel(computer, app.app);
return true;
default: default:
return super.onContextItemSelected(item); return super.onContextItemSelected(item);
} }

View File

@ -268,10 +268,12 @@ public class Game extends Activity implements SurfaceHolder.Callback,
return; return;
} }
// Add a launcher shortcut for this PC (forced, since this is user interaction) // Report this shortcut being used
shortcutHelper = new ShortcutHelper(this); shortcutHelper = new ShortcutHelper(this);
shortcutHelper.createAppViewShortcut(uuid, pcName, uuid, true);
shortcutHelper.reportShortcutUsed(uuid); shortcutHelper.reportShortcutUsed(uuid);
if (appName != null) {
shortcutHelper.reportGameLaunched(uuid, pcName, ""+appId, appName);
}
// Initialize the MediaCodec helper before creating the decoder // Initialize the MediaCodec helper before creating the decoder
GlPreferences glPrefs = GlPreferences.readPreferences(this); GlPreferences glPrefs = GlPreferences.readPreferences(this);
@ -412,7 +414,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
StreamConfiguration config = new StreamConfiguration.Builder() StreamConfiguration config = new StreamConfiguration.Builder()
.setResolution(prefConfig.width, prefConfig.height) .setResolution(prefConfig.width, prefConfig.height)
.setRefreshRate(prefConfig.fps) .setRefreshRate(prefConfig.fps)
.setApp(new NvApp(appName, appId, willStreamHdr)) .setApp(new NvApp(appName != null ? appName : "app", appId, willStreamHdr))
.setBitrate(prefConfig.bitrate) .setBitrate(prefConfig.bitrate)
.setEnableSops(prefConfig.enableSops) .setEnableSops(prefConfig.enableSops)
.enableLocalAudioPlayback(prefConfig.playHostAudio) .enableLocalAudioPlayback(prefConfig.playHostAudio)

View File

@ -25,7 +25,6 @@ import com.limelight.utils.Dialog;
import com.limelight.utils.HelpLauncher; import com.limelight.utils.HelpLauncher;
import com.limelight.utils.ServerHelper; import com.limelight.utils.ServerHelper;
import com.limelight.utils.ShortcutHelper; import com.limelight.utils.ShortcutHelper;
import com.limelight.utils.TvChannelHelper;
import com.limelight.utils.UiHelper; import com.limelight.utils.UiHelper;
import android.app.Activity; import android.app.Activity;
@ -63,7 +62,6 @@ public class PcView extends Activity implements AdapterFragmentCallbacks {
private RelativeLayout noPcFoundLayout; private RelativeLayout noPcFoundLayout;
private PcGridAdapter pcGridAdapter; private PcGridAdapter pcGridAdapter;
private ShortcutHelper shortcutHelper; private ShortcutHelper shortcutHelper;
private TvChannelHelper tvChannelHelper;
private ComputerManagerService.ComputerManagerBinder managerBinder; private ComputerManagerService.ComputerManagerBinder managerBinder;
private boolean freezeUpdates, runningPolling, inForeground, completeOnCreateCalled; private boolean freezeUpdates, runningPolling, inForeground, completeOnCreateCalled;
private final ServiceConnection serviceConnection = new ServiceConnection() { private final ServiceConnection serviceConnection = new ServiceConnection() {
@ -217,7 +215,6 @@ public class PcView extends Activity implements AdapterFragmentCallbacks {
completeOnCreateCalled = true; completeOnCreateCalled = true;
shortcutHelper = new ShortcutHelper(this); shortcutHelper = new ShortcutHelper(this);
tvChannelHelper = new TvChannelHelper(this);
UiHelper.setLocale(this); UiHelper.setLocale(this);
@ -443,7 +440,7 @@ public class PcView extends Activity implements AdapterFragmentCallbacks {
if (toastSuccess) { if (toastSuccess) {
// Open the app list after a successful pairing attempt // Open the app list after a successful pairing attempt
doAppList(computer); doAppList(computer, true);
} }
else { else {
// Start polling again if we're still in the foreground // Start polling again if we're still in the foreground
@ -542,7 +539,7 @@ public class PcView extends Activity implements AdapterFragmentCallbacks {
}).start(); }).start();
} }
private void doAppList(ComputerDetails computer) { private void doAppList(ComputerDetails computer, boolean newlyPaired) {
if (computer.state == ComputerDetails.State.OFFLINE) { if (computer.state == ComputerDetails.State.OFFLINE) {
Toast.makeText(PcView.this, getResources().getString(R.string.error_pc_offline), Toast.LENGTH_SHORT).show(); Toast.makeText(PcView.this, getResources().getString(R.string.error_pc_offline), Toast.LENGTH_SHORT).show();
return; return;
@ -555,6 +552,7 @@ public class PcView extends Activity implements AdapterFragmentCallbacks {
Intent i = new Intent(this, AppView.class); Intent i = new Intent(this, AppView.class);
i.putExtra(AppView.NAME_EXTRA, computer.name); i.putExtra(AppView.NAME_EXTRA, computer.name);
i.putExtra(AppView.UUID_EXTRA, computer.uuid); i.putExtra(AppView.UUID_EXTRA, computer.uuid);
i.putExtra(AppView.NEW_PAIR_EXTRA, newlyPaired);
startActivity(i); startActivity(i);
} }
@ -594,7 +592,7 @@ public class PcView extends Activity implements AdapterFragmentCallbacks {
return true; return true;
case APP_LIST_ID: case APP_LIST_ID:
doAppList(computer.details); doAppList(computer.details, false);
return true; return true;
case RESUME_ID: case RESUME_ID:
@ -640,9 +638,6 @@ public class PcView extends Activity implements AdapterFragmentCallbacks {
shortcutHelper.disableShortcut(details.uuid, shortcutHelper.disableShortcut(details.uuid,
getResources().getString(R.string.scut_deleted_pc)); getResources().getString(R.string.scut_deleted_pc));
//Delete channel of PC
tvChannelHelper.deleteChannel(details.uuid);
pcGridAdapter.removeComputer(computer); pcGridAdapter.removeComputer(computer);
pcGridAdapter.notifyDataSetChanged(); pcGridAdapter.notifyDataSetChanged();
@ -671,7 +666,7 @@ public class PcView extends Activity implements AdapterFragmentCallbacks {
// Add a launcher shortcut for this PC // Add a launcher shortcut for this PC
if (details.pairState == PairState.PAIRED) { if (details.pairState == PairState.PAIRED) {
shortcutHelper.createAppViewShortcut(details.uuid, details, false); shortcutHelper.createAppViewShortcutForOnlineHost(details);
} }
if (existingEntry != null) { if (existingEntry != null) {
@ -713,7 +708,7 @@ public class PcView extends Activity implements AdapterFragmentCallbacks {
// Pair an unpaired machine by default // Pair an unpaired machine by default
doPair(computer.details); doPair(computer.details);
} else { } else {
doAppList(computer.details); doAppList(computer.details, false);
} }
} }
}); });

View File

@ -104,7 +104,7 @@ public class ShortcutTrampoline extends Activity {
if (appIdString != null && appIdString.length() > 0) { if (appIdString != null && appIdString.length() > 0) {
if (details.runningGameId == 0 || details.runningGameId == Integer.parseInt(appIdString)) { if (details.runningGameId == 0 || details.runningGameId == Integer.parseInt(appIdString)) {
intentStack.add(ServerHelper.createStartIntent(ShortcutTrampoline.this, intentStack.add(ServerHelper.createStartIntent(ShortcutTrampoline.this,
new NvApp("app", Integer.parseInt(appIdString), false), details, managerBinder)); new NvApp(null, Integer.parseInt(appIdString), false), details, managerBinder));
// Close this activity // Close this activity
finish(); finish();
@ -115,7 +115,7 @@ public class ShortcutTrampoline extends Activity {
// Create the start intent immediately, so we can safely unbind the managerBinder // Create the start intent immediately, so we can safely unbind the managerBinder
// below before we return. // below before we return.
final Intent startIntent = ServerHelper.createStartIntent(ShortcutTrampoline.this, final Intent startIntent = ServerHelper.createStartIntent(ShortcutTrampoline.this,
new NvApp("app", Integer.parseInt(appIdString), false), details, managerBinder); new NvApp(null, Integer.parseInt(appIdString), false), details, managerBinder);
UiHelper.displayQuitConfirmationDialog(ShortcutTrampoline.this, new Runnable() { UiHelper.displayQuitConfirmationDialog(ShortcutTrampoline.this, new Runnable() {
@Override @Override
@ -155,7 +155,7 @@ public class ShortcutTrampoline extends Activity {
// If a game is running, we'll make the stream the top level activity // If a game is running, we'll make the stream the top level activity
if (details.runningGameId != 0) { if (details.runningGameId != 0) {
intentStack.add(ServerHelper.createStartIntent(ShortcutTrampoline.this, intentStack.add(ServerHelper.createStartIntent(ShortcutTrampoline.this,
new NvApp("app", details.runningGameId, false), details, managerBinder)); new NvApp(null, details.runningGameId, false), details, managerBinder));
} }
// Now start the activities // Now start the activities

View File

@ -1,7 +1,7 @@
package com.limelight.utils; package com.limelight.utils;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.content.Context; import android.app.Activity;
import android.content.Intent; import android.content.Intent;
import android.content.pm.ShortcutInfo; import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutManager; import android.content.pm.ShortcutManager;
@ -22,9 +22,10 @@ import java.util.List;
public class ShortcutHelper { public class ShortcutHelper {
private final ShortcutManager sm; private final ShortcutManager sm;
private final Context context; private final Activity context;
private final TvChannelHelper tvChannelHelper;
public ShortcutHelper(Context context) { public ShortcutHelper(Activity context) {
this.context = context; this.context = context;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
sm = context.getSystemService(ShortcutManager.class); sm = context.getSystemService(ShortcutManager.class);
@ -32,6 +33,7 @@ public class ShortcutHelper {
else { else {
sm = null; sm = null;
} }
this.tvChannelHelper = new TvChannelHelper(context);
} }
@TargetApi(Build.VERSION_CODES.N_MR1) @TargetApi(Build.VERSION_CODES.N_MR1)
@ -80,15 +82,20 @@ public class ShortcutHelper {
return false; return false;
} }
public void reportShortcutUsed(String id) { public void reportShortcutUsed(String computerUuid) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
if (getInfoForId(id) != null) { if (getInfoForId(computerUuid) != null) {
sm.reportShortcutUsed(id); sm.reportShortcutUsed(computerUuid);
} }
} }
} }
public void createAppViewShortcut(String id, String computerName, String computerUuid, boolean forceAdd) { public void reportGameLaunched(String computerUuid, String computerName, String appId, String appName) {
tvChannelHelper.createTvChannel(computerUuid, computerName);
tvChannelHelper.addGameToChannel(computerUuid, computerName, appId, appName);
}
public void createAppViewShortcut(String id, String computerName, String computerUuid, boolean forceAdd, boolean newlyPaired) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
Intent i = new Intent(context, ShortcutTrampoline.class); Intent i = new Intent(context, ShortcutTrampoline.class);
i.putExtra(AppView.NAME_EXTRA, computerName); i.putExtra(AppView.NAME_EXTRA, computerName);
@ -122,10 +129,16 @@ public class ShortcutHelper {
} }
} }
} }
if (newlyPaired) {
// Avoid hammering the channel API for each computer poll because it will throttle us
tvChannelHelper.createTvChannel(computerUuid, computerName);
tvChannelHelper.requestChannelOnHomeScreen(computerUuid);
}
} }
public void createAppViewShortcut(String id, ComputerDetails details, boolean forceAdd) { public void createAppViewShortcutForOnlineHost(ComputerDetails details) {
createAppViewShortcut(id, details.name, details.uuid, forceAdd); createAppViewShortcut(details.uuid, details.name, details.uuid, false, false);
} }
@TargetApi(Build.VERSION_CODES.O) @TargetApi(Build.VERSION_CODES.O)
@ -161,10 +174,11 @@ public class ShortcutHelper {
return createPinnedGameShortcut(id, iconBits, cDetails.name, cDetails.uuid, app.getAppName(), Integer.valueOf(app.getAppId()).toString()); return createPinnedGameShortcut(id, iconBits, cDetails.name, cDetails.uuid, app.getAppName(), Integer.valueOf(app.getAppId()).toString());
} }
public void disableShortcut(String id, CharSequence reason) { public void disableShortcut(String uuid, CharSequence reason) {
tvChannelHelper.deleteChannel(uuid);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
if (getInfoForId(id) != null) { if (getInfoForId(uuid) != null) {
sm.disableShortcuts(Collections.singletonList(id), reason); sm.disableShortcuts(Collections.singletonList(uuid), reason);
} }
} }
} }

View File

@ -1,12 +1,12 @@
package com.limelight.utils; package com.limelight.utils;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.app.UiModeManager; import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.ContentUris; import android.content.ContentUris;
import android.content.ContentValues; import android.content.ContentValues;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.res.Configuration; import android.content.pm.PackageManager;
import android.database.Cursor; import android.database.Cursor;
import android.database.sqlite.SQLiteException; import android.database.sqlite.SQLiteException;
import android.graphics.Bitmap; import android.graphics.Bitmap;
@ -21,29 +21,46 @@ import com.limelight.LimeLog;
import com.limelight.PosterContentProvider; import com.limelight.PosterContentProvider;
import com.limelight.R; import com.limelight.R;
import com.limelight.ShortcutTrampoline; import com.limelight.ShortcutTrampoline;
import com.limelight.nvstream.http.ComputerDetails;
import com.limelight.nvstream.http.NvApp;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
@TargetApi(Build.VERSION_CODES.O)
public class TvChannelHelper { public class TvChannelHelper {
private static final int ASPECT_RATIO_MOVIE_POSTER = 5; private static final int ASPECT_RATIO_MOVIE_POSTER = 5;
private static final int TYPE_GAME = 12; private static final int TYPE_GAME = 12;
public static final String[] CHANNEL_PROJECTION = {TvContract.Channels._ID, TvContract.Channels.COLUMN_INTERNAL_PROVIDER_ID}; private static final int INTERNAL_PROVIDER_ID_INDEX = 1;
public static final int INTERNAL_PROVIDER_ID_INDEX = 1; private static final int ID_INDEX = 0;
public static final int ID_INDEX = 0; private Activity context;
private Context context;
public TvChannelHelper(Context context) { public TvChannelHelper(Activity context) {
this.context = context; this.context = context;
} }
public boolean createTvChannel(String computerUuid, String computerName) { void requestChannelOnHomeScreen(String computerUuid) {
if (!isSupport()) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
return false; if (!isAndroidTV()) {
return;
}
Long channelId = getChannelId(computerUuid);
if (channelId == null) {
return;
}
Intent intent = new Intent(TvContract.ACTION_REQUEST_CHANNEL_BROWSABLE);
intent.putExtra(TvContract.EXTRA_CHANNEL_ID, getChannelId(computerUuid));
try {
context.startActivityForResult(intent, 0);
} catch (ActivityNotFoundException e) {
}
}
}
void createTvChannel(String computerUuid, String computerName) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (!isAndroidTV()) {
return;
} }
Intent i = new Intent(context, ShortcutTrampoline.class); Intent i = new Intent(context, ShortcutTrampoline.class);
@ -57,61 +74,36 @@ public class TvChannelHelper {
.setAppLinkIntent(i); .setAppLinkIntent(i);
Long channelId = getChannelId(computerUuid); Long channelId = getChannelId(computerUuid);
if (channelId != null) { if (channelId != null) {
context.getContentResolver().update(TvContract.buildChannelUri(channelId), context.getContentResolver().update(TvContract.buildChannelUri(channelId),
builder.toContentValues(), null, null); builder.toContentValues(), null, null);
return false; return;
} }
Uri channelUri = context.getContentResolver().insert( Uri channelUri = context.getContentResolver().insert(
TvContract.Channels.CONTENT_URI, builder.toContentValues()); TvContract.Channels.CONTENT_URI, builder.toContentValues());
if (channelUri != null) { if (channelUri != null) {
long id = ContentUris.parseId(channelUri); long id = ContentUris.parseId(channelUri);
updateChannelIcon(id); updateChannelIcon(id);
return true;
} }
return false; }
} }
private void updateChannelIcon(long id) { @TargetApi(Build.VERSION_CODES.O)
Bitmap bitmap = drawableToBitmap(context.getResources().getDrawable(R.drawable.ic_channel)); private void updateChannelIcon(long channelId) {
Bitmap logo = drawableToBitmap(context.getResources().getDrawable(R.drawable.ic_channel));
try { try {
storeChannelLogo(id, bitmap);
} finally {
bitmap.recycle();
}
}
/**
* Stores the given channel logo {@link Bitmap} in the system content provider and associate
* it with the given channel ID.
*
* @param channelId the ID of the target channel with which the given logo should be associated
* @param logo the logo image to be stored
* @return {@code true} if successfully stored the logo in the system content provider,
* otherwise {@code false}.
*/
private boolean storeChannelLogo(long channelId,
Bitmap logo) {
if (!isSupport()) {
return false;
}
boolean result = false;
Uri localUri = TvContract.buildChannelLogoUri(channelId); Uri localUri = TvContract.buildChannelLogoUri(channelId);
try (OutputStream outputStream = context.getContentResolver().openOutputStream(localUri)) { try (OutputStream outputStream = context.getContentResolver().openOutputStream(localUri)) {
result = logo.compress(Bitmap.CompressFormat.PNG, 100, outputStream); logo.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
outputStream.flush(); outputStream.flush();
} catch (SQLiteException | IOException e) { } catch (SQLiteException | IOException e) {
LimeLog.warning("Failed to store the logo to the system content provider."); LimeLog.warning("Failed to store the logo to the system content provider.");
e.printStackTrace(); e.printStackTrace();
} }
return result; } finally {
logo.recycle();
}
} }
private Bitmap drawableToBitmap(Drawable drawable) { private Bitmap drawableToBitmap(Drawable drawable) {
@ -125,10 +117,10 @@ public class TvChannelHelper {
return bitmap; return bitmap;
} }
void addGameToChannel(String computerUuid, String computerName, String appId, String appName) {
public boolean addGameToChannel(String computerUuid, String computerName, String appId, String appName) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (!isSupport()) { if (!isAndroidTV()) {
return false; return;
} }
PreviewProgramBuilder builder = new PreviewProgramBuilder(); PreviewProgramBuilder builder = new PreviewProgramBuilder();
@ -142,11 +134,10 @@ public class TvChannelHelper {
Uri resourceURI = PosterContentProvider.createBoxArtUri(computerUuid, appId); Uri resourceURI = PosterContentProvider.createBoxArtUri(computerUuid, appId);
Long channelId = getChannelId(computerUuid); Long channelId = getChannelId(computerUuid);
if (channelId == null) { if (channelId == null) {
return false; return;
} }
builder.setChannelId(channelId) builder.setChannelId(channelId)
.setType(TYPE_GAME) .setType(TYPE_GAME)
.setTitle(appName) .setTitle(appName)
@ -154,30 +145,34 @@ public class TvChannelHelper {
.setPosterArtUri(resourceURI) .setPosterArtUri(resourceURI)
.setIntent(i) .setIntent(i)
.setInternalProviderId(appId); .setInternalProviderId(appId);
Uri programUri = context.getContentResolver().insert(TvContract.PreviewPrograms.CONTENT_URI,
context.getContentResolver().insert(TvContract.PreviewPrograms.CONTENT_URI,
builder.toContentValues()); builder.toContentValues());
TvContract.requestChannelBrowsable(context, channelId); TvContract.requestChannelBrowsable(context, channelId);
return programUri != null; }
} }
public boolean deleteChannel(String computerUuid) { void deleteChannel(String computerUuid) {
if (!isSupport()) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
return false; if (!isAndroidTV()) {
return;
} }
Long channelId = getChannelId(computerUuid); Long channelId = getChannelId(computerUuid);
if (channelId == null) { if (channelId == null) {
return false; return;
} }
Uri uri = TvContract.buildChannelUri(channelId); Uri uri = TvContract.buildChannelUri(channelId);
return context.getContentResolver().delete(uri, null, null) > 0; context.getContentResolver().delete(uri, null, null);
}
} }
@TargetApi(Build.VERSION_CODES.LOLLIPOP) @TargetApi(Build.VERSION_CODES.O)
private Long getChannelId(String computerUuid) { private Long getChannelId(String computerUuid) {
Uri uri = TvContract.Channels.CONTENT_URI; Uri uri = TvContract.Channels.CONTENT_URI;
final String[] CHANNEL_PROJECTION = {TvContract.Channels._ID, TvContract.Channels.COLUMN_INTERNAL_PROVIDER_ID};
Cursor cursor = context.getContentResolver().query(uri, Cursor cursor = context.getContentResolver().query(uri,
CHANNEL_PROJECTION, CHANNEL_PROJECTION,
null, null,
@ -202,11 +197,6 @@ public class TvChannelHelper {
} }
} }
public void addGameToChannel(ComputerDetails computer, NvApp app) {
addGameToChannel(computer.uuid, computer.name, String.valueOf(app.getAppId()), app.getAppName());
}
private static <T> String toValueString(T value) { private static <T> String toValueString(T value) {
return value == null ? null : value.toString(); return value == null ? null : value.toString();
} }
@ -215,15 +205,12 @@ public class TvChannelHelper {
return intent == null ? null : intent.toUri(Intent.URI_INTENT_SCHEME); return intent == null ? null : intent.toUri(Intent.URI_INTENT_SCHEME);
} }
public boolean isSupport() { @TargetApi(Build.VERSION_CODES.O)
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { public boolean isAndroidTV() {
return false; return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK);
}
UiModeManager uiModeManager = (UiModeManager) context.getSystemService(Context.UI_MODE_SERVICE);
return uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION;
} }
@TargetApi(Build.VERSION_CODES.O)
private static class PreviewProgramBuilder { private static class PreviewProgramBuilder {
private ContentValues mValues = new ContentValues(); private ContentValues mValues = new ContentValues();
@ -275,6 +262,7 @@ public class TvChannelHelper {
} }
@TargetApi(Build.VERSION_CODES.O)
private static class ChannelBuilder { private static class ChannelBuilder {
private ContentValues mValues = new ContentValues(); private ContentValues mValues = new ContentValues();