mirror of
https://github.com/moonlight-stream/moonlight-android.git
synced 2025-07-18 10:32:43 +00:00
Refactor shortcut and channel code and handle removal of apps and PCs properly
This commit is contained in:
parent
dc984e8679
commit
d54fdc9f5f
@ -90,6 +90,10 @@ public class AppView extends Activity implements AdapterFragmentCallbacks {
|
||||
return;
|
||||
}
|
||||
|
||||
// Add a launcher shortcut for this PC (forced, since this is user interaction)
|
||||
shortcutHelper.createAppViewShortcut(computer, true, getIntent().getBooleanExtra(NEW_PAIR_EXTRA, false));
|
||||
shortcutHelper.reportComputerShortcutUsed(computer);
|
||||
|
||||
try {
|
||||
appGridAdapter = new AppGridAdapter(AppView.this,
|
||||
PreferenceConfiguration.readPreferences(AppView.this).listMode,
|
||||
@ -182,7 +186,7 @@ public class AppView extends Activity implements AdapterFragmentCallbacks {
|
||||
@Override
|
||||
public void run() {
|
||||
// Disable shortcuts referencing this PC for now
|
||||
shortcutHelper.disableShortcut(details.uuid,
|
||||
shortcutHelper.disableComputerShortcut(details,
|
||||
getResources().getString(R.string.scut_not_paired));
|
||||
|
||||
// Display a toast to the user and quit the activity
|
||||
@ -268,10 +272,6 @@ public class AppView extends Activity implements AdapterFragmentCallbacks {
|
||||
setTitle(computerName);
|
||||
label.setText(computerName);
|
||||
|
||||
// Add a launcher shortcut for this PC (forced, since this is user interaction)
|
||||
shortcutHelper.createAppViewShortcut(uuidString, computerName, uuidString, true, getIntent().getBooleanExtra(NEW_PAIR_EXTRA, false));
|
||||
shortcutHelper.reportShortcutUsed(uuidString);
|
||||
|
||||
// Bind to the computer manager service
|
||||
bindService(new Intent(this, ComputerManagerService.class), serviceConnection,
|
||||
Service.BIND_AUTO_CREATE);
|
||||
@ -420,7 +420,7 @@ public class AppView extends Activity implements AdapterFragmentCallbacks {
|
||||
case CREATE_SHORTCUT_ID:
|
||||
ImageView appImageView = info.targetView.findViewById(R.id.grid_image);
|
||||
Bitmap appBits = ((BitmapDrawable)appImageView.getDrawable()).getBitmap();
|
||||
if (!shortcutHelper.createPinnedGameShortcut(uuidString + Integer.valueOf(app.app.getAppId()).toString(), appBits, computer, app.app)) {
|
||||
if (!shortcutHelper.createPinnedGameShortcut(computer, app.app, appBits)) {
|
||||
Toast.makeText(AppView.this, getResources().getString(R.string.unable_to_pin_shortcut), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
return true;
|
||||
@ -516,6 +516,7 @@ public class AppView extends Activity implements AdapterFragmentCallbacks {
|
||||
|
||||
// This app was removed in the latest app list
|
||||
if (!foundExistingApp) {
|
||||
shortcutHelper.disableAppShortcut(computer, existingApp.app, "App removed from PC");
|
||||
appGridAdapter.removeApp(existingApp);
|
||||
updated = true;
|
||||
|
||||
|
@ -17,6 +17,7 @@ import com.limelight.binding.video.PerfOverlayListener;
|
||||
import com.limelight.nvstream.NvConnection;
|
||||
import com.limelight.nvstream.NvConnectionListener;
|
||||
import com.limelight.nvstream.StreamConfiguration;
|
||||
import com.limelight.nvstream.http.ComputerDetails;
|
||||
import com.limelight.nvstream.http.NvApp;
|
||||
import com.limelight.nvstream.input.KeyboardPacket;
|
||||
import com.limelight.nvstream.input.MouseButtonPacket;
|
||||
@ -269,10 +270,16 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
}
|
||||
|
||||
// Report this shortcut being used
|
||||
ComputerDetails computer = new ComputerDetails();
|
||||
computer.name = pcName;
|
||||
computer.uuid = uuid;
|
||||
shortcutHelper = new ShortcutHelper(this);
|
||||
shortcutHelper.reportShortcutUsed(uuid);
|
||||
shortcutHelper.reportComputerShortcutUsed(computer);
|
||||
if (appName != null) {
|
||||
shortcutHelper.reportGameLaunched(uuid, pcName, ""+appId, appName);
|
||||
NvApp app = new NvApp();
|
||||
app.setAppId(appId);
|
||||
app.setAppName(appName);
|
||||
shortcutHelper.reportGameLaunched(computer, app);
|
||||
}
|
||||
|
||||
// Initialize the MediaCodec helper before creating the decoder
|
||||
|
@ -636,7 +636,7 @@ public class PcView extends Activity implements AdapterFragmentCallbacks {
|
||||
|
||||
if (details.equals(computer.details)) {
|
||||
// Disable or delete shortcuts referencing this PC
|
||||
shortcutHelper.disableShortcut(details.uuid,
|
||||
shortcutHelper.disableComputerShortcut(details,
|
||||
getResources().getString(R.string.scut_deleted_pc));
|
||||
|
||||
pcGridAdapter.removeComputer(computer);
|
||||
|
@ -82,44 +82,44 @@ public class ShortcutHelper {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void reportShortcutUsed(String computerUuid) {
|
||||
public void reportComputerShortcutUsed(ComputerDetails computer) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
|
||||
if (getInfoForId(computerUuid) != null) {
|
||||
sm.reportShortcutUsed(computerUuid);
|
||||
if (getInfoForId(computer.uuid) != null) {
|
||||
sm.reportShortcutUsed(computer.uuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void reportGameLaunched(String computerUuid, String computerName, String appId, String appName) {
|
||||
tvChannelHelper.createTvChannel(computerUuid, computerName);
|
||||
tvChannelHelper.addGameToChannel(computerUuid, computerName, appId, appName);
|
||||
public void reportGameLaunched(ComputerDetails computer, NvApp app) {
|
||||
tvChannelHelper.createTvChannel(computer);
|
||||
tvChannelHelper.addGameToChannel(computer, app);
|
||||
}
|
||||
|
||||
public void createAppViewShortcut(String id, String computerName, String computerUuid, boolean forceAdd, boolean newlyPaired) {
|
||||
public void createAppViewShortcut(ComputerDetails computer, boolean forceAdd, boolean newlyPaired) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
|
||||
Intent i = new Intent(context, ShortcutTrampoline.class);
|
||||
i.putExtra(AppView.NAME_EXTRA, computerName);
|
||||
i.putExtra(AppView.UUID_EXTRA, computerUuid);
|
||||
i.putExtra(AppView.NAME_EXTRA, computer.name);
|
||||
i.putExtra(AppView.UUID_EXTRA, computer.uuid);
|
||||
i.setAction(Intent.ACTION_DEFAULT);
|
||||
|
||||
ShortcutInfo sinfo = new ShortcutInfo.Builder(context, id)
|
||||
ShortcutInfo sinfo = new ShortcutInfo.Builder(context, computer.uuid)
|
||||
.setIntent(i)
|
||||
.setShortLabel(computerName)
|
||||
.setLongLabel(computerName)
|
||||
.setShortLabel(computer.name)
|
||||
.setLongLabel(computer.name)
|
||||
.setIcon(Icon.createWithResource(context, R.mipmap.ic_pc_scut))
|
||||
.build();
|
||||
|
||||
ShortcutInfo existingSinfo = getInfoForId(id);
|
||||
ShortcutInfo existingSinfo = getInfoForId(computer.uuid);
|
||||
if (existingSinfo != null) {
|
||||
// Update in place
|
||||
sm.updateShortcuts(Collections.singletonList(sinfo));
|
||||
sm.enableShortcuts(Collections.singletonList(id));
|
||||
sm.enableShortcuts(Collections.singletonList(computer.uuid));
|
||||
}
|
||||
|
||||
// Reap shortcuts to make space for this if it's new
|
||||
// NOTE: This CAN'T be an else on the above if, because it's
|
||||
// possible that we have an existing shortcut but it's not a dynamic one.
|
||||
if (!isExistingDynamicShortcut(id)) {
|
||||
if (!isExistingDynamicShortcut(computer.uuid)) {
|
||||
// To avoid a random carousel of shortcuts popping in and out based on polling status,
|
||||
// we only add shortcuts if it's not at the limit or the user made a conscious action
|
||||
// to interact with this PC.
|
||||
@ -132,24 +132,28 @@ 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);
|
||||
tvChannelHelper.createTvChannel(computer);
|
||||
tvChannelHelper.requestChannelOnHomeScreen(computer);
|
||||
}
|
||||
}
|
||||
|
||||
public void createAppViewShortcutForOnlineHost(ComputerDetails details) {
|
||||
createAppViewShortcut(details.uuid, details.name, details.uuid, false, false);
|
||||
createAppViewShortcut(details, false, false);
|
||||
}
|
||||
|
||||
private String getShortcutIdForGame(ComputerDetails computer, NvApp app) {
|
||||
return computer.uuid + app.getAppId();
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.O)
|
||||
public boolean createPinnedGameShortcut(String id, Bitmap iconBits, String computerName, String computerUuid, String appName, String appId) {
|
||||
public boolean createPinnedGameShortcut(ComputerDetails computer, NvApp app, Bitmap iconBits) {
|
||||
if (sm.isRequestPinShortcutSupported()) {
|
||||
Icon appIcon;
|
||||
Intent i = new Intent(context, ShortcutTrampoline.class);
|
||||
|
||||
i.putExtra(AppView.NAME_EXTRA, computerName);
|
||||
i.putExtra(AppView.UUID_EXTRA, computerUuid);
|
||||
i.putExtra(ShortcutTrampoline.APP_ID_EXTRA, appId);
|
||||
i.putExtra(AppView.NAME_EXTRA, computer.name);
|
||||
i.putExtra(AppView.UUID_EXTRA, computer.uuid);
|
||||
i.putExtra(ShortcutTrampoline.APP_ID_EXTRA, ""+app.getAppId());
|
||||
i.setAction(Intent.ACTION_DEFAULT);
|
||||
|
||||
if (iconBits != null) {
|
||||
@ -158,9 +162,9 @@ public class ShortcutHelper {
|
||||
appIcon = Icon.createWithResource(context, R.mipmap.ic_pc_scut);
|
||||
}
|
||||
|
||||
ShortcutInfo sInfo = new ShortcutInfo.Builder(context, id)
|
||||
ShortcutInfo sInfo = new ShortcutInfo.Builder(context, getShortcutIdForGame(computer, app))
|
||||
.setIntent(i)
|
||||
.setShortLabel(appName + " (" + computerName + ")")
|
||||
.setShortLabel(app.getAppName() + " (" + computer.name + ")")
|
||||
.setIcon(appIcon)
|
||||
.build();
|
||||
|
||||
@ -170,15 +174,32 @@ public class ShortcutHelper {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean createPinnedGameShortcut(String id, Bitmap iconBits, ComputerDetails cDetails, NvApp app) {
|
||||
return createPinnedGameShortcut(id, iconBits, cDetails.name, cDetails.uuid, app.getAppName(), Integer.valueOf(app.getAppId()).toString());
|
||||
public void disableComputerShortcut(ComputerDetails computer, CharSequence reason) {
|
||||
tvChannelHelper.deleteChannel(computer);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
|
||||
// Delete the computer shortcut itself
|
||||
if (getInfoForId(computer.uuid) != null) {
|
||||
sm.disableShortcuts(Collections.singletonList(computer.uuid), reason);
|
||||
}
|
||||
|
||||
public void disableShortcut(String uuid, CharSequence reason) {
|
||||
tvChannelHelper.deleteChannel(uuid);
|
||||
// Delete all associated app shortcuts too
|
||||
List<ShortcutInfo> shortcuts = getAllShortcuts();
|
||||
LinkedList<String> appShortcutIds = new LinkedList<>();
|
||||
for (ShortcutInfo info : shortcuts) {
|
||||
if (info.getId().startsWith(computer.uuid)) {
|
||||
appShortcutIds.add(info.getId());
|
||||
}
|
||||
}
|
||||
sm.disableShortcuts(appShortcutIds, reason);
|
||||
}
|
||||
}
|
||||
|
||||
public void disableAppShortcut(ComputerDetails computer, NvApp app, CharSequence reason) {
|
||||
tvChannelHelper.deleteProgram(computer, app);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
|
||||
if (getInfoForId(uuid) != null) {
|
||||
sm.disableShortcuts(Collections.singletonList(uuid), reason);
|
||||
String id = getShortcutIdForGame(computer, app);
|
||||
if (getInfoForId(id) != null) {
|
||||
sm.disableShortcuts(Collections.singletonList(id), reason);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,8 @@ import com.limelight.LimeLog;
|
||||
import com.limelight.PosterContentProvider;
|
||||
import com.limelight.R;
|
||||
import com.limelight.ShortcutTrampoline;
|
||||
import com.limelight.nvstream.http.ComputerDetails;
|
||||
import com.limelight.nvstream.http.NvApp;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
@ -37,19 +39,19 @@ public class TvChannelHelper {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
void requestChannelOnHomeScreen(String computerUuid) {
|
||||
void requestChannelOnHomeScreen(ComputerDetails computer) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
if (!isAndroidTV()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Long channelId = getChannelId(computerUuid);
|
||||
Long channelId = getChannelId(computer.uuid);
|
||||
if (channelId == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Intent intent = new Intent(TvContract.ACTION_REQUEST_CHANNEL_BROWSABLE);
|
||||
intent.putExtra(TvContract.EXTRA_CHANNEL_ID, getChannelId(computerUuid));
|
||||
intent.putExtra(TvContract.EXTRA_CHANNEL_ID, getChannelId(computer.uuid));
|
||||
try {
|
||||
context.startActivityForResult(intent, 0);
|
||||
} catch (ActivityNotFoundException e) {
|
||||
@ -57,23 +59,23 @@ public class TvChannelHelper {
|
||||
}
|
||||
}
|
||||
|
||||
void createTvChannel(String computerUuid, String computerName) {
|
||||
void createTvChannel(ComputerDetails computer) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
if (!isAndroidTV()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Intent i = new Intent(context, ShortcutTrampoline.class);
|
||||
i.putExtra(AppView.NAME_EXTRA, computerName);
|
||||
i.putExtra(AppView.UUID_EXTRA, computerUuid);
|
||||
i.putExtra(AppView.NAME_EXTRA, computer.name);
|
||||
i.putExtra(AppView.UUID_EXTRA, computer.uuid);
|
||||
i.setAction(Intent.ACTION_DEFAULT);
|
||||
ChannelBuilder builder = new ChannelBuilder()
|
||||
.setType(TvContract.Channels.TYPE_PREVIEW)
|
||||
.setDisplayName(computerName)
|
||||
.setInternalProviderId(computerUuid)
|
||||
.setDisplayName(computer.name)
|
||||
.setInternalProviderId(computer.uuid)
|
||||
.setAppLinkIntent(i);
|
||||
|
||||
Long channelId = getChannelId(computerUuid);
|
||||
Long channelId = getChannelId(computer.uuid);
|
||||
if (channelId != null) {
|
||||
context.getContentResolver().update(TvContract.buildChannelUri(channelId),
|
||||
builder.toContentValues(), null, null);
|
||||
@ -117,7 +119,7 @@ public class TvChannelHelper {
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
void addGameToChannel(String computerUuid, String computerName, String appId, String appName) {
|
||||
void addGameToChannel(ComputerDetails computer, NvApp app) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
if (!isAndroidTV()) {
|
||||
return;
|
||||
@ -126,29 +128,29 @@ public class TvChannelHelper {
|
||||
PreviewProgramBuilder builder = new PreviewProgramBuilder();
|
||||
Intent i = new Intent(context, ShortcutTrampoline.class);
|
||||
|
||||
i.putExtra(AppView.NAME_EXTRA, computerName);
|
||||
i.putExtra(AppView.UUID_EXTRA, computerUuid);
|
||||
i.putExtra(ShortcutTrampoline.APP_ID_EXTRA, appId);
|
||||
i.putExtra(AppView.NAME_EXTRA, computer.name);
|
||||
i.putExtra(AppView.UUID_EXTRA, computer.uuid);
|
||||
i.putExtra(ShortcutTrampoline.APP_ID_EXTRA, ""+app.getAppId());
|
||||
i.setAction(Intent.ACTION_DEFAULT);
|
||||
|
||||
Uri resourceURI = PosterContentProvider.createBoxArtUri(computerUuid, appId);
|
||||
Uri resourceURI = PosterContentProvider.createBoxArtUri(computer.uuid, ""+app.getAppId());
|
||||
|
||||
Long channelId = getChannelId(computerUuid);
|
||||
Long channelId = getChannelId(computer.uuid);
|
||||
if (channelId == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
builder.setChannelId(channelId)
|
||||
.setType(TYPE_GAME)
|
||||
.setTitle(appName)
|
||||
.setTitle(app.getAppName())
|
||||
.setPosterArtAspectRatio(ASPECT_RATIO_MOVIE_POSTER)
|
||||
.setPosterArtUri(resourceURI)
|
||||
.setIntent(i)
|
||||
.setInternalProviderId(appId)
|
||||
.setInternalProviderId(""+app.getAppId())
|
||||
// Weight should increase each time we run the game
|
||||
.setWeight((int)((System.currentTimeMillis() - 1500000000000L) / 1000));
|
||||
|
||||
Long programId = getProgramId(channelId, appId);
|
||||
Long programId = getProgramId(channelId, ""+app.getAppId());
|
||||
if (programId != null) {
|
||||
context.getContentResolver().update(TvContract.buildPreviewProgramUri(programId),
|
||||
builder.toContentValues(), null, null);
|
||||
@ -162,18 +164,39 @@ public class TvChannelHelper {
|
||||
}
|
||||
}
|
||||
|
||||
void deleteChannel(String computerUuid) {
|
||||
void deleteChannel(ComputerDetails computer) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
if (!isAndroidTV()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Long channelId = getChannelId(computerUuid);
|
||||
Long channelId = getChannelId(computer.uuid);
|
||||
if (channelId == null) {
|
||||
return;
|
||||
}
|
||||
Uri uri = TvContract.buildChannelUri(channelId);
|
||||
context.getContentResolver().delete(uri, null, null);
|
||||
|
||||
context.getContentResolver().delete(TvContract.buildChannelUri(channelId), null, null);
|
||||
}
|
||||
}
|
||||
|
||||
void deleteProgram(ComputerDetails computer, NvApp app) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
if (!isAndroidTV()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Long channelId = getChannelId(computer.uuid);
|
||||
if (channelId == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Long programId = getProgramId(channelId, ""+app.getAppId());
|
||||
if (programId == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
context.getContentResolver().delete(TvContract.buildPreviewProgramUri(programId), null, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user