mirror of
https://github.com/moonlight-stream/moonlight-android.git
synced 2025-07-04 00:35:47 +00:00
Add launcher shortcuts and fix duplicate pairing error
This commit is contained in:
parent
b02db2c182
commit
a107b5e652
@ -4,12 +4,12 @@ import org.apache.tools.ant.taskdefs.condition.Os
|
|||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 24
|
compileSdkVersion 25
|
||||||
buildToolsVersion "24.0.3"
|
buildToolsVersion "25.0.0"
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdkVersion 16
|
minSdkVersion 16
|
||||||
targetSdkVersion 24
|
targetSdkVersion 25
|
||||||
|
|
||||||
versionName "4.7.2"
|
versionName "4.7.2"
|
||||||
versionCode = 106
|
versionCode = 106
|
||||||
|
Binary file not shown.
@ -11,12 +11,14 @@ import com.limelight.grid.AppGridAdapter;
|
|||||||
import com.limelight.nvstream.http.ComputerDetails;
|
import com.limelight.nvstream.http.ComputerDetails;
|
||||||
import com.limelight.nvstream.http.NvApp;
|
import com.limelight.nvstream.http.NvApp;
|
||||||
import com.limelight.nvstream.http.NvHTTP;
|
import com.limelight.nvstream.http.NvHTTP;
|
||||||
|
import com.limelight.nvstream.http.PairingManager;
|
||||||
import com.limelight.preferences.PreferenceConfiguration;
|
import com.limelight.preferences.PreferenceConfiguration;
|
||||||
import com.limelight.ui.AdapterFragment;
|
import com.limelight.ui.AdapterFragment;
|
||||||
import com.limelight.ui.AdapterFragmentCallbacks;
|
import com.limelight.ui.AdapterFragmentCallbacks;
|
||||||
import com.limelight.utils.CacheHelper;
|
import com.limelight.utils.CacheHelper;
|
||||||
import com.limelight.utils.Dialog;
|
import com.limelight.utils.Dialog;
|
||||||
import com.limelight.utils.ServerHelper;
|
import com.limelight.utils.ServerHelper;
|
||||||
|
import com.limelight.utils.ShortcutHelper;
|
||||||
import com.limelight.utils.SpinnerDialog;
|
import com.limelight.utils.SpinnerDialog;
|
||||||
import com.limelight.utils.UiHelper;
|
import com.limelight.utils.UiHelper;
|
||||||
|
|
||||||
@ -43,14 +45,16 @@ import android.widget.AdapterView.AdapterContextMenuInfo;
|
|||||||
public class AppView extends Activity implements AdapterFragmentCallbacks {
|
public class AppView extends Activity implements AdapterFragmentCallbacks {
|
||||||
private AppGridAdapter appGridAdapter;
|
private AppGridAdapter appGridAdapter;
|
||||||
private String uuidString;
|
private String uuidString;
|
||||||
|
private ShortcutHelper shortcutHelper;
|
||||||
|
|
||||||
private ComputerDetails computer;
|
private ComputerDetails computer;
|
||||||
private ComputerManagerService.ApplistPoller poller;
|
private ComputerManagerService.ApplistPoller poller;
|
||||||
private SpinnerDialog blockingLoadSpinner;
|
private SpinnerDialog blockingLoadSpinner, blockingServerinfoSpinner;
|
||||||
private String lastRawApplist;
|
private String lastRawApplist;
|
||||||
private int lastRunningAppId;
|
private int lastRunningAppId;
|
||||||
private boolean suspendGridUpdates;
|
private boolean suspendGridUpdates;
|
||||||
private boolean inForeground;
|
private boolean inForeground;
|
||||||
|
private boolean launchedFromShortcut;
|
||||||
|
|
||||||
private final static int START_OR_RESUME_ID = 1;
|
private final static int START_OR_RESUME_ID = 1;
|
||||||
private final static int QUIT_ID = 2;
|
private final static int QUIT_ID = 2;
|
||||||
@ -59,6 +63,7 @@ public class AppView extends Activity implements AdapterFragmentCallbacks {
|
|||||||
|
|
||||||
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 SHORTCUT_EXTRA = "Shortcut";
|
||||||
|
|
||||||
private ComputerManagerService.ComputerManagerBinder managerBinder;
|
private ComputerManagerService.ComputerManagerBinder managerBinder;
|
||||||
private final ServiceConnection serviceConnection = new ServiceConnection() {
|
private final ServiceConnection serviceConnection = new ServiceConnection() {
|
||||||
@ -132,7 +137,7 @@ public class AppView extends Activity implements AdapterFragmentCallbacks {
|
|||||||
|
|
||||||
managerBinder.startPolling(new ComputerManagerListener() {
|
managerBinder.startPolling(new ComputerManagerListener() {
|
||||||
@Override
|
@Override
|
||||||
public void notifyComputerUpdated(ComputerDetails details) {
|
public void notifyComputerUpdated(final ComputerDetails details) {
|
||||||
// Do nothing if updates are suspended
|
// Do nothing if updates are suspended
|
||||||
if (suspendGridUpdates) {
|
if (suspendGridUpdates) {
|
||||||
return;
|
return;
|
||||||
@ -157,6 +162,48 @@ public class AppView extends Activity implements AdapterFragmentCallbacks {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Close immediately if the PC is no longer paired
|
||||||
|
if (details.state == ComputerDetails.State.ONLINE && details.pairState != PairingManager.PairState.PAIRED) {
|
||||||
|
AppView.this.runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
// Disable shortcuts referencing this PC for now
|
||||||
|
shortcutHelper.disableShortcut(details.uuid.toString(),
|
||||||
|
getResources().getString(R.string.scut_not_paired));
|
||||||
|
|
||||||
|
// 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();
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (launchedFromShortcut) {
|
||||||
|
if (details.state == ComputerDetails.State.ONLINE) {
|
||||||
|
if (blockingServerinfoSpinner != null) {
|
||||||
|
blockingServerinfoSpinner.dismiss();
|
||||||
|
blockingServerinfoSpinner = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (details.runningGameId != 0) {
|
||||||
|
AppView.this.runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
// We have to finish this activity here otherwise we'll get into a loop
|
||||||
|
// when the user hits back
|
||||||
|
finish();
|
||||||
|
|
||||||
|
// When launched from shortcut, resume the running game
|
||||||
|
ServerHelper.doStart(AppView.this, new NvApp("app", details.runningGameId), computer, managerBinder);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// App list is the same or empty
|
// App list is the same or empty
|
||||||
if (details.rawAppList == null || details.rawAppList.equals(lastRawApplist)) {
|
if (details.rawAppList == null || details.rawAppList.equals(lastRawApplist)) {
|
||||||
|
|
||||||
@ -208,6 +255,8 @@ public class AppView extends Activity implements AdapterFragmentCallbacks {
|
|||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
shortcutHelper = new ShortcutHelper(this);
|
||||||
|
|
||||||
String locale = PreferenceConfiguration.readPreferences(this).language;
|
String locale = PreferenceConfiguration.readPreferences(this).language;
|
||||||
if (!locale.equals(PreferenceConfiguration.DEFAULT_LANGUAGE)) {
|
if (!locale.equals(PreferenceConfiguration.DEFAULT_LANGUAGE)) {
|
||||||
Configuration config = new Configuration(getResources().getConfiguration());
|
Configuration config = new Configuration(getResources().getConfiguration());
|
||||||
@ -221,6 +270,15 @@ public class AppView extends Activity implements AdapterFragmentCallbacks {
|
|||||||
|
|
||||||
uuidString = getIntent().getStringExtra(UUID_EXTRA);
|
uuidString = getIntent().getStringExtra(UUID_EXTRA);
|
||||||
|
|
||||||
|
launchedFromShortcut = getIntent().getBooleanExtra(SHORTCUT_EXTRA, false);
|
||||||
|
if (launchedFromShortcut) {
|
||||||
|
// Display blocking loading spinner
|
||||||
|
blockingLoadSpinner = SpinnerDialog.displayDialog(this, getResources().getString(R.string.conn_establishing_title),
|
||||||
|
getResources().getString(R.string.applist_connect_msg), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
shortcutHelper.reportShortcutUsed(uuidString);
|
||||||
|
|
||||||
String labelText = getResources().getString(R.string.title_applist)+" "+getIntent().getStringExtra(NAME_EXTRA);
|
String labelText = getResources().getString(R.string.title_applist)+" "+getIntent().getStringExtra(NAME_EXTRA);
|
||||||
TextView label = (TextView) findViewById(R.id.appListText);
|
TextView label = (TextView) findViewById(R.id.appListText);
|
||||||
setTitle(labelText);
|
setTitle(labelText);
|
||||||
|
@ -24,6 +24,7 @@ import com.limelight.ui.AdapterFragment;
|
|||||||
import com.limelight.ui.AdapterFragmentCallbacks;
|
import com.limelight.ui.AdapterFragmentCallbacks;
|
||||||
import com.limelight.utils.Dialog;
|
import com.limelight.utils.Dialog;
|
||||||
import com.limelight.utils.ServerHelper;
|
import com.limelight.utils.ServerHelper;
|
||||||
|
import com.limelight.utils.ShortcutHelper;
|
||||||
import com.limelight.utils.UiHelper;
|
import com.limelight.utils.UiHelper;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
@ -52,6 +53,7 @@ import android.widget.AdapterView.AdapterContextMenuInfo;
|
|||||||
public class PcView extends Activity implements AdapterFragmentCallbacks {
|
public class PcView extends Activity implements AdapterFragmentCallbacks {
|
||||||
private RelativeLayout noPcFoundLayout;
|
private RelativeLayout noPcFoundLayout;
|
||||||
private PcGridAdapter pcGridAdapter;
|
private PcGridAdapter pcGridAdapter;
|
||||||
|
private ShortcutHelper shortcutHelper;
|
||||||
private ComputerManagerService.ComputerManagerBinder managerBinder;
|
private ComputerManagerService.ComputerManagerBinder managerBinder;
|
||||||
private boolean freezeUpdates, runningPolling, inForeground;
|
private boolean freezeUpdates, runningPolling, inForeground;
|
||||||
private final ServiceConnection serviceConnection = new ServiceConnection() {
|
private final ServiceConnection serviceConnection = new ServiceConnection() {
|
||||||
@ -142,6 +144,8 @@ public class PcView extends Activity implements AdapterFragmentCallbacks {
|
|||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
shortcutHelper = new ShortcutHelper(this);
|
||||||
|
|
||||||
String locale = PreferenceConfiguration.readPreferences(this).language;
|
String locale = PreferenceConfiguration.readPreferences(this).language;
|
||||||
if (!locale.equals(PreferenceConfiguration.DEFAULT_LANGUAGE)) {
|
if (!locale.equals(PreferenceConfiguration.DEFAULT_LANGUAGE)) {
|
||||||
Configuration config = new Configuration(getResources().getConfiguration());
|
Configuration config = new Configuration(getResources().getConfiguration());
|
||||||
@ -334,6 +338,9 @@ public class PcView extends Activity implements AdapterFragmentCallbacks {
|
|||||||
else if (pairState == PairingManager.PairState.FAILED) {
|
else if (pairState == PairingManager.PairState.FAILED) {
|
||||||
message = getResources().getString(R.string.pair_fail);
|
message = getResources().getString(R.string.pair_fail);
|
||||||
}
|
}
|
||||||
|
else if (pairState == PairingManager.PairState.ALREADY_IN_PROGRESS) {
|
||||||
|
message = getResources().getString(R.string.pair_already_in_progress);
|
||||||
|
}
|
||||||
else if (pairState == PairingManager.PairState.PAIRED) {
|
else if (pairState == PairingManager.PairState.PAIRED) {
|
||||||
// Just navigate to the app view without displaying a toast
|
// Just navigate to the app view without displaying a toast
|
||||||
message = null;
|
message = null;
|
||||||
@ -486,6 +493,8 @@ public class PcView extends Activity implements AdapterFragmentCallbacks {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shortcutHelper.createAppViewShortcut(computer.uuid.toString(), computer);
|
||||||
|
|
||||||
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.toString());
|
i.putExtra(AppView.UUID_EXTRA, computer.uuid.toString());
|
||||||
@ -558,6 +567,10 @@ public class PcView extends Activity implements AdapterFragmentCallbacks {
|
|||||||
ComputerObject computer = (ComputerObject) pcGridAdapter.getItem(i);
|
ComputerObject computer = (ComputerObject) pcGridAdapter.getItem(i);
|
||||||
|
|
||||||
if (details.equals(computer.details)) {
|
if (details.equals(computer.details)) {
|
||||||
|
// Disable or delete shortcuts referencing this PC
|
||||||
|
shortcutHelper.disableShortcut(details.uuid.toString(),
|
||||||
|
getResources().getString(R.string.scut_deleted_pc));
|
||||||
|
|
||||||
pcGridAdapter.removeComputer(computer);
|
pcGridAdapter.removeComputer(computer);
|
||||||
pcGridAdapter.notifyDataSetChanged();
|
pcGridAdapter.notifyDataSetChanged();
|
||||||
|
|
||||||
|
115
app/src/main/java/com/limelight/utils/ShortcutHelper.java
Normal file
115
app/src/main/java/com/limelight/utils/ShortcutHelper.java
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
package com.limelight.utils;
|
||||||
|
|
||||||
|
import android.annotation.TargetApi;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.pm.ShortcutInfo;
|
||||||
|
import android.content.pm.ShortcutManager;
|
||||||
|
import android.os.Build;
|
||||||
|
|
||||||
|
import com.limelight.AppView;
|
||||||
|
import com.limelight.R;
|
||||||
|
import com.limelight.nvstream.http.ComputerDetails;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class ShortcutHelper {
|
||||||
|
|
||||||
|
private final ShortcutManager sm;
|
||||||
|
private final Context context;
|
||||||
|
|
||||||
|
public ShortcutHelper(Context context) {
|
||||||
|
this.context = context;
|
||||||
|
if (Build.VERSION.SDK_INT >= 25) {
|
||||||
|
sm = context.getSystemService(ShortcutManager.class);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sm = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@TargetApi(25)
|
||||||
|
private void reapShortcutsForDynamicAdd() {
|
||||||
|
List<ShortcutInfo> dynamicShortcuts = sm.getDynamicShortcuts();
|
||||||
|
while (dynamicShortcuts.size() >= sm.getMaxShortcutCountPerActivity()) {
|
||||||
|
ShortcutInfo maxRankShortcut = dynamicShortcuts.get(0);
|
||||||
|
for (ShortcutInfo scut : dynamicShortcuts) {
|
||||||
|
if (maxRankShortcut.getRank() < scut.getRank()) {
|
||||||
|
maxRankShortcut = scut;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sm.removeDynamicShortcuts(Arrays.asList(maxRankShortcut.getId()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@TargetApi(25)
|
||||||
|
private List<ShortcutInfo> getAllShortcuts() {
|
||||||
|
LinkedList<ShortcutInfo> list = new LinkedList<>();
|
||||||
|
list.addAll(sm.getDynamicShortcuts());
|
||||||
|
list.addAll(sm.getPinnedShortcuts());
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
@TargetApi(25)
|
||||||
|
private ShortcutInfo getInfoForId(String id) {
|
||||||
|
List<ShortcutInfo> shortcuts = getAllShortcuts();
|
||||||
|
|
||||||
|
for (ShortcutInfo info : shortcuts) {
|
||||||
|
if (info.getId().equals(id)) {
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reportShortcutUsed(String id) {
|
||||||
|
if (Build.VERSION.SDK_INT >= 25) {
|
||||||
|
ShortcutInfo sinfo = getInfoForId(id);
|
||||||
|
if (sinfo != null) {
|
||||||
|
sm.reportShortcutUsed(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void createAppViewShortcut(String id, ComputerDetails details) {
|
||||||
|
if (Build.VERSION.SDK_INT >= 25) {
|
||||||
|
Intent i = new Intent(context, AppView.class);
|
||||||
|
i.putExtra(AppView.NAME_EXTRA, details.name);
|
||||||
|
i.putExtra(AppView.UUID_EXTRA, details.uuid.toString());
|
||||||
|
i.putExtra(AppView.SHORTCUT_EXTRA, true);
|
||||||
|
i.setAction(Intent.ACTION_DEFAULT);
|
||||||
|
|
||||||
|
ShortcutInfo sinfo = new ShortcutInfo.Builder(context, id)
|
||||||
|
.setIntent(i)
|
||||||
|
.setShortLabel(details.name)
|
||||||
|
.setLongLabel(details.name)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
ShortcutInfo existingSinfo = getInfoForId(id);
|
||||||
|
if (existingSinfo != null) {
|
||||||
|
// Update in place
|
||||||
|
sm.updateShortcuts(Arrays.asList(sinfo));
|
||||||
|
sm.enableShortcuts(Arrays.asList(id));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Reap shortcuts to make space for this new one
|
||||||
|
reapShortcutsForDynamicAdd();
|
||||||
|
|
||||||
|
// Add the new shortcut
|
||||||
|
sm.addDynamicShortcuts(Arrays.asList(sinfo));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void disableShortcut(String id, CharSequence reason) {
|
||||||
|
if (Build.VERSION.SDK_INT >= 25) {
|
||||||
|
ShortcutInfo sinfo = getInfoForId(id);
|
||||||
|
if (sinfo != null) {
|
||||||
|
sm.disableShortcuts(Arrays.asList(id), reason);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
|
<!-- Shortcut strings -->
|
||||||
|
<string name="scut_deleted_pc">PC deleted</string>
|
||||||
|
<string name="scut_not_paired">PC not paired</string>
|
||||||
|
|
||||||
<!-- PC view menu entries -->
|
<!-- PC view menu entries -->
|
||||||
<string name="pcview_menu_app_list">View Game List</string>
|
<string name="pcview_menu_app_list">View Game List</string>
|
||||||
@ -16,6 +19,7 @@
|
|||||||
<string name="pair_pairing_msg">Please enter the following PIN on the target PC:</string>
|
<string name="pair_pairing_msg">Please enter the following PIN on the target PC:</string>
|
||||||
<string name="pair_incorrect_pin">Incorrect PIN</string>
|
<string name="pair_incorrect_pin">Incorrect PIN</string>
|
||||||
<string name="pair_fail">Pairing failed</string>
|
<string name="pair_fail">Pairing failed</string>
|
||||||
|
<string name="pair_already_in_progress">Pairing already in progress</string>
|
||||||
|
|
||||||
<!-- WOL messages -->
|
<!-- WOL messages -->
|
||||||
<string name="wol_pc_online">Computer is online</string>
|
<string name="wol_pc_online">Computer is online</string>
|
||||||
@ -63,6 +67,7 @@
|
|||||||
|
|
||||||
<!-- AppList activity -->
|
<!-- AppList activity -->
|
||||||
<string name="title_applist">Apps on</string>
|
<string name="title_applist">Apps on</string>
|
||||||
|
<string name="applist_connect_msg">Connecting to PC…</string>
|
||||||
<string name="applist_menu_resume">Resume Session</string>
|
<string name="applist_menu_resume">Resume Session</string>
|
||||||
<string name="applist_menu_quit">Quit Session</string>
|
<string name="applist_menu_quit">Quit Session</string>
|
||||||
<string name="applist_menu_quit_and_start">Quit Current Game and Start</string>
|
<string name="applist_menu_quit_and_start">Quit Current Game and Start</string>
|
||||||
|
@ -4,7 +4,7 @@ buildscript {
|
|||||||
jcenter()
|
jcenter()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:2.2.0'
|
classpath 'com.android.tools.build:gradle:2.2.2'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user