Skip to content
This repository has been archived by the owner on Dec 29, 2022. It is now read-only.

Commit

Permalink
Merge pull request #156 from g-ortuno/correctly-destroy-activity
Browse files Browse the repository at this point in the history
Correctly destroy activity
  • Loading branch information
schilit committed Jan 22, 2015
2 parents 797088e + f738bce commit 75309e1
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
Expand All @@ -30,7 +32,6 @@

public class TestActivity extends Activity {

public static final String OPTIONAL_IMPLEMENTED = "optional.implemented";
private static final String TAG = TestActivity.class.getCanonicalName();
private TestRunner mTestRunner;
private ArrayList<TestHelper> mUriBeaconTests;
Expand Down Expand Up @@ -58,8 +59,13 @@ public void run() {
progress = new ProgressDialog(TestActivity.this);
progress.setMessage(getString(R.string.put_beacon_in_config_mode));
progress.show();
progress.setCancelable(false);
progress.setCanceledOnTouchOutside(false);
progress.setOnCancelListener(new OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
mTestRunner.stop();
}
});
}
});
}
Expand Down Expand Up @@ -113,10 +119,9 @@ protected void onResume() {
}

@Override
protected void onPause() {
super.onPause();
mTestRunner.pause();
protected void onDestroy() {
super.onDestroy();
mTestRunner.stop();
}

}

Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ public void onScanResult(int callbackType, ScanResult result) {
private boolean failed = false;
private boolean finished = false;
private boolean disconnected = false;
private BluetoothGatt mGatt;
private long SCAN_TIMEOUT = TimeUnit.SECONDS.toMillis(5);
private BluetoothGattService mService;
private String mName;
Expand All @@ -78,51 +79,53 @@ public void onScanResult(int callbackType, ScanResult result) {
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
super.onConnectionStateChange(gatt, status, newState);
Log.d(TAG, "Status: " + status + "; New State: " + newState);
mGatt = gatt;
if (status == BluetoothGatt.GATT_SUCCESS) {
if (newState == BluetoothProfile.STATE_CONNECTED) {
gatt.discoverServices();
mGatt.discoverServices();
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
if (!failed) {
mTestActions.remove();
disconnected = true;
dispatch(gatt);
dispatch();
}
}
} else {
fail(gatt, "Failed. Status: " + status + ". New State: " + newState);
fail("Failed. Status: " + status + ". New State: " + newState);
}
}

@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
super.onServicesDiscovered(gatt, status);
Log.d(TAG, "On services discovered");
mService = gatt.getService(mServiceUuid);
mGatt = gatt;
mService = mGatt.getService(mServiceUuid);
mTestActions.remove();
mTestCallback.connectedToBeacon();
dispatch(gatt);
dispatch();
}

@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic,
int status) {
super.onCharacteristicRead(gatt, characteristic, status);
Log.d(TAG, "On characteristic read");
mGatt = gatt;
TestAction readTest = mTestActions.peek();
if (readTest.expectedReturnCode != status) {
fail(gatt,
"Incorrect status code: " + status + ". Expected: " + readTest.expectedReturnCode);
fail("Incorrect status code: " + status + ". Expected: " + readTest.expectedReturnCode);
} else if (!Arrays.equals(readTest.transmittedValue, characteristic.getValue())) {
if (readTest.transmittedValue.length != characteristic.getValue().length) {
fail(gatt, "Wrong length. Expected: " + new String(readTest.transmittedValue)
fail("Wrong length. Expected: " + new String(readTest.transmittedValue)
+ ". But received: " + new String(characteristic.getValue()));
} else {
fail(gatt, "Result not the same. Expected: " + new String(readTest.transmittedValue)
fail("Result not the same. Expected: " + new String(readTest.transmittedValue)
+ ". But received: " + new String(characteristic.getValue()));
}
} else {
mTestActions.remove();
dispatch(gatt);
dispatch();
}
}

Expand All @@ -132,13 +135,13 @@ public void onCharacteristicWrite(BluetoothGatt gatt,
int status) {
super.onCharacteristicWrite(gatt, characteristic, status);
Log.d(TAG, "On write");
mGatt = gatt;
TestAction writeTest = mTestActions.peek();
if (writeTest.expectedReturnCode != status) {
fail(gatt,
"Incorrect status code: " + status + ". Expected: " + writeTest.expectedReturnCode);
fail("Incorrect status code: " + status + ". Expected: " + writeTest.expectedReturnCode);
} else {
mTestActions.remove();
dispatch(gatt);
dispatch();
}
}

Expand All @@ -148,6 +151,7 @@ public void onCharacteristicWrite(BluetoothGatt gatt,
private LinkedList<TestAction> mTestSteps;
private BluetoothAdapter mBluetoothAdapter;
private Handler mHandler;
private boolean stopped;

private TestHelper(
String name, Context context, UUID serviceUuid,
Expand All @@ -163,6 +167,7 @@ private TestHelper(
(BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
mHandler = new Handler(Looper.myLooper());
stopped = false;
}

public String getName() {
Expand All @@ -185,17 +190,18 @@ public void run(BluetoothDevice bluetoothDevice, BluetoothGatt gatt, BluetoothGa
Log.d(TAG, "Run Called for: " + getName());
started = true;
mBluetoothDevice = bluetoothDevice;
if (gatt != null) {
mGatt = gatt;
if (mGatt != null) {
mService = gatt.getService(mServiceUuid);
}
mTestCallback.testStarted();
mOutSideGattCallback = outsideCallback;
dispatch(gatt);
dispatch();
}

private void connectToGatt() {
Log.d(TAG, "Connecting");
// Gatt == null is only passed on the first connection

if (disconnected) {
try {
disconnected = false;
Expand All @@ -215,15 +221,15 @@ private void connectToGatt() {
}
}

private void readFromGatt(BluetoothGatt gatt) {
private void readFromGatt() {
Log.d(TAG, "reading");
TestAction readTest = mTestActions.peek();
BluetoothGattCharacteristic characteristic = mService
.getCharacteristic(readTest.characteristicUuid);
gatt.readCharacteristic(characteristic);
mGatt.readCharacteristic(characteristic);
}

private void writeToGatt(BluetoothGatt gatt) {
private void writeToGatt() {
Log.d(TAG, "Writting");
TestAction writeTest = mTestActions.peek();
BluetoothGattCharacteristic characteristic = mService
Expand All @@ -235,27 +241,33 @@ private void writeToGatt(BluetoothGatt gatt) {
characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
}
characteristic.setValue(writeTest.transmittedValue);
gatt.writeCharacteristic(characteristic);
mGatt.writeCharacteristic(characteristic);
}

private void disconnectFromGatt(BluetoothGatt gatt) {
private void disconnectFromGatt() {
Log.d(TAG, "Disconnecting");
gatt.disconnect();
mGatt.disconnect();
}

private void dispatch(BluetoothGatt gatt) {
private void dispatch() {
Log.d(TAG, "Dispatching");
if (mTestActions.peek().actionType == TestAction.LAST) {
// If the test is stopped and connected to the beacon
// disconnect from the beacon
if (stopped) {
if (mGatt != null) {
disconnectFromGatt();
}
} else if (mTestActions.peek().actionType == TestAction.LAST) {
finished = true;
mTestCallback.testCompleted(mBluetoothDevice, gatt);
mTestCallback.testCompleted(mBluetoothDevice, mGatt);
} else if (mTestActions.peek().actionType == TestAction.CONNECT) {
connectToGatt();
} else if (mTestActions.peek().actionType == TestAction.ASSERT) {
readFromGatt(gatt);
readFromGatt();
} else if (mTestActions.peek().actionType == TestAction.WRITE) {
writeToGatt(gatt);
writeToGatt();
} else if (mTestActions.peek().actionType == TestAction.DISCONNECT) {
disconnectFromGatt(gatt);
disconnectFromGatt();
} else if (mTestActions.peek().actionType == TestAction.ADV_FLAGS) {
lookForAdv();
} else if (mTestActions.peek().actionType == TestAction.ADV_TX_POWER) {
Expand Down Expand Up @@ -297,7 +309,7 @@ private void lookForAdv() {
@Override
public void run() {
stopSearchingForBeacons();
fail(null, "Could not find adv packet");
fail("Could not find adv packet");
}
}, SCAN_TIMEOUT);
}
Expand All @@ -312,37 +324,37 @@ private void checkPacket(ScanResult result) {
TestAction action = mTestActions.peek();
if (action.actionType == TestAction.ADV_PACKET) {
if (getAdvPacket(result).length < 2) {
fail(null, "Invalid Adv Packet");
fail("Invalid Adv Packet");
} else {
mTestActions.remove();
dispatch(null);
dispatch();
}
} else if (action.actionType == TestAction.ADV_FLAGS) {
byte flags = getFlags(result);
byte expectedFlags = action.transmittedValue[0];
if (expectedFlags != flags) {
fail(null, "Received: " + flags + ". Expected: " + expectedFlags);
fail("Received: " + flags + ". Expected: " + expectedFlags);
} else {
mTestActions.remove();
dispatch(null);
dispatch();
}
} else if (action.actionType == TestAction.ADV_TX_POWER) {
byte txPowerLevel = getTxPowerLevel(result);
byte expectedTxPowerLevel = action.transmittedValue[0];
if (expectedTxPowerLevel != txPowerLevel) {
fail(null, "Received: " + txPowerLevel + ". Expected: " + expectedTxPowerLevel);
fail("Received: " + txPowerLevel + ". Expected: " + expectedTxPowerLevel);
} else {
mTestActions.remove();
dispatch(null);
dispatch();
}
} else if (action.actionType == TestAction.ADV_URI) {
byte[] uri = getUri(result);
if (!Arrays.equals(action.transmittedValue, uri)) {
fail(null, "Received: " + Arrays.toString(uri)
fail("Received: " + Arrays.toString(uri)
+ ". Expected: " + Arrays.toString(action.transmittedValue));
} else {
mTestActions.remove();
dispatch(null);
dispatch();
}
}
}
Expand All @@ -369,19 +381,25 @@ private byte[] getAdvPacket(ScanResult result) {
return result.getScanRecord().getServiceData(UriBeacon.URI_SERVICE_UUID);
}

private void fail(BluetoothGatt gatt, String reason) {
private void fail(String reason) {
Log.d(TAG, "Failing because: " + reason);
failed = true;
mTestActions.peek().failed = true;
mTestActions.peek().reason = reason;
finished = true;
mTestCallback.testCompleted(mBluetoothDevice, gatt);
mTestCallback.testCompleted(mBluetoothDevice, mGatt);
}

public boolean isFinished() {
return finished;
}

public void stopTest() {
stopped = true;
stopSearchingForBeacons();
fail("Stopped by user");
}

public interface TestCallback {

public void testStarted();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public class TestRunner {

private static final String TAG = TestRunner.class.getCanonicalName();

private boolean mPause;
private boolean mStoped;
private boolean mFailed = false;
private TestCallback mTestCallback = new TestCallback() {
@Override
Expand All @@ -50,13 +50,18 @@ public void testCompleted(final BluetoothDevice bluetoothDevice, final Bluetooth
mFailed = true;
}
mDataCallback.dataUpdated();
if (!mPause) {
if (!mStoped) {
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
start(bluetoothDevice, gatt);
}
}, TimeUnit.SECONDS.toMillis(1));
} else {
if (gatt != null){
gatt.disconnect();
}
mHandler.removeCallbacksAndMessages(null);
}
}

Expand All @@ -78,6 +83,7 @@ public void connectedToBeacon() {

public TestRunner(Context context, DataCallback dataCallback,
String testType, boolean optionalImplemented) {
mStoped = false;
mDataCallback = dataCallback;
if (BasicUriBeaconTests.class.getName().equals(testType)) {
mUriBeaconTests = BasicUriBeaconTests.initializeTests(context, mTestCallback, optionalImplemented);
Expand All @@ -90,14 +96,14 @@ public TestRunner(Context context, DataCallback dataCallback,

public void start(BluetoothDevice bluetoothDevice, BluetoothGatt gatt) {
Log.d(TAG, "Starting tests");
mPause = false;
if (mTestIterator.hasNext()) {
mLatestTest = mTestIterator.next();
mLatestTest.run(bluetoothDevice, gatt, superBluetoothScanCallback);
} else {
mDataCallback.testsCompleted(mFailed);
}
}

// To keep the connection to the beacon alive the same gatt object
// must be passed around. But since gatt is attached to a callback a single super callback
// is needed for all tests to share.
Expand Down Expand Up @@ -130,8 +136,9 @@ public ArrayList<TestHelper> getUriBeaconTests() {
return mUriBeaconTests;
}

public void pause() {
mPause = true;
public void stop() {
mStoped = true;
mLatestTest.stopTest();
}

public interface DataCallback {
Expand Down

0 comments on commit 75309e1

Please sign in to comment.