Merge branch 'master' of github.com:limelight-stream/limelight-android

This commit is contained in:
Cameron Gutman 2014-07-20 14:19:53 -07:00
commit f0f801ba3f
13 changed files with 213 additions and 56 deletions

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.limelight" package="com.limelight"
android:versionCode="24" android:versionCode="26"
android:versionName="2.5.0.4" > android:versionName="2.5.1" >
<uses-sdk <uses-sdk
android:minSdkVersion="16" android:minSdkVersion="16"

View File

@ -52,12 +52,13 @@ or to a theme attribute in the form "<code>?[<i>package</i>:][<i>type</i>:]<i>na
public static final int discoveryText=0x7f08000b; public static final int discoveryText=0x7f08000b;
public static final int hardwareDec=0x7f080005; public static final int hardwareDec=0x7f080005;
public static final int hostTextView=0x7f080000; public static final int hostTextView=0x7f080000;
public static final int manuallyAddPc=0x7f080013; public static final int manuallyAddPc=0x7f080014;
public static final int pcListView=0x7f080008; public static final int pcListView=0x7f080008;
public static final int rowTextView=0x7f080014; public static final int rowTextView=0x7f080015;
public static final int settingsButton=0x7f08000c; public static final int settingsButton=0x7f08000c;
public static final int softwareDec=0x7f080003; public static final int softwareDec=0x7f080003;
public static final int streamConfigGroup=0x7f08000d; public static final int streamConfigGroup=0x7f08000d;
public static final int stretchToFill=0x7f080013;
public static final int surfaceView=0x7f08000a; public static final int surfaceView=0x7f08000a;
} }
public static final class layout { public static final class layout {

Binary file not shown.

View File

@ -2,12 +2,13 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="#0099cc" android:background="#000"
tools:context=".Game" > tools:context=".Game" >
<SurfaceView <SurfaceView
android:id="@+id/surfaceView" android:id="@+id/surfaceView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" /> android:layout_height="match_parent"
android:layout_gravity="center" />
</FrameLayout> </FrameLayout>

View File

@ -54,7 +54,7 @@
android:id="@+id/advancedSettingsButton" android:id="@+id/advancedSettingsButton"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@+id/streamConfigGroup" android:layout_below="@+id/stretchToFill"
android:layout_centerHorizontal="true" android:layout_centerHorizontal="true"
android:layout_marginTop="15dp" android:layout_marginTop="15dp"
android:text="Advanced Settings" /> android:text="Advanced Settings" />
@ -67,6 +67,14 @@
android:layout_centerHorizontal="true" android:layout_centerHorizontal="true"
android:text="Add PC Manually" /> android:text="Add PC Manually" />
<CheckBox
android:id="@+id/stretchToFill"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/streamConfigGroup"
android:layout_marginTop="15dp"
android:text="Stretch video to fill screen" />
</RelativeLayout> </RelativeLayout>
</ScrollView> </ScrollView>

View File

@ -94,8 +94,8 @@ public class AppView extends Activity {
} }
@Override @Override
protected void onStop() { protected void onDestroy() {
super.onStop(); super.onDestroy();
Dialog.closeDialogs(); Dialog.closeDialogs();
SpinnerDialog.closeDialogs(); SpinnerDialog.closeDialogs();

View File

@ -32,6 +32,7 @@ import android.view.SurfaceView;
import android.view.View; import android.view.View;
import android.view.View.OnGenericMotionListener; import android.view.View.OnGenericMotionListener;
import android.view.View.OnTouchListener; import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.view.Window; import android.view.Window;
import android.view.WindowManager; import android.view.WindowManager;
import android.widget.Toast; import android.widget.Toast;
@ -58,6 +59,8 @@ public class Game extends Activity implements SurfaceHolder.Callback, OnGenericM
private boolean connecting = false; private boolean connecting = false;
private boolean connected = false; private boolean connected = false;
private boolean stretchToFit;
private ConfigurableDecoderRenderer decoderRenderer; private ConfigurableDecoderRenderer decoderRenderer;
private WifiManager.WifiLock wifiLock; private WifiManager.WifiLock wifiLock;
@ -76,6 +79,7 @@ public class Game extends Activity implements SurfaceHolder.Callback, OnGenericM
public static final String REFRESH_RATE_PREF_STRING = "FPS"; public static final String REFRESH_RATE_PREF_STRING = "FPS";
public static final String DECODER_PREF_STRING = "Decoder"; public static final String DECODER_PREF_STRING = "Decoder";
public static final String BITRATE_PREF_STRING = "Bitrate"; public static final String BITRATE_PREF_STRING = "Bitrate";
public static final String STRETCH_PREF_STRING = "Stretch";
public static final int BITRATE_DEFAULT_720_30 = 5; public static final int BITRATE_DEFAULT_720_30 = 5;
public static final int BITRATE_DEFAULT_720_60 = 10; public static final int BITRATE_DEFAULT_720_60 = 10;
@ -87,6 +91,7 @@ public class Game extends Activity implements SurfaceHolder.Callback, OnGenericM
public static final int DEFAULT_REFRESH_RATE = 60; public static final int DEFAULT_REFRESH_RATE = 60;
public static final int DEFAULT_DECODER = 0; public static final int DEFAULT_DECODER = 0;
public static final int DEFAULT_BITRATE = BITRATE_DEFAULT_720_60; public static final int DEFAULT_BITRATE = BITRATE_DEFAULT_720_60;
public static final boolean DEFAULT_STRETCH = false;
public static final int FORCE_HARDWARE_DECODER = -1; public static final int FORCE_HARDWARE_DECODER = -1;
public static final int AUTOSELECT_DECODER = 0; public static final int AUTOSELECT_DECODER = 0;
@ -121,13 +126,6 @@ public class Game extends Activity implements SurfaceHolder.Callback, OnGenericM
// Inflate the content // Inflate the content
setContentView(R.layout.activity_game); setContentView(R.layout.activity_game);
// Listen for events on the game surface
SurfaceView sv = (SurfaceView) findViewById(R.id.surfaceView);
sv.setOnGenericMotionListener(this);
sv.setOnTouchListener(this);
SurfaceHolder sh = sv.getHolder();
// Start the spinner // Start the spinner
spinner = SpinnerDialog.displayDialog(this, "Establishing Connection", "Starting connection", true); spinner = SpinnerDialog.displayDialog(this, "Establishing Connection", "Starting connection", true);
@ -143,16 +141,32 @@ public class Game extends Activity implements SurfaceHolder.Callback, OnGenericM
drFlags |= VideoDecoderRenderer.FLAG_FORCE_HARDWARE_DECODING; drFlags |= VideoDecoderRenderer.FLAG_FORCE_HARDWARE_DECODING;
break; break;
} }
stretchToFit = prefs.getBoolean(STRETCH_PREF_STRING, DEFAULT_STRETCH);
if (stretchToFit) {
drFlags |= VideoDecoderRenderer.FLAG_FILL_SCREEN;
}
int refreshRate, bitrate; int refreshRate, bitrate;
width = prefs.getInt(WIDTH_PREF_STRING, DEFAULT_WIDTH); width = prefs.getInt(WIDTH_PREF_STRING, DEFAULT_WIDTH);
height = prefs.getInt(HEIGHT_PREF_STRING, DEFAULT_HEIGHT); height = prefs.getInt(HEIGHT_PREF_STRING, DEFAULT_HEIGHT);
refreshRate = prefs.getInt(REFRESH_RATE_PREF_STRING, DEFAULT_REFRESH_RATE); refreshRate = prefs.getInt(REFRESH_RATE_PREF_STRING, DEFAULT_REFRESH_RATE);
bitrate = prefs.getInt(BITRATE_PREF_STRING, DEFAULT_BITRATE); bitrate = prefs.getInt(BITRATE_PREF_STRING, DEFAULT_BITRATE);
sh.setFixedSize(width, height);
Display display = getWindowManager().getDefaultDisplay(); Display display = getWindowManager().getDefaultDisplay();
display.getSize(screenSize); display.getSize(screenSize);
// Listen for events on the game surface
SurfaceView sv = (SurfaceView) findViewById(R.id.surfaceView);
sv.setOnGenericMotionListener(this);
sv.setOnTouchListener(this);
SurfaceHolder sh = sv.getHolder();
if (stretchToFit) {
// Set the surface to the size of the video
sh.setFixedSize(width, height);
}
// Warn the user if they're on a metered connection // Warn the user if they're on a metered connection
checkDataConnection(); checkDataConnection();
@ -181,6 +195,21 @@ public class Game extends Activity implements SurfaceHolder.Callback, OnGenericM
sh.addCallback(this); sh.addCallback(this);
} }
private void resizeSurfaceWithAspectRatio(SurfaceView sv, double vidWidth, double vidHeight)
{
// Get the visible width of the activity
double visibleWidth = getWindow().getDecorView().getWidth();
ViewGroup.LayoutParams lp = sv.getLayoutParams();
// Calculate the new size of the SurfaceView
lp.width = (int) visibleWidth;
lp.height = (int) ((vidHeight / vidWidth) * visibleWidth);
// Apply the size change
sv.setLayoutParams(lp);
}
private void checkDataConnection() private void checkDataConnection()
{ {
ConnectivityManager mgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); ConnectivityManager mgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
@ -233,7 +262,7 @@ public class Game extends Activity implements SurfaceHolder.Callback, OnGenericM
int averageDecoderLat = decoderRenderer.getAverageDecoderLatency(); int averageDecoderLat = decoderRenderer.getAverageDecoderLatency();
String message = null; String message = null;
if (averageEndToEndLat > 0) { if (averageEndToEndLat > 0) {
message = "Average total frame latency: "+averageEndToEndLat+" ms"; message = "Average client-side frame latency: "+averageEndToEndLat+" ms";
if (averageDecoderLat > 0) { if (averageDecoderLat > 0) {
message += " (hardware decoder latency: "+averageDecoderLat+" ms)"; message += " (hardware decoder latency: "+averageDecoderLat+" ms)";
} }
@ -270,10 +299,27 @@ public class Game extends Activity implements SurfaceHolder.Callback, OnGenericM
return modifier; return modifier;
} }
private static boolean isSourceFlagSet(int sourcesFlags, int flag) {
return (sourcesFlags & flag) == flag;
}
@Override @Override
public boolean onKeyDown(int keyCode, KeyEvent event) { public boolean onKeyDown(int keyCode, KeyEvent event) {
if (event.getDevice() != null && InputDevice dev = event.getDevice();
(event.getDevice().getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC)) { if (dev == null) {
return super.onKeyDown(keyCode, event);
}
int source = dev.getSources();
boolean handled = false;
if (isSourceFlagSet(source, InputDevice.SOURCE_DPAD) ||
isSourceFlagSet(source, InputDevice.SOURCE_GAMEPAD) ||
isSourceFlagSet(source, InputDevice.SOURCE_JOYSTICK))
{
handled = controllerHandler.handleButtonDown(keyCode, event);
}
if (!handled) {
short translated = keybTranslator.translate(event.getKeyCode()); short translated = keybTranslator.translate(event.getKeyCode());
if (translated == 0) { if (translated == 0) {
return super.onKeyDown(keyCode, event); return super.onKeyDown(keyCode, event);
@ -282,12 +328,7 @@ public class Game extends Activity implements SurfaceHolder.Callback, OnGenericM
keybTranslator.sendKeyDown(translated, keybTranslator.sendKeyDown(translated,
getModifierState(event)); getModifierState(event));
} }
else {
if (!controllerHandler.handleButtonDown(keyCode, event)) {
return super.onKeyDown(keyCode, event);
}
}
return true; return true;
} }
@ -302,22 +343,30 @@ public class Game extends Activity implements SurfaceHolder.Callback, OnGenericM
h.postDelayed(hideSystemUi, 2000); h.postDelayed(hideSystemUi, 2000);
} }
} }
if (event.getDevice() != null && InputDevice dev = event.getDevice();
(event.getDevice().getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC)) { if (dev == null) {
return super.onKeyUp(keyCode, event);
}
int source = dev.getSources();
boolean handled = false;
if (isSourceFlagSet(source, InputDevice.SOURCE_DPAD) ||
isSourceFlagSet(source, InputDevice.SOURCE_GAMEPAD) ||
isSourceFlagSet(source, InputDevice.SOURCE_JOYSTICK))
{
handled = controllerHandler.handleButtonUp(keyCode, event);
}
if (!handled) {
short translated = keybTranslator.translate(event.getKeyCode()); short translated = keybTranslator.translate(event.getKeyCode());
if (translated == 0) { if (translated == 0) {
return super.onKeyUp(keyCode, event); return super.onKeyUp(keyCode, event);
} }
keybTranslator.sendKeyUp(translated, keybTranslator.sendKeyUp(translated,
getModifierState(event)); getModifierState(event));
} }
else {
if (!controllerHandler.handleButtonUp(keyCode, event)) {
return super.onKeyUp(keyCode, event);
}
}
return true; return true;
} }
@ -562,6 +611,13 @@ public class Game extends Activity implements SurfaceHolder.Callback, OnGenericM
public void surfaceCreated(SurfaceHolder holder) { public void surfaceCreated(SurfaceHolder holder) {
if (!connected && !connecting) { if (!connected && !connecting) {
connecting = true; connecting = true;
// Resize the surface to match the aspect ratio of the video
// This must be done after the surface is created.
if (!stretchToFit) {
resizeSurfaceWithAspectRatio((SurfaceView) findViewById(R.id.surfaceView), width, height);
}
conn.start(PlatformBinding.getDeviceName(), holder, drFlags, conn.start(PlatformBinding.getDeviceName(), holder, drFlags,
PlatformBinding.getAudioRenderer(), decoderRenderer); PlatformBinding.getAudioRenderer(), decoderRenderer);
} }

View File

@ -6,6 +6,7 @@ import android.os.Bundle;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
import android.widget.Button; import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton; import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.RadioButton; import android.widget.RadioButton;
@ -18,6 +19,7 @@ public class StreamSettings extends Activity {
private Button advancedSettingsButton, addComputerButton; private Button advancedSettingsButton, addComputerButton;
private SharedPreferences prefs; private SharedPreferences prefs;
private RadioButton rbutton720p30, rbutton720p60, rbutton1080p30, rbutton1080p60; private RadioButton rbutton720p30, rbutton720p60, rbutton1080p30, rbutton1080p60;
private CheckBox stretchToFill;
@Override @Override
protected void onStop() { protected void onStop() {
@ -32,6 +34,7 @@ public class StreamSettings extends Activity {
setContentView(R.layout.activity_stream_settings); setContentView(R.layout.activity_stream_settings);
this.stretchToFill = (CheckBox) findViewById(R.id.stretchToFill);
this.advancedSettingsButton = (Button) findViewById(R.id.advancedSettingsButton); this.advancedSettingsButton = (Button) findViewById(R.id.advancedSettingsButton);
this.addComputerButton = (Button) findViewById(R.id.manuallyAddPc); this.addComputerButton = (Button) findViewById(R.id.manuallyAddPc);
this.rbutton720p30 = (RadioButton) findViewById(R.id.config720p30Selected); this.rbutton720p30 = (RadioButton) findViewById(R.id.config720p30Selected);
@ -44,6 +47,8 @@ public class StreamSettings extends Activity {
boolean res720p = prefs.getInt(Game.HEIGHT_PREF_STRING, Game.DEFAULT_HEIGHT) == 720; boolean res720p = prefs.getInt(Game.HEIGHT_PREF_STRING, Game.DEFAULT_HEIGHT) == 720;
boolean fps30 = prefs.getInt(Game.REFRESH_RATE_PREF_STRING, Game.DEFAULT_REFRESH_RATE) == 30; boolean fps30 = prefs.getInt(Game.REFRESH_RATE_PREF_STRING, Game.DEFAULT_REFRESH_RATE) == 30;
stretchToFill.setChecked(prefs.getBoolean(Game.STRETCH_PREF_STRING, Game.DEFAULT_STRETCH));
rbutton720p30.setChecked(false); rbutton720p30.setChecked(false);
rbutton720p60.setChecked(false); rbutton720p60.setChecked(false);
rbutton1080p30.setChecked(false); rbutton1080p30.setChecked(false);
@ -119,5 +124,12 @@ public class StreamSettings extends Activity {
startActivity(i); startActivity(i);
} }
}); });
stretchToFill.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
prefs.edit().putBoolean(Game.STRETCH_PREF_STRING, isChecked).commit();
}
});
} }
} }

View File

@ -148,6 +148,10 @@ public class ControllerHandler {
} }
} }
mapping.isDpad = (dev.getSources() & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD;
mapping.isGamepad = (dev.getSources() & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD ||
(dev.getSources() & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK;
return mapping; return mapping;
} }
@ -177,7 +181,48 @@ public class ControllerHandler {
leftStickX, leftStickY, rightStickX, rightStickY); leftStickX, leftStickY, rightStickX, rightStickY);
} }
private int handleRemapping(ControllerMapping mapping, int keyCode) { private static boolean isEventExpected(ControllerMapping mapping, int keyCode) {
if (mapping.isDpad) {
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_LEFT:
case KeyEvent.KEYCODE_DPAD_RIGHT:
case KeyEvent.KEYCODE_DPAD_CENTER:
case KeyEvent.KEYCODE_DPAD_UP:
case KeyEvent.KEYCODE_DPAD_DOWN:
return true;
}
}
if (mapping.isGamepad) {
switch (keyCode) {
case KeyEvent.KEYCODE_BUTTON_MODE:
case KeyEvent.KEYCODE_BUTTON_START:
case KeyEvent.KEYCODE_MENU:
case KeyEvent.KEYCODE_BACK:
case KeyEvent.KEYCODE_BUTTON_SELECT:
case KeyEvent.KEYCODE_DPAD_LEFT:
case KeyEvent.KEYCODE_DPAD_RIGHT:
case KeyEvent.KEYCODE_DPAD_UP:
case KeyEvent.KEYCODE_DPAD_DOWN:
case KeyEvent.KEYCODE_BUTTON_B:
case KeyEvent.KEYCODE_DPAD_CENTER:
case KeyEvent.KEYCODE_BUTTON_A:
case KeyEvent.KEYCODE_BUTTON_X:
case KeyEvent.KEYCODE_BUTTON_Y:
case KeyEvent.KEYCODE_BUTTON_L1:
case KeyEvent.KEYCODE_BUTTON_R1:
case KeyEvent.KEYCODE_BUTTON_THUMBL:
case KeyEvent.KEYCODE_BUTTON_THUMBR:
case KeyEvent.KEYCODE_BUTTON_L2:
case KeyEvent.KEYCODE_BUTTON_R2:
return true;
}
}
return false;
}
private static int handleRemapping(ControllerMapping mapping, int keyCode) {
if (mapping.isDualShock4) { if (mapping.isDualShock4) {
switch (keyCode) { switch (keyCode) {
case KeyEvent.KEYCODE_BUTTON_Y: case KeyEvent.KEYCODE_BUTTON_Y:
@ -317,6 +362,10 @@ public class ControllerHandler {
return true; return true;
} }
if (!isEventExpected(mapping, keyCode)) {
return false;
}
// If the button hasn't been down long enough, sleep for a bit before sending the up event // If the button hasn't been down long enough, sleep for a bit before sending the up event
// This allows "instant" button presses (like OUYA's virtual menu button) to work. This // This allows "instant" button presses (like OUYA's virtual menu button) to work. This
// path should not be triggered during normal usage. // path should not be triggered during normal usage.
@ -440,6 +489,10 @@ public class ControllerHandler {
return true; return true;
} }
if (!isEventExpected(mapping, keyCode)) {
return false;
}
switch (keyCode) { switch (keyCode) {
case KeyEvent.KEYCODE_BUTTON_MODE: case KeyEvent.KEYCODE_BUTTON_MODE:
inputMap |= ControllerPacket.SPECIAL_BUTTON_FLAG; inputMap |= ControllerPacket.SPECIAL_BUTTON_FLAG;
@ -549,5 +602,7 @@ public class ControllerHandler {
public float hatYDeadzone; public float hatYDeadzone;
public boolean isDualShock4; public boolean isDualShock4;
public boolean isDpad;
public boolean isGamepad;
} }
} }

View File

@ -5,6 +5,7 @@ import java.io.File;
import java.io.FileReader; import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.concurrent.locks.LockSupport;
import android.graphics.PixelFormat; import android.graphics.PixelFormat;
import android.os.Build; import android.os.Build;
@ -169,6 +170,7 @@ public class AndroidCpuDecoderRenderer implements VideoDecoderRenderer {
long diff = nextFrameTime - System.currentTimeMillis(); long diff = nextFrameTime - System.currentTimeMillis();
if (diff > WAIT_CEILING_MS) { if (diff > WAIT_CEILING_MS) {
LockSupport.parkNanos(1);
continue; continue;
} }

View File

@ -3,6 +3,7 @@ package com.limelight.binding.video;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.concurrent.locks.LockSupport;
import com.limelight.LimeLog; import com.limelight.LimeLog;
import com.limelight.nvstream.av.ByteBufferDescriptor; import com.limelight.nvstream.av.ByteBufferDescriptor;
@ -203,6 +204,9 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer {
} }
} else { } else {
switch (outIndex) { switch (outIndex) {
case MediaCodec.INFO_TRY_AGAIN_LATER:
LockSupport.parkNanos(1);
break;
case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED: case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
LimeLog.info("Output buffers changed"); LimeLog.info("Output buffers changed");
break; break;

View File

@ -11,7 +11,7 @@ public class Dialog implements Runnable {
private Activity activity; private Activity activity;
private boolean endAfterDismiss; private boolean endAfterDismiss;
AlertDialog alert; private AlertDialog alert;
private static ArrayList<Dialog> rundownDialogs = new ArrayList<Dialog>(); private static ArrayList<Dialog> rundownDialogs = new ArrayList<Dialog>();
@ -25,13 +25,15 @@ public class Dialog implements Runnable {
public static void closeDialogs() public static void closeDialogs()
{ {
for (Dialog d : rundownDialogs) { synchronized (rundownDialogs) {
if (d.alert.isShowing()) { for (Dialog d : rundownDialogs) {
d.alert.dismiss(); if (d.alert.isShowing()) {
d.alert.dismiss();
}
} }
rundownDialogs.clear();
} }
rundownDialogs.clear();
} }
public static void displayDialog(Activity activity, String title, String message, boolean endAfterDismiss) public static void displayDialog(Activity activity, String title, String message, boolean endAfterDismiss)
@ -54,16 +56,21 @@ public class Dialog implements Runnable {
alert.setButton(AlertDialog.BUTTON_NEUTRAL, "OK", new DialogInterface.OnClickListener() { alert.setButton(AlertDialog.BUTTON_NEUTRAL, "OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
alert.dismiss(); synchronized (rundownDialogs) {
rundownDialogs.remove(this); rundownDialogs.remove(this);
alert.dismiss();
}
if (endAfterDismiss) if (endAfterDismiss) {
activity.finish(); activity.finish();
}
} }
}); });
rundownDialogs.add(this); synchronized (rundownDialogs) {
alert.show(); rundownDialogs.add(this);
alert.show();
}
} }
} }

View File

@ -33,13 +33,15 @@ public class SpinnerDialog implements Runnable,OnCancelListener {
public static void closeDialogs() public static void closeDialogs()
{ {
for (SpinnerDialog d : rundownDialogs) { synchronized (rundownDialogs) {
if (d.progress.isShowing()) { for (SpinnerDialog d : rundownDialogs) {
d.progress.dismiss(); if (d.progress.isShowing()) {
d.progress.dismiss();
}
} }
rundownDialogs.clear();
} }
rundownDialogs.clear();
} }
public void dismiss() public void dismiss()
@ -85,18 +87,27 @@ public class SpinnerDialog implements Runnable,OnCancelListener {
progress.setCancelable(false); progress.setCancelable(false);
} }
progress.show(); synchronized (rundownDialogs) {
rundownDialogs.add(this);
progress.show();
}
} }
else else
{ {
if (progress.isShowing()) { synchronized (rundownDialogs) {
progress.dismiss(); if (rundownDialogs.remove(this) && progress.isShowing()) {
progress.dismiss();
}
} }
} }
} }
@Override @Override
public void onCancel(DialogInterface dialog) { public void onCancel(DialogInterface dialog) {
synchronized (rundownDialogs) {
rundownDialogs.remove(this);
}
// This will only be called if finish was true, so we don't need to check again // This will only be called if finish was true, so we don't need to check again
activity.finish(); activity.finish();
} }