mirror of
https://github.com/moonlight-stream/moonlight-android.git
synced 2026-10-21 07:46:57 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
56b814e877 | ||
|
|
628ccd39d6 | ||
|
|
59db3f9b62 | ||
|
|
416f922b56 | ||
|
|
b52a86e6cc | ||
|
|
e523b5069e | ||
|
|
e8ae8d9807 | ||
|
|
64e56a861d | ||
|
|
c1bcd09c9b | ||
|
|
574258804f | ||
|
|
21ea3d8a2b | ||
|
|
6de4288a85 | ||
|
|
a107b5e652 | ||
|
|
b02db2c182 |
No files matched your search
+21
-15
@@ -72,13 +72,6 @@
|
|||||||
<sourceFolder url="file://$MODULE_DIR$/src/nonRoot/java" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/src/nonRoot/java" isTestSource="false" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/nonRoot/rs" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/src/nonRoot/rs" isTestSource="false" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/nonRoot/shaders" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/src/nonRoot/shaders" isTestSource="false" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTestNonRoot/res" type="java-test-resource" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTestNonRoot/resources" type="java-test-resource" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTestNonRoot/assets" type="java-test-resource" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTestNonRoot/aidl" isTestSource="true" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTestNonRoot/java" isTestSource="true" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTestNonRoot/rs" isTestSource="true" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTestNonRoot/shaders" isTestSource="true" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/testNonRoot/res" type="java-test-resource" />
|
<sourceFolder url="file://$MODULE_DIR$/src/testNonRoot/res" type="java-test-resource" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/testNonRoot/resources" type="java-test-resource" />
|
<sourceFolder url="file://$MODULE_DIR$/src/testNonRoot/resources" type="java-test-resource" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/testNonRoot/assets" type="java-test-resource" />
|
<sourceFolder url="file://$MODULE_DIR$/src/testNonRoot/assets" type="java-test-resource" />
|
||||||
@@ -86,6 +79,13 @@
|
|||||||
<sourceFolder url="file://$MODULE_DIR$/src/testNonRoot/java" isTestSource="true" />
|
<sourceFolder url="file://$MODULE_DIR$/src/testNonRoot/java" isTestSource="true" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/testNonRoot/rs" isTestSource="true" />
|
<sourceFolder url="file://$MODULE_DIR$/src/testNonRoot/rs" isTestSource="true" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/testNonRoot/shaders" isTestSource="true" />
|
<sourceFolder url="file://$MODULE_DIR$/src/testNonRoot/shaders" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/androidTestNonRoot/res" type="java-test-resource" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/androidTestNonRoot/resources" type="java-test-resource" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/androidTestNonRoot/assets" type="java-test-resource" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/androidTestNonRoot/aidl" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/androidTestNonRoot/java" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/androidTestNonRoot/rs" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/androidTestNonRoot/shaders" isTestSource="true" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
|
<sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
|
<sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" />
|
<sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" />
|
||||||
@@ -107,13 +107,6 @@
|
|||||||
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/main/shaders" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/src/main/shaders" isTestSource="false" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/test/res" type="java-test-resource" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/test/assets" type="java-test-resource" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/test/aidl" isTestSource="true" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/test/rs" isTestSource="true" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/test/shaders" isTestSource="true" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
|
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
|
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
|
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
|
||||||
@@ -121,19 +114,32 @@
|
|||||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
|
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
|
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/shaders" isTestSource="true" />
|
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/shaders" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/test/res" type="java-test-resource" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/test/assets" type="java-test-resource" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/test/aidl" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/test/rs" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/test/shaders" isTestSource="true" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-safeguard" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-safeguard" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jniLibs" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/ndkBuild" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/shaders" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/transforms" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
|
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
|
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="jdk" jdkName="Android API 24 Platform" jdkType="Android SDK" />
|
<orderEntry type="jdk" jdkName="Android API 25 Platform" jdkType="Android SDK" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
<orderEntry type="library" exported="" name="bcprov-jdk15on-1.52" level="project" />
|
<orderEntry type="library" exported="" name="bcprov-jdk15on-1.52" level="project" />
|
||||||
<orderEntry type="library" exported="" name="bcpkix-jdk15on-1.52" level="project" />
|
<orderEntry type="library" exported="" name="bcpkix-jdk15on-1.52" level="project" />
|
||||||
|
|||||||
+5
-5
@@ -4,15 +4,15 @@ 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.3"
|
||||||
versionCode = 106
|
versionCode = 108
|
||||||
}
|
}
|
||||||
|
|
||||||
productFlavors {
|
productFlavors {
|
||||||
|
|||||||
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() {
|
||||||
@@ -90,12 +95,15 @@ public class AppView extends Activity implements AdapterFragmentCallbacks {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load the app grid with cached data (if possible).
|
||||||
|
// This must be done _before_ startComputerUpdates()
|
||||||
|
// so the initial serverinfo response can update the running
|
||||||
|
// icon.
|
||||||
|
populateAppGridWithCache();
|
||||||
|
|
||||||
// Start updates
|
// Start updates
|
||||||
startComputerUpdates();
|
startComputerUpdates();
|
||||||
|
|
||||||
// Load the app grid with cached data (if possible)
|
|
||||||
populateAppGridWithCache();
|
|
||||||
|
|
||||||
runOnUiThread(new Runnable() {
|
runOnUiThread(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@@ -132,7 +140,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 +165,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)) {
|
||||||
|
|
||||||
@@ -175,6 +225,7 @@ public class AppView extends Activity implements AdapterFragmentCallbacks {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
updateUiWithAppList(NvHTTP.getAppListByReader(new StringReader(details.rawAppList)));
|
updateUiWithAppList(NvHTTP.getAppListByReader(new StringReader(details.rawAppList)));
|
||||||
|
updateUiWithServerinfo(details);
|
||||||
|
|
||||||
if (blockingLoadSpinner != null) {
|
if (blockingLoadSpinner != null) {
|
||||||
blockingLoadSpinner.dismiss();
|
blockingLoadSpinner.dismiss();
|
||||||
@@ -208,6 +259,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 +274,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);
|
||||||
@@ -282,27 +344,14 @@ public class AppView extends Activity implements AdapterFragmentCallbacks {
|
|||||||
stopComputerUpdates();
|
stopComputerUpdates();
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getRunningAppId() {
|
|
||||||
int runningAppId = -1;
|
|
||||||
for (int i = 0; i < appGridAdapter.getCount(); i++) {
|
|
||||||
AppObject app = (AppObject) appGridAdapter.getItem(i);
|
|
||||||
if (app.app.getIsRunning()) {
|
|
||||||
runningAppId = app.app.getAppId();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return runningAppId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
|
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
|
||||||
super.onCreateContextMenu(menu, v, menuInfo);
|
super.onCreateContextMenu(menu, v, menuInfo);
|
||||||
|
|
||||||
AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
|
AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
|
||||||
AppObject selectedApp = (AppObject) appGridAdapter.getItem(info.position);
|
AppObject selectedApp = (AppObject) appGridAdapter.getItem(info.position);
|
||||||
int runningAppId = getRunningAppId();
|
if (lastRunningAppId != 0) {
|
||||||
if (runningAppId != -1) {
|
if (lastRunningAppId == selectedApp.app.getAppId()) {
|
||||||
if (runningAppId == selectedApp.app.getAppId()) {
|
|
||||||
menu.add(Menu.NONE, START_OR_RESUME_ID, 1, getResources().getString(R.string.applist_menu_resume));
|
menu.add(Menu.NONE, START_OR_RESUME_ID, 1, getResources().getString(R.string.applist_menu_resume));
|
||||||
menu.add(Menu.NONE, QUIT_ID, 2, getResources().getString(R.string.applist_menu_quit));
|
menu.add(Menu.NONE, QUIT_ID, 2, getResources().getString(R.string.applist_menu_quit));
|
||||||
}
|
}
|
||||||
@@ -378,19 +427,19 @@ public class AppView extends Activity implements AdapterFragmentCallbacks {
|
|||||||
AppObject existingApp = (AppObject) appGridAdapter.getItem(i);
|
AppObject existingApp = (AppObject) appGridAdapter.getItem(i);
|
||||||
|
|
||||||
// There can only be one or zero apps running.
|
// There can only be one or zero apps running.
|
||||||
if (existingApp.app.getIsRunning() &&
|
if (existingApp.isRunning &&
|
||||||
existingApp.app.getAppId() == details.runningGameId) {
|
existingApp.app.getAppId() == details.runningGameId) {
|
||||||
// This app was running and still is, so we're done now
|
// This app was running and still is, so we're done now
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (existingApp.app.getAppId() == details.runningGameId) {
|
else if (existingApp.app.getAppId() == details.runningGameId) {
|
||||||
// This app wasn't running but now is
|
// This app wasn't running but now is
|
||||||
existingApp.app.setIsRunning(true);
|
existingApp.isRunning = true;
|
||||||
updated = true;
|
updated = true;
|
||||||
}
|
}
|
||||||
else if (existingApp.app.getIsRunning()) {
|
else if (existingApp.isRunning) {
|
||||||
// This app was running but now isn't
|
// This app was running but now isn't
|
||||||
existingApp.app.setIsRunning(false);
|
existingApp.isRunning = false;
|
||||||
updated = true;
|
updated = true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -420,10 +469,6 @@ public class AppView extends Activity implements AdapterFragmentCallbacks {
|
|||||||
AppObject existingApp = (AppObject) appGridAdapter.getItem(i);
|
AppObject existingApp = (AppObject) appGridAdapter.getItem(i);
|
||||||
if (existingApp.app.getAppId() == app.getAppId()) {
|
if (existingApp.app.getAppId() == app.getAppId()) {
|
||||||
// Found the app; update its properties
|
// Found the app; update its properties
|
||||||
if (existingApp.app.getIsRunning() != app.getIsRunning()) {
|
|
||||||
existingApp.app.setIsRunning(app.getIsRunning());
|
|
||||||
updated = true;
|
|
||||||
}
|
|
||||||
if (!existingApp.app.getAppName().equals(app.getAppName())) {
|
if (!existingApp.app.getAppName().equals(app.getAppName())) {
|
||||||
existingApp.app.setAppName(app.getAppName());
|
existingApp.app.setAppName(app.getAppName());
|
||||||
updated = true;
|
updated = true;
|
||||||
@@ -493,7 +538,7 @@ public class AppView extends Activity implements AdapterFragmentCallbacks {
|
|||||||
AppObject app = (AppObject) appGridAdapter.getItem(pos);
|
AppObject app = (AppObject) appGridAdapter.getItem(pos);
|
||||||
|
|
||||||
// Only open the context menu if something is running, otherwise start it
|
// Only open the context menu if something is running, otherwise start it
|
||||||
if (getRunningAppId() != -1) {
|
if (lastRunningAppId != 0) {
|
||||||
openContextMenu(arg1);
|
openContextMenu(arg1);
|
||||||
} else {
|
} else {
|
||||||
ServerHelper.doStart(AppView.this, app.app, computer, managerBinder);
|
ServerHelper.doStart(AppView.this, app.app, computer, managerBinder);
|
||||||
@@ -506,6 +551,7 @@ public class AppView extends Activity implements AdapterFragmentCallbacks {
|
|||||||
|
|
||||||
public class AppObject {
|
public class AppObject {
|
||||||
public final NvApp app;
|
public final NvApp app;
|
||||||
|
public boolean isRunning;
|
||||||
|
|
||||||
public AppObject(NvApp app) {
|
public AppObject(NvApp app) {
|
||||||
if (app == null) {
|
if (app == null) {
|
||||||
|
|||||||
@@ -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;
|
||||||
@@ -366,6 +373,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
|
||||||
|
computer.pairState = PairState.PAIRED;
|
||||||
doAppList(computer);
|
doAppList(computer);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -486,6 +494,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 +568,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();
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import android.hardware.input.InputManager;
|
|||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
import android.view.InputDevice;
|
import android.view.InputDevice;
|
||||||
|
import android.view.InputEvent;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
@@ -415,21 +416,27 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
|||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
private InputDeviceContext getContextForDevice(InputDevice dev) {
|
private InputDeviceContext getContextForEvent(InputEvent event) {
|
||||||
// Unknown devices use the default context
|
// Unknown devices use the default context
|
||||||
if (dev == null) {
|
if (event.getDeviceId() == 0) {
|
||||||
return defaultContext;
|
return defaultContext;
|
||||||
}
|
}
|
||||||
|
else if (event.getDevice() == null) {
|
||||||
|
// During device removal, sometimes we can get events after the
|
||||||
|
// input device has been destroyed. In this case we'll see a
|
||||||
|
// != 0 device ID but no device attached.
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
// Return the existing context if it exists
|
// Return the existing context if it exists
|
||||||
InputDeviceContext context = inputDeviceContexts.get(dev.getId());
|
InputDeviceContext context = inputDeviceContexts.get(event.getDeviceId());
|
||||||
if (context != null) {
|
if (context != null) {
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise create a new context
|
// Otherwise create a new context
|
||||||
context = createInputDeviceContextForDevice(dev);
|
context = createInputDeviceContextForDevice(event.getDevice());
|
||||||
inputDeviceContexts.put(dev.getId(), context);
|
inputDeviceContexts.put(event.getDeviceId(), context);
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
@@ -627,6 +634,11 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
|||||||
default:
|
default:
|
||||||
// Other buttons are mapped correctly
|
// Other buttons are mapped correctly
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The Xbox button is sent as MENU
|
||||||
|
if (event.getKeyCode() == KeyEvent.KEYCODE_MENU) {
|
||||||
|
return KeyEvent.KEYCODE_BUTTON_MODE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (context.hatXAxis != -1 && context.hatYAxis != -1) {
|
if (context.hatXAxis != -1 && context.hatYAxis != -1) {
|
||||||
@@ -642,7 +654,12 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
|||||||
}
|
}
|
||||||
else if (context.hatXAxis == -1 &&
|
else if (context.hatXAxis == -1 &&
|
||||||
context.hatYAxis == -1 &&
|
context.hatYAxis == -1 &&
|
||||||
context.isXboxController &&
|
/* FIXME: There's no good way to know for sure if xpad is bound
|
||||||
|
to this device, so we won't use the name to validate if these
|
||||||
|
scancodes should be mapped to DPAD
|
||||||
|
|
||||||
|
context.isXboxController &&
|
||||||
|
*/
|
||||||
event.getKeyCode() == KeyEvent.KEYCODE_UNKNOWN) {
|
event.getKeyCode() == KeyEvent.KEYCODE_UNKNOWN) {
|
||||||
// If there's not a proper Xbox controller mapping, we'll translate the raw d-pad
|
// If there's not a proper Xbox controller mapping, we'll translate the raw d-pad
|
||||||
// scan codes into proper key codes
|
// scan codes into proper key codes
|
||||||
@@ -732,9 +749,23 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (context.leftTriggerAxis != -1 && context.rightTriggerAxis != -1) {
|
if (context.leftTriggerAxis != -1 && context.rightTriggerAxis != -1) {
|
||||||
|
// Android sends an initial 0 value for trigger axes even if the trigger
|
||||||
|
// should be negative when idle. After the first touch, the axes will go back
|
||||||
|
// to normal behavior, so ignore triggersIdleNegative for each trigger until
|
||||||
|
// first touch.
|
||||||
|
if (lt != 0) {
|
||||||
|
context.leftTriggerUsed = true;
|
||||||
|
}
|
||||||
|
if (rt != 0) {
|
||||||
|
context.rightTriggerUsed = true;
|
||||||
|
}
|
||||||
if (context.triggersIdleNegative) {
|
if (context.triggersIdleNegative) {
|
||||||
lt = (lt + 1) / 2;
|
if (context.leftTriggerUsed) {
|
||||||
rt = (rt + 1) / 2;
|
lt = (lt + 1) / 2;
|
||||||
|
}
|
||||||
|
if (context.rightTriggerUsed) {
|
||||||
|
rt = (rt + 1) / 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lt <= context.triggerDeadzone) {
|
if (lt <= context.triggerDeadzone) {
|
||||||
@@ -770,7 +801,11 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean handleMotionEvent(MotionEvent event) {
|
public boolean handleMotionEvent(MotionEvent event) {
|
||||||
InputDeviceContext context = getContextForDevice(event.getDevice());
|
InputDeviceContext context = getContextForEvent(event);
|
||||||
|
if (context == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
float lsX = 0, lsY = 0, rsX = 0, rsY = 0, rt = 0, lt = 0, hatX = 0, hatY = 0;
|
float lsX = 0, lsY = 0, rsX = 0, rsY = 0, rt = 0, lt = 0, hatX = 0, hatY = 0;
|
||||||
|
|
||||||
// We purposefully ignore the historical values in the motion event as it makes
|
// We purposefully ignore the historical values in the motion event as it makes
|
||||||
@@ -842,7 +877,10 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean handleButtonUp(KeyEvent event) {
|
public boolean handleButtonUp(KeyEvent event) {
|
||||||
InputDeviceContext context = getContextForDevice(event.getDevice());
|
InputDeviceContext context = getContextForEvent(event);
|
||||||
|
if (context == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
int keyCode = handleRemapping(context, event);
|
int keyCode = handleRemapping(context, event);
|
||||||
if (keyCode == 0) {
|
if (keyCode == 0) {
|
||||||
@@ -867,7 +905,11 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
|||||||
break;
|
break;
|
||||||
case KeyEvent.KEYCODE_BUTTON_START:
|
case KeyEvent.KEYCODE_BUTTON_START:
|
||||||
case KeyEvent.KEYCODE_MENU:
|
case KeyEvent.KEYCODE_MENU:
|
||||||
if (SystemClock.uptimeMillis() - context.startDownTime > ControllerHandler.START_DOWN_TIME_MOUSE_MODE_MS) {
|
// Sometimes we'll get a spurious key up event on controller disconnect.
|
||||||
|
// Make sure it's real by checking that the key is actually down before taking
|
||||||
|
// any action.
|
||||||
|
if ((context.inputMap & ControllerPacket.PLAY_FLAG) != 0 &&
|
||||||
|
SystemClock.uptimeMillis() - context.startDownTime > ControllerHandler.START_DOWN_TIME_MOUSE_MODE_MS) {
|
||||||
toggleMouseEmulation(context);
|
toggleMouseEmulation(context);
|
||||||
}
|
}
|
||||||
context.inputMap &= ~ControllerPacket.PLAY_FLAG;
|
context.inputMap &= ~ControllerPacket.PLAY_FLAG;
|
||||||
@@ -965,7 +1007,10 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean handleButtonDown(KeyEvent event) {
|
public boolean handleButtonDown(KeyEvent event) {
|
||||||
InputDeviceContext context = getContextForDevice(event.getDevice());
|
InputDeviceContext context = getContextForEvent(event);
|
||||||
|
if (context == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
int keyCode = handleRemapping(context, event);
|
int keyCode = handleRemapping(context, event);
|
||||||
if (keyCode == 0) {
|
if (keyCode == 0) {
|
||||||
@@ -1153,6 +1198,7 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
|||||||
public int leftTriggerAxis = -1;
|
public int leftTriggerAxis = -1;
|
||||||
public int rightTriggerAxis = -1;
|
public int rightTriggerAxis = -1;
|
||||||
public boolean triggersIdleNegative;
|
public boolean triggersIdleNegative;
|
||||||
|
public boolean leftTriggerUsed, rightTriggerUsed;
|
||||||
|
|
||||||
public int hatXAxis = -1;
|
public int hatXAxis = -1;
|
||||||
public int hatYAxis = -1;
|
public int hatYAxis = -1;
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ public class AppGridAdapter extends GenericGridAdapter<AppView.AppObject> {
|
|||||||
Collections.sort(itemList, new Comparator<AppView.AppObject>() {
|
Collections.sort(itemList, new Comparator<AppView.AppObject>() {
|
||||||
@Override
|
@Override
|
||||||
public int compare(AppView.AppObject lhs, AppView.AppObject rhs) {
|
public int compare(AppView.AppObject lhs, AppView.AppObject rhs) {
|
||||||
return lhs.app.getAppName().compareTo(rhs.app.getAppName());
|
return lhs.app.getAppName().toLowerCase().compareTo(rhs.app.getAppName().toLowerCase());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -101,7 +101,7 @@ public class AppGridAdapter extends GenericGridAdapter<AppView.AppObject> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean populateOverlayView(ImageView overlayView, AppView.AppObject obj) {
|
public boolean populateOverlayView(ImageView overlayView, AppView.AppObject obj) {
|
||||||
if (obj.app.getIsRunning()) {
|
if (obj.isRunning) {
|
||||||
// Show the play button overlay
|
// Show the play button overlay
|
||||||
overlayView.setImageResource(R.drawable.ic_play);
|
overlayView.setImageResource(R.drawable.ic_play);
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ public class PcGridAdapter extends GenericGridAdapter<PcView.ComputerObject> {
|
|||||||
Collections.sort(itemList, new Comparator<PcView.ComputerObject>() {
|
Collections.sort(itemList, new Comparator<PcView.ComputerObject>() {
|
||||||
@Override
|
@Override
|
||||||
public int compare(PcView.ComputerObject lhs, PcView.ComputerObject rhs) {
|
public int compare(PcView.ComputerObject lhs, PcView.ComputerObject rhs) {
|
||||||
return lhs.details.name.compareTo(rhs.details.name);
|
return lhs.details.name.toLowerCase().compareTo(rhs.details.name.toLowerCase());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
//TODO: Testing and proper icon - 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,6 +15,8 @@
|
|||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <netinet/tcp.h>
|
#include <netinet/tcp.h>
|
||||||
|
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
#include <android/log.h>
|
#include <android/log.h>
|
||||||
|
|
||||||
#define EVDEV_MAX_EVENT_SIZE 24
|
#define EVDEV_MAX_EVENT_SIZE 24
|
||||||
|
|||||||
@@ -19,7 +19,8 @@ Java_com_limelight_nvstream_av_audio_OpusDecoder_init(JNIEnv *env, jobject this,
|
|||||||
ChannelCount = channelCount;
|
ChannelCount = channelCount;
|
||||||
|
|
||||||
jni_mapping_data = (*env)->GetByteArrayElements(env, mapping, 0);
|
jni_mapping_data = (*env)->GetByteArrayElements(env, mapping, 0);
|
||||||
ret = nv_opus_init(sampleRate, channelCount, streams, coupledStreams, jni_mapping_data);
|
ret = nv_opus_init(sampleRate, channelCount, streams, coupledStreams,
|
||||||
|
(const unsigned char*)jni_mapping_data);
|
||||||
(*env)->ReleaseByteArrayElements(env, mapping, jni_mapping_data, JNI_ABORT);
|
(*env)->ReleaseByteArrayElements(env, mapping, jni_mapping_data, JNI_ABORT);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@@ -49,7 +50,8 @@ Java_com_limelight_nvstream_av_audio_OpusDecoder_decode(
|
|||||||
if (indata != NULL) {
|
if (indata != NULL) {
|
||||||
jni_input_data = (*env)->GetByteArrayElements(env, indata, 0);
|
jni_input_data = (*env)->GetByteArrayElements(env, indata, 0);
|
||||||
|
|
||||||
ret = nv_opus_decode(&jni_input_data[inoff], inlen, (jshort*)jni_pcm_data, SamplesPerChannel);
|
ret = nv_opus_decode((unsigned char*)&jni_input_data[inoff], inlen,
|
||||||
|
(jshort*)jni_pcm_data, SamplesPerChannel);
|
||||||
|
|
||||||
// The input data isn't changed so it can be safely aborted
|
// The input data isn't changed so it can be safely aborted
|
||||||
(*env)->ReleaseByteArrayElements(env, indata, jni_input_data, JNI_ABORT);
|
(*env)->ReleaseByteArrayElements(env, indata, jni_input_data, JNI_ABORT);
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
+1
-1
@@ -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'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user