diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 9ba989ce..487c8d85 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -51,6 +51,15 @@
+
+
+
+
diff --git a/app/src/main/java/com/limelight/AppView.java b/app/src/main/java/com/limelight/AppView.java
index a85c91fa..673d4a2e 100644
--- a/app/src/main/java/com/limelight/AppView.java
+++ b/app/src/main/java/com/limelight/AppView.java
@@ -49,12 +49,11 @@ public class AppView extends Activity implements AdapterFragmentCallbacks {
private ComputerDetails computer;
private ComputerManagerService.ApplistPoller poller;
- private SpinnerDialog blockingLoadSpinner, blockingServerinfoSpinner;
+ private SpinnerDialog blockingLoadSpinner;
private String lastRawApplist;
private int lastRunningAppId;
private boolean suspendGridUpdates;
private boolean inForeground;
- private boolean launchedFromShortcut;
private final static int START_OR_RESUME_ID = 1;
private final static int QUIT_ID = 2;
@@ -63,7 +62,6 @@ public class AppView extends Activity implements AdapterFragmentCallbacks {
public final static String NAME_EXTRA = "Name";
public final static String UUID_EXTRA = "UUID";
- public final static String SHORTCUT_EXTRA = "Shortcut";
private ComputerManagerService.ComputerManagerBinder managerBinder;
private final ServiceConnection serviceConnection = new ServiceConnection() {
@@ -183,30 +181,6 @@ public class AppView extends Activity implements AdapterFragmentCallbacks {
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
if (details.rawAppList == null || details.rawAppList.equals(lastRawApplist)) {
@@ -274,13 +248,6 @@ public class AppView extends Activity implements AdapterFragmentCallbacks {
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);
diff --git a/app/src/main/java/com/limelight/AppViewShortcutTrampoline.java b/app/src/main/java/com/limelight/AppViewShortcutTrampoline.java
new file mode 100644
index 00000000..19c136ad
--- /dev/null
+++ b/app/src/main/java/com/limelight/AppViewShortcutTrampoline.java
@@ -0,0 +1,119 @@
+package com.limelight;
+
+import android.app.Activity;
+import android.app.Service;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Bundle;
+import android.os.IBinder;
+
+import com.limelight.computers.ComputerManagerListener;
+import com.limelight.computers.ComputerManagerService;
+import com.limelight.nvstream.http.ComputerDetails;
+import com.limelight.nvstream.http.NvApp;
+import com.limelight.utils.ServerHelper;
+import com.limelight.utils.SpinnerDialog;
+import com.limelight.utils.UiHelper;
+
+import java.util.UUID;
+
+public class AppViewShortcutTrampoline extends Activity {
+ private String uuidString;
+
+ private ComputerDetails computer;
+ private SpinnerDialog blockingLoadSpinner;
+
+ public final static String UUID_EXTRA = "UUID";
+
+ private ComputerManagerService.ComputerManagerBinder managerBinder;
+ private final ServiceConnection serviceConnection = new ServiceConnection() {
+ public void onServiceConnected(ComponentName className, IBinder binder) {
+ final ComputerManagerService.ComputerManagerBinder localBinder =
+ ((ComputerManagerService.ComputerManagerBinder)binder);
+
+ // Wait in a separate thread to avoid stalling the UI
+ new Thread() {
+ @Override
+ public void run() {
+ // Wait for the binder to be ready
+ localBinder.waitForReady();
+
+ // Now make the binder visible
+ managerBinder = localBinder;
+
+ // Get the computer object
+ computer = managerBinder.getComputer(UUID.fromString(uuidString));
+
+ // Force CMS to repoll this machine
+ managerBinder.invalidateStateForComputer(computer.uuid);
+
+ // Start polling
+ managerBinder.startPolling(new ComputerManagerListener() {
+ @Override
+ public void notifyComputerUpdated(final ComputerDetails details) {
+ // Don't care about other computers
+ if (!details.uuid.toString().equalsIgnoreCase(uuidString)) {
+ return;
+ }
+
+ if (details.state != ComputerDetails.State.UNKNOWN) {
+ // Close this activity
+ finish();
+
+ if (details.runningGameId != 0) {
+ // A game is running so launch straight to the game activity
+ ServerHelper.doStart(AppViewShortcutTrampoline.this,
+ new NvApp("app", details.runningGameId), details, managerBinder);
+ }
+ else {
+ // No game running or computer offline - launch to the AppView
+ Intent i = new Intent(getIntent());
+ i.setClass(AppViewShortcutTrampoline.this, AppView.class);
+ startActivity(i);
+ }
+ }
+ }
+ });
+ }
+ }.start();
+ }
+
+ public void onServiceDisconnected(ComponentName className) {
+ managerBinder = null;
+ }
+ };
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ UiHelper.notifyNewRootView(this);
+
+ uuidString = getIntent().getStringExtra(UUID_EXTRA);
+
+ // Bind to the computer manager service
+ bindService(new Intent(this, ComputerManagerService.class), serviceConnection,
+ Service.BIND_AUTO_CREATE);
+
+ blockingLoadSpinner = SpinnerDialog.displayDialog(this, getResources().getString(R.string.conn_establishing_title),
+ getResources().getString(R.string.applist_connect_msg), true);
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+
+ blockingLoadSpinner.dismiss();
+
+ if (managerBinder != null) {
+ unbindService(serviceConnection);
+ }
+
+ if (managerBinder != null) {
+ managerBinder.stopPolling();
+ }
+
+ finish();
+ }
+}
diff --git a/app/src/main/java/com/limelight/utils/ShortcutHelper.java b/app/src/main/java/com/limelight/utils/ShortcutHelper.java
index f7465027..538a6cb9 100644
--- a/app/src/main/java/com/limelight/utils/ShortcutHelper.java
+++ b/app/src/main/java/com/limelight/utils/ShortcutHelper.java
@@ -5,9 +5,12 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutManager;
+import android.graphics.drawable.Icon;
import android.os.Build;
import com.limelight.AppView;
+import com.limelight.AppViewShortcutTrampoline;
+import com.limelight.R;
import com.limelight.nvstream.http.ComputerDetails;
import java.util.Collections;
@@ -75,16 +78,16 @@ public class ShortcutHelper {
public void createAppViewShortcut(String id, ComputerDetails details) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
- Intent i = new Intent(context, AppView.class);
+ Intent i = new Intent(context, AppViewShortcutTrampoline.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)
+ .setIcon(Icon.createWithResource(context, R.mipmap.ic_pc_scut))
.build();
ShortcutInfo existingSinfo = getInfoForId(id);
@@ -98,7 +101,7 @@ public class ShortcutHelper {
reapShortcutsForDynamicAdd();
// Add the new shortcut
- //TODO: Testing and proper icon - sm.addDynamicShortcuts(Arrays.asList(sinfo));
+ sm.addDynamicShortcuts(Collections.singletonList(sinfo));
}
}
}
diff --git a/app/src/main/res/mipmap-hdpi/ic_pc_scut.png b/app/src/main/res/mipmap-hdpi/ic_pc_scut.png
new file mode 100644
index 00000000..edd9a152
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_pc_scut.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_pc_scut.png b/app/src/main/res/mipmap-mdpi/ic_pc_scut.png
new file mode 100644
index 00000000..ff3ae496
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_pc_scut.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_pc_scut.png b/app/src/main/res/mipmap-xhdpi/ic_pc_scut.png
new file mode 100644
index 00000000..6d9195d8
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_pc_scut.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_pc_scut.png b/app/src/main/res/mipmap-xxhdpi/ic_pc_scut.png
new file mode 100644
index 00000000..9c7799b4
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_pc_scut.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_pc_scut.png b/app/src/main/res/mipmap-xxxhdpi/ic_pc_scut.png
new file mode 100644
index 00000000..fe196ebf
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_pc_scut.png differ