mirror of
https://github.com/moonlight-stream/moonlight-android.git
synced 2025-07-19 02:53:05 +00:00
713 lines
28 KiB
Java
713 lines
28 KiB
Java
package com.limelight;
|
|
|
|
import java.io.FileNotFoundException;
|
|
import java.io.IOException;
|
|
import java.net.UnknownHostException;
|
|
|
|
import com.limelight.binding.PlatformBinding;
|
|
import com.limelight.binding.crypto.AndroidCryptoProvider;
|
|
import com.limelight.computers.ComputerManagerListener;
|
|
import com.limelight.computers.ComputerManagerService;
|
|
import com.limelight.grid.PcGridAdapter;
|
|
import com.limelight.nvstream.http.ComputerDetails;
|
|
import com.limelight.nvstream.http.NvApp;
|
|
import com.limelight.nvstream.http.NvHTTP;
|
|
import com.limelight.nvstream.http.PairingManager;
|
|
import com.limelight.nvstream.http.PairingManager.PairState;
|
|
import com.limelight.nvstream.wol.WakeOnLanSender;
|
|
import com.limelight.preferences.AddComputerManually;
|
|
import com.limelight.preferences.GlPreferences;
|
|
import com.limelight.preferences.PreferenceConfiguration;
|
|
import com.limelight.preferences.StreamSettings;
|
|
import com.limelight.ui.AdapterFragment;
|
|
import com.limelight.ui.AdapterFragmentCallbacks;
|
|
import com.limelight.utils.Dialog;
|
|
import com.limelight.utils.HelpLauncher;
|
|
import com.limelight.utils.ServerHelper;
|
|
import com.limelight.utils.ShortcutHelper;
|
|
import com.limelight.utils.UiHelper;
|
|
|
|
import android.app.Activity;
|
|
import android.app.ActivityManager;
|
|
import android.app.Service;
|
|
import android.content.ComponentName;
|
|
import android.content.Intent;
|
|
import android.content.ServiceConnection;
|
|
import android.content.res.Configuration;
|
|
import android.opengl.GLSurfaceView;
|
|
import android.os.Build;
|
|
import android.os.Bundle;
|
|
import android.os.IBinder;
|
|
import android.preference.PreferenceManager;
|
|
import android.view.ContextMenu;
|
|
import android.view.Menu;
|
|
import android.view.MenuItem;
|
|
import android.view.View;
|
|
import android.view.ContextMenu.ContextMenuInfo;
|
|
import android.view.View.OnClickListener;
|
|
import android.widget.AbsListView;
|
|
import android.widget.AdapterView;
|
|
import android.widget.AdapterView.OnItemClickListener;
|
|
import android.widget.ImageButton;
|
|
import android.widget.RelativeLayout;
|
|
import android.widget.Toast;
|
|
import android.widget.AdapterView.AdapterContextMenuInfo;
|
|
|
|
import javax.microedition.khronos.egl.EGLConfig;
|
|
import javax.microedition.khronos.opengles.GL10;
|
|
|
|
public class PcView extends Activity implements AdapterFragmentCallbacks {
|
|
private RelativeLayout noPcFoundLayout;
|
|
private PcGridAdapter pcGridAdapter;
|
|
private ShortcutHelper shortcutHelper;
|
|
private ComputerManagerService.ComputerManagerBinder managerBinder;
|
|
private boolean freezeUpdates, runningPolling, inForeground, completeOnCreateCalled;
|
|
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;
|
|
|
|
// Start updates
|
|
startComputerUpdates();
|
|
|
|
// Force a keypair to be generated early to avoid discovery delays
|
|
new AndroidCryptoProvider(PcView.this).getClientCertificate();
|
|
}
|
|
}.start();
|
|
}
|
|
|
|
public void onServiceDisconnected(ComponentName className) {
|
|
managerBinder = null;
|
|
}
|
|
};
|
|
|
|
@Override
|
|
public void onConfigurationChanged(Configuration newConfig) {
|
|
super.onConfigurationChanged(newConfig);
|
|
|
|
// Only reinitialize views if completeOnCreate() was called
|
|
// before this callback. If it was not, completeOnCreate() will
|
|
// handle initializing views with the config change accounted for.
|
|
// This is not prone to races because both callbacks are invoked
|
|
// in the main thread.
|
|
if (completeOnCreateCalled) {
|
|
// Reinitialize views just in case orientation changed
|
|
initializeViews();
|
|
}
|
|
}
|
|
|
|
private final static int APP_LIST_ID = 1;
|
|
private final static int PAIR_ID = 2;
|
|
private final static int UNPAIR_ID = 3;
|
|
private final static int WOL_ID = 4;
|
|
private final static int DELETE_ID = 5;
|
|
private final static int RESUME_ID = 6;
|
|
private final static int QUIT_ID = 7;
|
|
|
|
private void initializeViews() {
|
|
setContentView(R.layout.activity_pc_view);
|
|
|
|
UiHelper.notifyNewRootView(this);
|
|
|
|
// Set default preferences if we've never been run
|
|
PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
|
|
|
|
// Setup the list view
|
|
ImageButton settingsButton = findViewById(R.id.settingsButton);
|
|
ImageButton addComputerButton = findViewById(R.id.manuallyAddPc);
|
|
ImageButton helpButton = findViewById(R.id.helpButton);
|
|
|
|
settingsButton.setOnClickListener(new OnClickListener() {
|
|
@Override
|
|
public void onClick(View v) {
|
|
startActivity(new Intent(PcView.this, StreamSettings.class));
|
|
}
|
|
});
|
|
addComputerButton.setOnClickListener(new OnClickListener() {
|
|
@Override
|
|
public void onClick(View v) {
|
|
Intent i = new Intent(PcView.this, AddComputerManually.class);
|
|
startActivity(i);
|
|
}
|
|
});
|
|
helpButton.setOnClickListener(new OnClickListener() {
|
|
@Override
|
|
public void onClick(View v) {
|
|
HelpLauncher.launchSetupGuide(PcView.this);
|
|
}
|
|
});
|
|
|
|
getFragmentManager().beginTransaction()
|
|
.replace(R.id.pcFragmentContainer, new AdapterFragment())
|
|
.commitAllowingStateLoss();
|
|
|
|
noPcFoundLayout = findViewById(R.id.no_pc_found_layout);
|
|
if (pcGridAdapter.getCount() == 0) {
|
|
noPcFoundLayout.setVisibility(View.VISIBLE);
|
|
}
|
|
else {
|
|
noPcFoundLayout.setVisibility(View.INVISIBLE);
|
|
}
|
|
pcGridAdapter.notifyDataSetChanged();
|
|
}
|
|
|
|
@Override
|
|
protected void onCreate(Bundle savedInstanceState) {
|
|
super.onCreate(savedInstanceState);
|
|
|
|
// Assume we're in the foreground when created to avoid a race
|
|
// between binding to CMS and onResume()
|
|
inForeground = true;
|
|
|
|
// Create a GLSurfaceView to fetch GLRenderer unless we have
|
|
// a cached result already.
|
|
final GlPreferences glPrefs = GlPreferences.readPreferences(this);
|
|
if (!glPrefs.savedFingerprint.equals(Build.FINGERPRINT) || glPrefs.glRenderer.isEmpty()) {
|
|
GLSurfaceView surfaceView = new GLSurfaceView(this);
|
|
surfaceView.setRenderer(new GLSurfaceView.Renderer() {
|
|
@Override
|
|
public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) {
|
|
// Save the GLRenderer string so we don't need to do this next time
|
|
glPrefs.glRenderer = gl10.glGetString(GL10.GL_RENDERER);
|
|
glPrefs.savedFingerprint = Build.FINGERPRINT;
|
|
glPrefs.writePreferences();
|
|
|
|
LimeLog.info("Fetched GL Renderer: " + glPrefs.glRenderer);
|
|
|
|
runOnUiThread(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
completeOnCreate();
|
|
}
|
|
});
|
|
}
|
|
|
|
@Override
|
|
public void onSurfaceChanged(GL10 gl10, int i, int i1) {
|
|
}
|
|
|
|
@Override
|
|
public void onDrawFrame(GL10 gl10) {
|
|
}
|
|
});
|
|
setContentView(surfaceView);
|
|
}
|
|
else {
|
|
LimeLog.info("Cached GL Renderer: " + glPrefs.glRenderer);
|
|
completeOnCreate();
|
|
}
|
|
}
|
|
|
|
private void completeOnCreate() {
|
|
completeOnCreateCalled = true;
|
|
|
|
shortcutHelper = new ShortcutHelper(this);
|
|
|
|
UiHelper.setLocale(this);
|
|
|
|
// Bind to the computer manager service
|
|
bindService(new Intent(PcView.this, ComputerManagerService.class), serviceConnection,
|
|
Service.BIND_AUTO_CREATE);
|
|
|
|
pcGridAdapter = new PcGridAdapter(this,
|
|
PreferenceConfiguration.readPreferences(this).listMode,
|
|
PreferenceConfiguration.readPreferences(this).smallIconMode);
|
|
|
|
initializeViews();
|
|
}
|
|
|
|
private void startComputerUpdates() {
|
|
// Only allow polling to start if we're bound to CMS, polling is not already running,
|
|
// and our activity is in the foreground.
|
|
if (managerBinder != null && !runningPolling && inForeground) {
|
|
freezeUpdates = false;
|
|
managerBinder.startPolling(new ComputerManagerListener() {
|
|
@Override
|
|
public void notifyComputerUpdated(final ComputerDetails details) {
|
|
if (!freezeUpdates) {
|
|
PcView.this.runOnUiThread(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
updateComputer(details);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
});
|
|
runningPolling = true;
|
|
}
|
|
}
|
|
|
|
private void stopComputerUpdates(boolean wait) {
|
|
if (managerBinder != null) {
|
|
if (!runningPolling) {
|
|
return;
|
|
}
|
|
|
|
freezeUpdates = true;
|
|
|
|
managerBinder.stopPolling();
|
|
|
|
if (wait) {
|
|
managerBinder.waitForPollingStopped();
|
|
}
|
|
|
|
runningPolling = false;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onDestroy() {
|
|
super.onDestroy();
|
|
|
|
if (managerBinder != null) {
|
|
unbindService(serviceConnection);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void onResume() {
|
|
super.onResume();
|
|
|
|
// Display a decoder crash notification if we've returned after a crash
|
|
UiHelper.showDecoderCrashDialog(this);
|
|
|
|
inForeground = true;
|
|
startComputerUpdates();
|
|
}
|
|
|
|
@Override
|
|
protected void onPause() {
|
|
super.onPause();
|
|
|
|
inForeground = false;
|
|
stopComputerUpdates(false);
|
|
}
|
|
|
|
@Override
|
|
protected void onStop() {
|
|
super.onStop();
|
|
|
|
Dialog.closeDialogs();
|
|
}
|
|
|
|
@Override
|
|
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
|
|
stopComputerUpdates(false);
|
|
|
|
// Call superclass
|
|
super.onCreateContextMenu(menu, v, menuInfo);
|
|
|
|
AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
|
|
ComputerObject computer = (ComputerObject) pcGridAdapter.getItem(info.position);
|
|
|
|
// Inflate the context menu
|
|
if (computer.details.reachability == ComputerDetails.Reachability.OFFLINE ||
|
|
computer.details.reachability == ComputerDetails.Reachability.UNKNOWN) {
|
|
menu.add(Menu.NONE, WOL_ID, 1, getResources().getString(R.string.pcview_menu_send_wol));
|
|
menu.add(Menu.NONE, DELETE_ID, 2, getResources().getString(R.string.pcview_menu_delete_pc));
|
|
}
|
|
else if (computer.details.pairState != PairState.PAIRED) {
|
|
menu.add(Menu.NONE, PAIR_ID, 1, getResources().getString(R.string.pcview_menu_pair_pc));
|
|
menu.add(Menu.NONE, DELETE_ID, 2, getResources().getString(R.string.pcview_menu_delete_pc));
|
|
}
|
|
else {
|
|
if (computer.details.runningGameId != 0) {
|
|
menu.add(Menu.NONE, 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, APP_LIST_ID, 3, getResources().getString(R.string.pcview_menu_app_list));
|
|
|
|
// FIXME: We used to be able to unpair here but it's been broken since GFE 2.1.x, so I've replaced
|
|
// it with delete which actually work
|
|
menu.add(Menu.NONE, DELETE_ID, 4, getResources().getString(R.string.pcview_menu_delete_pc));
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onContextMenuClosed(Menu menu) {
|
|
// For some reason, this gets called again _after_ onPause() is called on this activity.
|
|
// startComputerUpdates() manages this and won't actual start polling until the activity
|
|
// returns to the foreground.
|
|
startComputerUpdates();
|
|
}
|
|
|
|
private void doPair(final ComputerDetails computer) {
|
|
if (computer.reachability == ComputerDetails.Reachability.OFFLINE) {
|
|
Toast.makeText(PcView.this, getResources().getString(R.string.pair_pc_offline), Toast.LENGTH_SHORT).show();
|
|
return;
|
|
}
|
|
if (computer.runningGameId != 0) {
|
|
Toast.makeText(PcView.this, getResources().getString(R.string.pair_pc_ingame), Toast.LENGTH_LONG).show();
|
|
return;
|
|
}
|
|
if (managerBinder == null) {
|
|
Toast.makeText(PcView.this, getResources().getString(R.string.error_manager_not_running), Toast.LENGTH_LONG).show();
|
|
return;
|
|
}
|
|
|
|
Toast.makeText(PcView.this, getResources().getString(R.string.pairing), Toast.LENGTH_SHORT).show();
|
|
new Thread(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
NvHTTP httpConn;
|
|
String message;
|
|
boolean success = false;
|
|
try {
|
|
// Stop updates and wait while pairing
|
|
stopComputerUpdates(true);
|
|
|
|
httpConn = new NvHTTP(ServerHelper.getCurrentAddressFromComputer(computer),
|
|
managerBinder.getUniqueId(),
|
|
PlatformBinding.getDeviceName(),
|
|
PlatformBinding.getCryptoProvider(PcView.this));
|
|
if (httpConn.getPairState() == PairingManager.PairState.PAIRED) {
|
|
// Don't display any toast, but open the app list
|
|
message = null;
|
|
success = true;
|
|
}
|
|
else {
|
|
final String pinStr = PairingManager.generatePinString();
|
|
|
|
// Spin the dialog off in a thread because it blocks
|
|
Dialog.displayDialog(PcView.this, getResources().getString(R.string.pair_pairing_title),
|
|
getResources().getString(R.string.pair_pairing_msg)+" "+pinStr, false);
|
|
|
|
PairingManager.PairState pairState = httpConn.pair(httpConn.getServerInfo(), pinStr);
|
|
if (pairState == PairingManager.PairState.PIN_WRONG) {
|
|
message = getResources().getString(R.string.pair_incorrect_pin);
|
|
}
|
|
else if (pairState == PairingManager.PairState.FAILED) {
|
|
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) {
|
|
// Just navigate to the app view without displaying a toast
|
|
message = null;
|
|
success = true;
|
|
|
|
// Invalidate reachability information after pairing to force
|
|
// a refresh before reading pair state again
|
|
managerBinder.invalidateStateForComputer(computer.uuid);
|
|
}
|
|
else {
|
|
// Should be no other values
|
|
message = null;
|
|
}
|
|
}
|
|
} catch (UnknownHostException e) {
|
|
message = getResources().getString(R.string.error_unknown_host);
|
|
} catch (FileNotFoundException e) {
|
|
message = getResources().getString(R.string.error_404);
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
message = e.getMessage();
|
|
}
|
|
|
|
Dialog.closeDialogs();
|
|
|
|
final String toastMessage = message;
|
|
final boolean toastSuccess = success;
|
|
runOnUiThread(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
if (toastMessage != null) {
|
|
Toast.makeText(PcView.this, toastMessage, Toast.LENGTH_LONG).show();
|
|
}
|
|
|
|
if (toastSuccess) {
|
|
// Open the app list after a successful pairing attempt
|
|
doAppList(computer);
|
|
}
|
|
else {
|
|
// Start polling again if we're still in the foreground
|
|
startComputerUpdates();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}).start();
|
|
}
|
|
|
|
private void doWakeOnLan(final ComputerDetails computer) {
|
|
if (computer.state == ComputerDetails.State.ONLINE) {
|
|
Toast.makeText(PcView.this, getResources().getString(R.string.wol_pc_online), Toast.LENGTH_SHORT).show();
|
|
return;
|
|
}
|
|
|
|
if (computer.macAddress == null) {
|
|
Toast.makeText(PcView.this, getResources().getString(R.string.wol_no_mac), Toast.LENGTH_SHORT).show();
|
|
return;
|
|
}
|
|
|
|
new Thread(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
String message;
|
|
try {
|
|
WakeOnLanSender.sendWolPacket(computer);
|
|
message = getResources().getString(R.string.wol_waking_msg);
|
|
} catch (IOException e) {
|
|
message = getResources().getString(R.string.wol_fail);
|
|
}
|
|
|
|
final String toastMessage = message;
|
|
runOnUiThread(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
Toast.makeText(PcView.this, toastMessage, Toast.LENGTH_LONG).show();
|
|
}
|
|
});
|
|
}
|
|
}).start();
|
|
}
|
|
|
|
private void doUnpair(final ComputerDetails computer) {
|
|
if (computer.reachability == ComputerDetails.Reachability.OFFLINE) {
|
|
Toast.makeText(PcView.this, getResources().getString(R.string.error_pc_offline), Toast.LENGTH_SHORT).show();
|
|
return;
|
|
}
|
|
if (managerBinder == null) {
|
|
Toast.makeText(PcView.this, getResources().getString(R.string.error_manager_not_running), Toast.LENGTH_LONG).show();
|
|
return;
|
|
}
|
|
|
|
Toast.makeText(PcView.this, getResources().getString(R.string.unpairing), Toast.LENGTH_SHORT).show();
|
|
new Thread(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
NvHTTP httpConn;
|
|
String message;
|
|
try {
|
|
httpConn = new NvHTTP(ServerHelper.getCurrentAddressFromComputer(computer),
|
|
managerBinder.getUniqueId(),
|
|
PlatformBinding.getDeviceName(),
|
|
PlatformBinding.getCryptoProvider(PcView.this));
|
|
if (httpConn.getPairState() == PairingManager.PairState.PAIRED) {
|
|
httpConn.unpair();
|
|
if (httpConn.getPairState() == PairingManager.PairState.NOT_PAIRED) {
|
|
message = getResources().getString(R.string.unpair_success);
|
|
}
|
|
else {
|
|
message = getResources().getString(R.string.unpair_fail);
|
|
}
|
|
}
|
|
else {
|
|
message = getResources().getString(R.string.unpair_error);
|
|
}
|
|
} catch (UnknownHostException e) {
|
|
message = getResources().getString(R.string.error_unknown_host);
|
|
} catch (FileNotFoundException e) {
|
|
message = getResources().getString(R.string.error_404);
|
|
} catch (Exception e) {
|
|
message = e.getMessage();
|
|
}
|
|
|
|
final String toastMessage = message;
|
|
runOnUiThread(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
Toast.makeText(PcView.this, toastMessage, Toast.LENGTH_LONG).show();
|
|
}
|
|
});
|
|
}
|
|
}).start();
|
|
}
|
|
|
|
private void doAppList(ComputerDetails computer) {
|
|
if (computer.reachability == ComputerDetails.Reachability.OFFLINE) {
|
|
Toast.makeText(PcView.this, getResources().getString(R.string.error_pc_offline), Toast.LENGTH_SHORT).show();
|
|
return;
|
|
}
|
|
if (managerBinder == null) {
|
|
Toast.makeText(PcView.this, getResources().getString(R.string.error_manager_not_running), Toast.LENGTH_LONG).show();
|
|
return;
|
|
}
|
|
|
|
Intent i = new Intent(this, AppView.class);
|
|
i.putExtra(AppView.NAME_EXTRA, computer.name);
|
|
i.putExtra(AppView.UUID_EXTRA, computer.uuid.toString());
|
|
startActivity(i);
|
|
}
|
|
|
|
@Override
|
|
public boolean onContextItemSelected(MenuItem item) {
|
|
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
|
|
final ComputerObject computer = (ComputerObject) pcGridAdapter.getItem(info.position);
|
|
switch (item.getItemId()) {
|
|
case PAIR_ID:
|
|
doPair(computer.details);
|
|
return true;
|
|
|
|
case UNPAIR_ID:
|
|
doUnpair(computer.details);
|
|
return true;
|
|
|
|
case WOL_ID:
|
|
doWakeOnLan(computer.details);
|
|
return true;
|
|
|
|
case DELETE_ID:
|
|
if (ActivityManager.isUserAMonkey()) {
|
|
LimeLog.info("Ignoring delete PC request from monkey");
|
|
return true;
|
|
}
|
|
if (managerBinder == null) {
|
|
Toast.makeText(PcView.this, getResources().getString(R.string.error_manager_not_running), Toast.LENGTH_LONG).show();
|
|
return true;
|
|
}
|
|
managerBinder.removeComputer(computer.details.name);
|
|
removeComputer(computer.details);
|
|
return true;
|
|
|
|
case APP_LIST_ID:
|
|
doAppList(computer.details);
|
|
return true;
|
|
|
|
case RESUME_ID:
|
|
if (managerBinder == null) {
|
|
Toast.makeText(PcView.this, getResources().getString(R.string.error_manager_not_running), Toast.LENGTH_LONG).show();
|
|
return true;
|
|
}
|
|
|
|
ServerHelper.doStart(this, new NvApp("app", computer.details.runningGameId, false), computer.details, managerBinder);
|
|
return true;
|
|
|
|
case QUIT_ID:
|
|
if (managerBinder == null) {
|
|
Toast.makeText(PcView.this, getResources().getString(R.string.error_manager_not_running), Toast.LENGTH_LONG).show();
|
|
return true;
|
|
}
|
|
|
|
// Display a confirmation dialog first
|
|
UiHelper.displayQuitConfirmationDialog(this, new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
ServerHelper.doQuit(PcView.this,
|
|
ServerHelper.getCurrentAddressFromComputer(computer.details),
|
|
new NvApp("app", 0, false), managerBinder, null);
|
|
}
|
|
}, null);
|
|
return true;
|
|
|
|
default:
|
|
return super.onContextItemSelected(item);
|
|
}
|
|
}
|
|
|
|
private void removeComputer(ComputerDetails details) {
|
|
for (int i = 0; i < pcGridAdapter.getCount(); i++) {
|
|
ComputerObject computer = (ComputerObject) pcGridAdapter.getItem(i);
|
|
|
|
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.notifyDataSetChanged();
|
|
|
|
if (pcGridAdapter.getCount() == 0) {
|
|
// Show the "Discovery in progress" view
|
|
noPcFoundLayout.setVisibility(View.VISIBLE);
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void updateComputer(ComputerDetails details) {
|
|
ComputerObject existingEntry = null;
|
|
|
|
for (int i = 0; i < pcGridAdapter.getCount(); i++) {
|
|
ComputerObject computer = (ComputerObject) pcGridAdapter.getItem(i);
|
|
|
|
// Check if this is the same computer
|
|
if (details.uuid.equals(computer.details.uuid)) {
|
|
existingEntry = computer;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Add a launcher shortcut for this PC
|
|
if (details.pairState == PairState.PAIRED) {
|
|
shortcutHelper.createAppViewShortcut(details.uuid.toString(), details, false);
|
|
}
|
|
|
|
if (existingEntry != null) {
|
|
// Replace the information in the existing entry
|
|
existingEntry.details = details;
|
|
}
|
|
else {
|
|
// Add a new entry
|
|
pcGridAdapter.addComputer(new ComputerObject(details));
|
|
|
|
// Remove the "Discovery in progress" view
|
|
noPcFoundLayout.setVisibility(View.INVISIBLE);
|
|
}
|
|
|
|
// Notify the view that the data has changed
|
|
pcGridAdapter.notifyDataSetChanged();
|
|
}
|
|
|
|
@Override
|
|
public int getAdapterFragmentLayoutId() {
|
|
return PreferenceConfiguration.readPreferences(this).listMode ?
|
|
R.layout.list_view : (PreferenceConfiguration.readPreferences(this).smallIconMode ?
|
|
R.layout.pc_grid_view_small : R.layout.pc_grid_view);
|
|
}
|
|
|
|
@Override
|
|
public void receiveAbsListView(AbsListView listView) {
|
|
listView.setAdapter(pcGridAdapter);
|
|
listView.setOnItemClickListener(new OnItemClickListener() {
|
|
@Override
|
|
public void onItemClick(AdapterView<?> arg0, View arg1, int pos,
|
|
long id) {
|
|
ComputerObject computer = (ComputerObject) pcGridAdapter.getItem(pos);
|
|
if (computer.details.reachability == ComputerDetails.Reachability.UNKNOWN ||
|
|
computer.details.reachability == ComputerDetails.Reachability.OFFLINE) {
|
|
// Open the context menu if a PC is offline or refreshing
|
|
openContextMenu(arg1);
|
|
} else if (computer.details.pairState != PairState.PAIRED) {
|
|
// Pair an unpaired machine by default
|
|
doPair(computer.details);
|
|
} else {
|
|
doAppList(computer.details);
|
|
}
|
|
}
|
|
});
|
|
registerForContextMenu(listView);
|
|
}
|
|
|
|
public class ComputerObject {
|
|
public ComputerDetails details;
|
|
|
|
public ComputerObject(ComputerDetails details) {
|
|
if (details == null) {
|
|
throw new IllegalArgumentException("details must not be null");
|
|
}
|
|
this.details = details;
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return details.name;
|
|
}
|
|
}
|
|
}
|