diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 74878b4..ed323d1 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -4,9 +4,6 @@
package="com.samourai.txtenna">
-
-
-
@@ -26,7 +23,7 @@
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar"
- android:launchMode="singleTop">
+ android:launchMode="singleTask">
@@ -55,13 +52,6 @@
android:configChanges="keyboardHidden|orientation|screenSize"
/>
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/java/com/samourai/sms/SMSReceiver.java b/app/src/main/java/com/samourai/sms/SMSReceiver.java
deleted file mode 100755
index 4913139..0000000
--- a/app/src/main/java/com/samourai/sms/SMSReceiver.java
+++ /dev/null
@@ -1,221 +0,0 @@
-package com.samourai.sms;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.Handler;
-import android.telephony.SmsMessage;
-import android.util.Log;
-import android.widget.Toast;
-
-import com.samourai.txtenna.payload.PayloadFactory;
-
-import com.google.gson.Gson;
-import com.samourai.txtenna.utils.TransactionHandler;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-
-public class SMSReceiver extends BroadcastReceiver {
-
- /** TAG used for Debug-Logging */
- protected static final String LOG_TAG = "SMSReceiver";
-
- /** The Action fired by the Android-System when a SMS was received.
- * We are using the Default Package-Visibility */
- private static final String ACTION = "android.provider.Telephony.SMS_RECEIVED";
-
- private static HashMap>> incoming = new HashMap>>();
-
- private static List seen = new ArrayList();
-
- private static TransactionHandler transactionHandler = null;
-
- public SMSReceiver() {
- ;
- }
-
- public SMSReceiver(TransactionHandler transactionHandler) {
- this.transactionHandler = transactionHandler;
- }
-
- // @Override
- public void onReceive(final Context context, Intent intent) {
-
- if ((intent.getAction().equals(ACTION) || intent.getAction().contains("SMS_RECEIVED"))) {
-
- StringBuilder sb = new StringBuilder();
- Bundle bundle = intent.getExtras();
-
- Handler handler = new Handler();
-
- if (bundle != null) {
-
- Object[] pdusObj = (Object[]) bundle.get("pdus");
- SmsMessage[] messages = new SmsMessage[pdusObj.length];
- for(int i = 0; i < pdusObj.length; i++) {
- messages[i] = SmsMessage.createFromPdu((byte[])pdusObj[i]);
- }
-
- String incomingTelNo = null;
- String id = null;
- for(SmsMessage currentMessage : messages) {
- final String msg = currentMessage.getDisplayMessageBody().trim();
- incomingTelNo = currentMessage.getDisplayOriginatingAddress();
-
- if(seen.contains(incomingTelNo + ":" + msg)) {
- continue;
- }
- else {
- seen.add(incomingTelNo + ":" + msg);
- }
-
- Log.d("SMSReceiver", incomingTelNo + ":" + msg);
-
- //
- // test for segment count, if present assume Segment0
- //
- String i = null;
- int c = -1;
- PayloadFactory.Seg0 seg0 = null;
- PayloadFactory.SegN segn = null;
- Gson gson = new Gson();
- if(msg.contains("\"s\":")) {
- seg0 = gson.fromJson(msg, PayloadFactory.Seg0.class);
- c = 0;
- i = seg0.i;
- }
- else {
- segn = gson.fromJson(msg, PayloadFactory.SegN.class);
- c = segn.c;
- i = segn.i;
- }
-
- if(i != null && i.length() != 0 && c != -1) {
- HashMap> ids = incoming.get(incomingTelNo);
- HashMap segments = null;
- if(ids == null) {
- ids = new HashMap>();
- }
- else {
- segments = ids.get(i);
- }
- id = i;
- if(segments == null) {
- segments = new HashMap();
- }
- segments.put(Integer.toString(c), msg);
- if(ids == null) {
- ids = new HashMap>();
- }
- ids.put(i, segments);
- incoming.put(incomingTelNo, ids);
-
- handler.post(new Runnable() {
- @Override
- public void run() {
- Toast.makeText(context, "receiving:" + msg, Toast.LENGTH_SHORT).show();
- }
- });
-
- }
-
- }
-
- /*
- final String _incomingTelNo = incomingTelNo;
- handler.post(new Runnable() {
- @Override
- public void run() {
- Intent intent = new Intent("com.samourai.ponydirect.LOG");
- intent.putExtra("msg", "incoming from:" + _incomingTelNo);
- LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
- }
- });
- */
-
- if(incomingTelNo != null && id != null && id.length() != 0) {
- verifyIncoming(context, incomingTelNo, id);
- }
-
- }
- }
- }
-
- private void verifyIncoming(final Context context, String incomingTelNo, String id) {
-
- Handler handler = new Handler();
-
- HashMap> ids = incoming.get(incomingTelNo);
- HashMap segments = ids.get(id);
-
- int segs = -1;
- String hash = null;
- String net = null;
-
- Gson gson = new Gson();
- PayloadFactory.Seg0 seg0 = null;
- PayloadFactory.SegN segn = null;
-
- for(String key : segments.keySet()) {
-
- String msg = segments.get(key);
- if(msg.contains("\"s\":")) {
- seg0 = gson.fromJson(msg, PayloadFactory.Seg0.class);
- segs = seg0.s;
- hash = seg0.h;
- net = (seg0.n != null && seg0.n.length() > 0) ? seg0.n : "m";
- }
- else {
- segn = gson.fromJson(msg, PayloadFactory.SegN.class);
- }
-
- }
-
- if(segs != -1 && segs == segments.size()) {
-
- String[] s = new String[segs];
-
- int c = -1;
-
- for(String key : segments.keySet()) {
-
- final String msg = segments.get(key);
-
- if(msg.contains("\"s\":")) {
- seg0 = gson.fromJson(msg, PayloadFactory.Seg0.class);
- c = 0;
- }
- else {
- segn = gson.fromJson(msg, PayloadFactory.SegN.class);
- c = segn.c;
- }
-
- if(c != -1) {
- s[c] = msg;
- }
-
- }
-
- final List segmentList = Arrays.asList(s);
-
- handler.post(new Runnable() {
- @Override
- public void run() {
- Toast.makeText(context, "received:" + segmentList.size(), Toast.LENGTH_SHORT).show();
- }
- });
-
- PayloadFactory.getInstance(context, transactionHandler).broadcastPayload(segmentList, (net != null && net.equals("t")) ? false : true, false);
-
- }
- else {
- Log.d("SMSReceiver", "verifyIncoming(): segment size not recognized");
- }
-
- }
-
-}
diff --git a/app/src/main/java/com/samourai/sms/SMSSender.java b/app/src/main/java/com/samourai/sms/SMSSender.java
deleted file mode 100644
index 81cf6d7..0000000
--- a/app/src/main/java/com/samourai/sms/SMSSender.java
+++ /dev/null
@@ -1,88 +0,0 @@
-package com.samourai.sms;
-
-import android.app.Activity;
-import android.app.PendingIntent;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.telephony.SmsManager;
-import android.widget.Toast;
-//import android.widget.Toast;
-//import android.util.Log;
-
-public class SMSSender {
-
- private static Context context = null;
- private static PendingIntent sentPI = null;
- private static PendingIntent deliveredPI = null;
-
- private static SMSSender instance = null;
-
- private SMSSender() { ; }
-
- public static SMSSender getInstance(Context ctx) {
- context = ctx;
-
- if(instance == null) {
- instance = new SMSSender();
- setReceivers();
- }
-
- return instance;
- }
-
- public void send(String text, String dest) {
- SmsManager sm = SmsManager.getDefault();
- sm.sendTextMessage(dest, null, text, null, null);
- }
-
- public static void setReceivers() {
- String SENT = "SMS_SENT";
- String DELIVERED = "SMS_DELIVERED";
-
- sentPI = PendingIntent.getBroadcast(context, 0, new Intent(SENT), 0);
- deliveredPI = PendingIntent.getBroadcast(context, 0, new Intent(DELIVERED), 0);
-
- //---when the SMS has been sent---
- context.registerReceiver(new BroadcastReceiver(){
- @Override
- public void onReceive(Context arg0, Intent arg1) {
- switch (getResultCode())
- {
- case Activity.RESULT_OK:
- Toast.makeText(((Activity)context).getBaseContext(), "SMS sent", Toast.LENGTH_SHORT).show();
- break;
- case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
-// Toast.makeText(((Activity)context).getBaseContext(), "SMS not sent: Generic failure", Toast.LENGTH_SHORT).show();
- break;
- case SmsManager.RESULT_ERROR_NO_SERVICE:
-// Toast.makeText(((Activity)context).getBaseContext(), "SMS not sent: No service", Toast.LENGTH_SHORT).show();
- break;
- case SmsManager.RESULT_ERROR_NULL_PDU:
-// Toast.makeText(((Activity)context).getBaseContext(), "SMS not sent: Null PDU", Toast.LENGTH_SHORT).show();
- break;
- case SmsManager.RESULT_ERROR_RADIO_OFF:
-// Toast.makeText(((Activity)context).getBaseContext(), "SMS not sent: Radio off", Toast.LENGTH_SHORT).show();
- break;
- }
- }
- }, new IntentFilter(SENT));
-
- //---when the SMS has been delivered---
- context.registerReceiver(new BroadcastReceiver(){
- @Override
- public void onReceive(Context arg0, Intent arg1) {
- switch (getResultCode())
- {
- case Activity.RESULT_OK:
- Toast.makeText(((Activity)context).getBaseContext(), "SMS delivered", Toast.LENGTH_SHORT).show();
- break;
- case Activity.RESULT_CANCELED:
-// Toast.makeText(((Activity)context).getBaseContext(), "SMS not delivered", Toast.LENGTH_SHORT).show();
- break;
- }
- }
- }, new IntentFilter(DELIVERED));
- }
-}
diff --git a/app/src/main/java/com/samourai/txtenna/MainActivity.java b/app/src/main/java/com/samourai/txtenna/MainActivity.java
index 3ff746a..38eb572 100644
--- a/app/src/main/java/com/samourai/txtenna/MainActivity.java
+++ b/app/src/main/java/com/samourai/txtenna/MainActivity.java
@@ -37,7 +37,6 @@
import com.dm.zbar.android.scanner.ZBarScannerActivity;
import com.gotenna.sdk.GoTenna;
import com.gotenna.sdk.exceptions.GTInvalidAppTokenException;
-import com.samourai.sms.SMSReceiver;
import com.samourai.txtenna.adapters.BroadcastLogsAdapter;
import com.samourai.txtenna.payload.PayloadFactory;
import com.samourai.txtenna.prefs.PrefsUtil;
@@ -68,7 +67,6 @@ public class MainActivity extends AppCompatActivity implements IncomingMessagesM
private final static int SCAN_HEX_TX = 2011;
- private static final int SMS_PERMISSION_CODE = 0;
private static final int CAMERA_PERMISSION_CODE = 1;
private Group emptyView;
private LinearLayout BottomSheetMenu;
@@ -129,17 +127,6 @@ public void onClick(View view) {
}
});
- smsSelection = BottomSheetMenu.findViewById(R.id.sms);
- smsSelection.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- relayViaGoTenna = false;
- bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
- doGetHex();
- }
- });
-
-
if (!hasCameraPermission()) {
showRequestCameraPermissionInfoAlertDialog();
}
@@ -148,9 +135,10 @@ public void onClick(View view) {
showRequestCameraPermissionInfoAlertDialog();
}
- if (!hasReadSmsPermission() || !hasSendSmsPermission()) {
- showRequestSMSPermissionInfoAlertDialog();
- }
+ transactionHandler = new TransactionHandler("TransactionHandler", adapter);
+ transactionHandler.start();
+
+ Log.d("MainActivity", "onCreate " + Integer.toHexString(this.hashCode()) + " transactionHandler:" + Integer.toHexString(transactionHandler.hashCode()) + " [lifecycle]");
try {
PayloadFactory.getInstance(MainActivity.this, transactionHandler).readBroadcastLog();
@@ -161,14 +149,26 @@ public void onClick(View view) {
try {
goTennaUtil.getInstance(MainActivity.this).init();
}
- catch (GTInvalidAppTokenException e) {
+ catch (GTInvalidAppTokenException | java.lang.IllegalArgumentException e) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle(R.string.invalid_token_title);
+ builder.setMessage(R.string.invalid_token);
+ builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ dialog.dismiss();
+ }
+ });
+ builder.show();
+
// should set the value goTennaUtil::GOTENNA_APP_TOKEN
e.printStackTrace();
}
- Log.d("MainActivity", "checking connected address:" + goTennaUtil.getInstance(MainActivity.this).getGtConnectionManager().getConnectedGotennaAddress());
- if (GoTenna.tokenIsVerified()) {
+ if (goTennaUtil.tokenIsVerified()) {
// if NOT already paired, and previous hardware address saved, try to connect to a goTenna
+ Log.d("MainActivity", "checking connected address:" + goTennaUtil.getInstance(MainActivity.this).getGtConnectionManager().getConnectedGotennaAddress());
+
if (!goTennaUtil.getInstance(MainActivity.this).isPaired() &&
goTennaUtil.getInstance(MainActivity.this).GetHardwareAddress() != null) {
// set geolocation after we connect to a device
@@ -176,6 +176,9 @@ public void onClick(View view) {
IncomingMessagesManager.getInstance(MainActivity.this.getApplicationContext()).addIncomingMessageListener(this);
IncomingMessagesManager.getInstance(MainActivity.this.getApplicationContext()).startListening();
+
+ // use GID from last *unconfirmed* broadcast transaction, otherwise a new random GID
+ long gid = BroadcastLogUtil.getInstance().lastGID();
goTennaUtil.getInstance(MainActivity.this).connect(null, region);
}
}
@@ -195,445 +198,390 @@ public void onClick(View view) {
doSendHex(s[0], params);
}
}
- }
-
- @Override
- protected void onPostCreate(@Nullable Bundle savedInstanceState) {
- super.onPostCreate(savedInstanceState);
- try {
- transactionHandler.start();
-
- refreshData();
- transactionHandler.startTransactionChecker();
- IncomingMessagesManager.getInstance(MainActivity.this.getApplicationContext()).addIncomingMessageListener(this);
- }
- catch (Exception e) {
- e.printStackTrace();
- }
- }
-
+ }
- @Override
- protected void onResume() {
- super.onResume();
-
- if(isReceiver == null) {
- isFilter = new IntentFilter();
- isFilter.addAction("android.provider.Telephony.SMS_RECEIVED");
- isFilter.setPriority(2147483647);
- isReceiver = new SMSReceiver(transactionHandler);
- MainActivity.this.registerReceiver(isReceiver, isFilter);
- }
- refreshData();
- transactionHandler.startTransactionChecker();
- IncomingMessagesManager.getInstance(MainActivity.this.getApplicationContext()).addIncomingMessageListener(this);
+ @Override
+ protected void onRestart() {
+ Log.d("MainActivity", "onRestart " + Integer.toHexString(this.hashCode()) + " [lifecycle]");
+ super.onRestart();
+ if (transactionHandler == null) {
+ Log.d("MainActivity", "onRestart, transactionHandler is null!! " + Integer.toHexString(this.hashCode()) + " [lifecycle]");
}
+ }
- @Override
- protected void onPause() {
- super.onPause();
-
- try {
- if(isReceiver != null) {
- MainActivity.this.unregisterReceiver(isReceiver);
- IncomingMessagesManager.getInstance(MainActivity.this.getApplicationContext()).removeIncomingMessageListener(this);
- transactionHandler.stopTransactionChecker();
- }
- }
- catch(IllegalArgumentException iae) {
- ;
- }
+ @Override
+ protected void onStart() {
+ Log.d("MainActivity", "onStart " + Integer.toHexString(this.hashCode()) + " [lifecycle]");
+ super.onStart();
+ if (transactionHandler == null) {
+ Log.d("MainActivity", "onStart, transactionHandler is null!! " + Integer.toHexString(this.hashCode()) + " [lifecycle]");
}
+ }
- @Override
- protected void onDestroy() {
-
- try {
- if(isReceiver != null) {
- MainActivity.this.unregisterReceiver(isReceiver);
- IncomingMessagesManager.getInstance(MainActivity.this.getApplicationContext()).removeIncomingMessageListener(this);
- transactionHandler.stopTransactionChecker();
- }
- }
- catch(IllegalArgumentException iae) {
- ;
- }
-
- try {
- PayloadFactory.getInstance(MainActivity.this, transactionHandler).writeBroadcastLog();
- }
- catch(JSONException | IOException e) {
- e.printStackTrace();
- }
-
- transactionHandler.quit();
- transactionHandler = null;
+ @Override
+ protected void onResume() {
+ Log.d("MainActivity", "onResume " + Integer.toHexString(this.hashCode()) + " [lifecycle]");
+ super.onResume();
- super.onDestroy();
+ if (transactionHandler == null) {
+ Log.d("MainActivity", "onResume, transactionHandler is null!! " + Integer.toHexString(this.hashCode()) + " [lifecycle]");
}
- /**
- * Listener fpr bottomsheet events
- * this will set fab icon based on the bottomsheet's state
- */
- private BottomSheetBehavior.BottomSheetCallback bottomSheetCallback = new BottomSheetBehavior.BottomSheetCallback() {
- @Override
- public void onStateChanged(@NonNull View bottomSheet, int newState) {
- if (newState == BottomSheetBehavior.STATE_EXPANDED) {
- fab.setImageResource(R.drawable.ic_keyboard_arrow_down);
- }
- if (newState == BottomSheetBehavior.STATE_HIDDEN) {
- fab.setImageResource(R.drawable.ic_txtenna_fab_new);
- }
- }
-
- @Override
- public void onSlide(@NonNull View bottomSheet, float slideOffset) {
+ refreshData();
+ transactionHandler.startTransactionChecker();
+ IncomingMessagesManager.getInstance(MainActivity.this.getApplicationContext()).addIncomingMessageListener(this);
+ }
- }
- };
+ @Override
+ protected void onPause() {
+ Log.d("MainActivity", "onPause " + Integer.toHexString(this.hashCode()) + " [lifecycle]");
+ super.onPause();
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- // Inflate the menu; this adds items to the action bar if it is present.
- getMenuInflater().inflate(R.menu.menu_main, menu);
- return true;
+ if (transactionHandler == null) {
+ Log.d("MainActivity", "onPause, transactionHandler is null!! " + Integer.toHexString(this.hashCode()) + " [lifecycle]");
}
- @Override
- public void onBackPressed() {
- if (bottomSheetBehavior.getState() == BottomSheetBehavior.STATE_EXPANDED) {
- bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
- } else {
- super.onBackPressed();
- }
+ try {
+ PayloadFactory.getInstance(MainActivity.this, transactionHandler).writeBroadcastLog();
+ }
+ catch(JSONException | IOException e) {
+ e.printStackTrace();
}
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- // Handle action bar item clicks here. The action bar will
- // automatically handle clicks on the Home/Up button, so long
- // as you specify a parent activity in AndroidManifest.xml.
- int id = item.getItemId();
-
- //noinspection SimplifiableIfStatement
- if (id == R.id.action_settings) {
- startActivity(new Intent(this, SettingsActivity.class));
- return true;
- }
- if (id == R.id.networkmenu) {
- startActivity(new Intent(this, NetworkingActivity.class));
- return true;
- }
+ IncomingMessagesManager.getInstance(MainActivity.this.getApplicationContext()).removeIncomingMessageListener(this);
+ transactionHandler.stopTransactionChecker();
+ }
- if (id == R.id.qr_scan) {
- relayViaGoTenna = null;
- doScanHexTx();
- return true;
- }
+ @Override
+ protected void onStop() {
+ Log.d("MainActivity", "onStop " + Integer.toHexString(this.hashCode()) + " [lifecycle]");
+ super.onStop();
- return super.onOptionsItemSelected(item);
+ if (transactionHandler == null) {
+ Log.d("MainActivity", "onStop, transactionHandler is null!! " + Integer.toHexString(this.hashCode()) + " [lifecycle]");
}
+ }
+
+ @Override
+ protected void onDestroy() {
+ Log.d("MainActivity", "onDestroy " + Integer.toHexString(this.hashCode()) + " [lifecycle]");
+ super.onDestroy();
- private void refreshData() {
+ transactionHandler.quit();
+ transactionHandler = null;
+ }
- if (BroadcastLogUtil.getInstance().getBroadcastLog().size() == 0) {
- recyclerView.setVisibility(View.GONE);
- emptyView.setVisibility(View.VISIBLE);
- return;
- }else {
- recyclerView.setVisibility(View.VISIBLE);
- emptyView.setVisibility(View.GONE);
+ /**
+ * Listener fpr bottomsheet events
+ * this will set fab icon based on the bottomsheet's state
+ */
+ private BottomSheetBehavior.BottomSheetCallback bottomSheetCallback = new BottomSheetBehavior.BottomSheetCallback() {
+ @Override
+ public void onStateChanged(@NonNull View bottomSheet, int newState) {
+ if (newState == BottomSheetBehavior.STATE_EXPANDED) {
+ fab.setImageResource(R.drawable.ic_keyboard_arrow_down);
+ }
+ if (newState == BottomSheetBehavior.STATE_HIDDEN) {
+ fab.setImageResource(R.drawable.ic_txtenna_fab_new);
}
- transactionHandler.refresh();
}
@Override
- public void onActivityResult(int requestCode, int resultCode, Intent data) {
-
- if (resultCode == Activity.RESULT_OK && requestCode == SCAN_HEX_TX) {
-
- if (data != null && data.getStringExtra(ZBarConstants.SCAN_RESULT) != null) {
+ public void onSlide(@NonNull View bottomSheet, float slideOffset) {
- final String strResult = data.getStringExtra(ZBarConstants.SCAN_RESULT).trim();
-
- doSendHex(strResult, null);
+ }
+ };
- }
- } else {
- ;
- }
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ // Inflate the menu; this adds items to the action bar if it is present.
+ getMenuInflater().inflate(R.menu.menu_main, menu);
+ return true;
+ }
+ @Override
+ public void onBackPressed() {
+ Log.d("MainActivity", "onBackPressed " + Integer.toHexString(this.hashCode()) + " [lifecycle]");
+ if (bottomSheetBehavior.getState() == BottomSheetBehavior.STATE_EXPANDED) {
+ bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
+ } else {
+ super.onBackPressed();
}
+ }
- private void doGetHex() {
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ // Handle action bar item clicks here. The action bar will
+ // automatically handle clicks on the Home/Up button, so long
+ // as you specify a parent activity in AndroidManifest.xml.
+ int id = item.getItemId();
+
+ //noinspection SimplifiableIfStatement
+ if (id == R.id.action_settings) {
+ startActivity(new Intent(this, SettingsActivity.class));
+ return true;
+ }
+ if (id == R.id.networkmenu) {
+ startActivity(new Intent(this, NetworkingActivity.class));
+ return true;
+ }
- final EditText edHexTx = new EditText(MainActivity.this);
- edHexTx.setSingleLine(false);
- edHexTx.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE);
- edHexTx.setLines(10);
- edHexTx.setHint(R.string.tx_hex);
- edHexTx.setGravity(Gravity.START);
- TextWatcher textWatcher = new TextWatcher() {
+ if (id == R.id.qr_scan) {
+ relayViaGoTenna = null;
+ doScanHexTx();
+ return true;
+ }
- public void afterTextChanged(Editable s) {
- edHexTx.setSelection(0);
- }
+ return super.onOptionsItemSelected(item);
+ }
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- ;
- }
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- ;
- }
- };
- edHexTx.addTextChangedListener(textWatcher);
+ private void refreshData() {
- AlertDialog.Builder dlg = new AlertDialog.Builder(MainActivity.this)
- .setTitle(R.string.app_name)
- .setView(edHexTx)
- .setMessage(R.string.enter_tx_hex)
- .setCancelable(true)
- .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int whichButton) {
+ if (BroadcastLogUtil.getInstance().getBroadcastLog().size() == 0) {
+ recyclerView.setVisibility(View.GONE);
+ emptyView.setVisibility(View.VISIBLE);
+ return;
+ }else {
+ recyclerView.setVisibility(View.VISIBLE);
+ emptyView.setVisibility(View.GONE);
+ }
+ transactionHandler.refresh();
+ }
- dialog.dismiss();
- relayViaGoTenna = null;
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
- final String strHexTx = edHexTx.getText().toString().trim();
+ if (resultCode == Activity.RESULT_OK && requestCode == SCAN_HEX_TX) {
- Log.d("MainActivity", "hex:" + strHexTx);
+ if (data != null && data.getStringExtra(ZBarConstants.SCAN_RESULT) != null) {
- doSendHex(strHexTx, null);
+ final String strResult = data.getStringExtra(ZBarConstants.SCAN_RESULT).trim();
- }
- }).setNegativeButton(R.string.scan, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int whichButton) {
+ doSendHex(strResult, null);
- dialog.dismiss();
- relayViaGoTenna = null;
+ }
+ } else {
+ ;
+ }
- doScanHexTx();
- }
- });
+ }
- dlg.show();
+ private void doGetHex() {
- }
+ final EditText edHexTx = new EditText(MainActivity.this);
+ edHexTx.setSingleLine(false);
+ edHexTx.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE);
+ edHexTx.setLines(10);
+ edHexTx.setHint(R.string.tx_hex);
+ edHexTx.setGravity(Gravity.START);
+ TextWatcher textWatcher = new TextWatcher() {
- private void doScanHexTx() {
- Intent intent = new Intent(MainActivity.this, ZBarScannerActivity.class);
- intent.putExtra(ZBarConstants.SCAN_MODES, new int[]{ Symbol.QRCODE } );
- startActivityForResult(intent, SCAN_HEX_TX);
- }
+ public void afterTextChanged(Editable s) {
+ edHexTx.setSelection(0);
+ }
- private void showRequestCameraPermissionInfoAlertDialog() {
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ ;
+ }
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ ;
+ }
+ };
+ edHexTx.addTextChangedListener(textWatcher);
+
+ AlertDialog.Builder dlg = new AlertDialog.Builder(MainActivity.this)
+ .setTitle(R.string.app_name)
+ .setView(edHexTx)
+ .setMessage(R.string.enter_tx_hex)
+ .setCancelable(true)
+ .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int whichButton) {
- AlertDialog.Builder builder = new AlertDialog.Builder(this);
- builder.setTitle(R.string.permission_camera_alert_dialog_title);
- builder.setMessage(R.string.permission_camera_dialog_message);
- builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- dialog.dismiss();
- requestCameraPermission();
- }
- });
- builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- dialog.dismiss();
- }
- });
+ dialog.dismiss();
+ relayViaGoTenna = null;
- builder.show();
+ final String strHexTx = edHexTx.getText().toString().trim();
- }
+ Log.d("MainActivity", "hex:" + strHexTx);
- private void showRequestSMSPermissionInfoAlertDialog() {
+ doSendHex(strHexTx, null);
- AlertDialog.Builder builder = new AlertDialog.Builder(this);
- builder.setTitle(R.string.permission_sms_alert_dialog_title);
- builder.setMessage(R.string.permission_sms_dialog_message);
- builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- dialog.dismiss();
- requestSmsPermission();
- }
- });
- builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- dialog.dismiss();
- }
- });
+ }
+ }).setNegativeButton(R.string.scan, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int whichButton) {
- builder.show();
+ dialog.dismiss();
+ relayViaGoTenna = null;
- }
+ doScanHexTx();
+ }
+ });
- private boolean hasCameraPermission() {
- return ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED;
- }
+ dlg.show();
- private boolean hasReadSmsPermission() {
- return ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_SMS) == PackageManager.PERMISSION_GRANTED;
- }
+ }
- private boolean hasSendSmsPermission() {
- return ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.SEND_SMS) == PackageManager.PERMISSION_GRANTED;
- }
+ private void doScanHexTx() {
+ Intent intent = new Intent(MainActivity.this, ZBarScannerActivity.class);
+ intent.putExtra(ZBarConstants.SCAN_MODES, new int[]{ Symbol.QRCODE } );
+ startActivityForResult(intent, SCAN_HEX_TX);
+ }
- private void requestSmsPermission() {
+ private void showRequestCameraPermissionInfoAlertDialog() {
- if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, Manifest.permission.SEND_SMS) &&
- ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, Manifest.permission.READ_SMS)) {
- Log.d("MainActivity", "shouldShowRequestPermissionRationale(), no permission requested");
- return;
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle(R.string.permission_camera_alert_dialog_title);
+ builder.setMessage(R.string.permission_camera_dialog_message);
+ builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ dialog.dismiss();
+ requestCameraPermission();
}
+ });
+ builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ dialog.dismiss();
+ }
+ });
- ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.SEND_SMS, Manifest.permission.READ_SMS}, SMS_PERMISSION_CODE);
-
- }
+ builder.show();
- private void requestCameraPermission() {
+ }
- if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, Manifest.permission.CAMERA)
- ) {
- Log.d("MainActivity", "shouldShowRequestPermissionRationale(), no permission requested");
- return;
- }
+ private boolean hasCameraPermission() {
+ return ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED;
+ }
- ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CAMERA}, CAMERA_PERMISSION_CODE);
+ private void requestCameraPermission() {
+ if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, Manifest.permission.CAMERA)
+ ) {
+ Log.d("MainActivity", "shouldShowRequestPermissionRationale(), no permission requested");
+ return;
}
- private void doSendHex(final String hexTx, final NetworkParameters params) {
-
- // show transaction log after sending a transaction
- recyclerView.setVisibility(View.VISIBLE);
- emptyView.setVisibility(View.GONE);
-
- if(!hexTx.matches("^[A-Fa-f0-9]+$")) {
- return;
- }
+ ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CAMERA}, CAMERA_PERMISSION_CODE);
- Transaction tx = null;
- String msg = null;
- try {
- tx = new Transaction(PrefsUtil.getInstance(MainActivity.this).getValue(PrefsUtil.USE_MAINNET, true) == true ? MainNetParams.get() : TestNet3Params.get(), Hex.decode(hexTx));
- msg = MainActivity.this.getString(R.string.broadcast) + ":" + tx.getHashAsString() + " " + getText(R.string.to) + " " + PrefsUtil.getInstance(MainActivity.this).getValue(PrefsUtil.SMS_RELAY, MainActivity.this.getText(R.string.default_relay).toString()) + " ?";
- Log.d("MainActivity", "hash:" + tx.getHashAsString());
- tx.verify();
- }
- catch(VerificationException ve) {
- Log.d("MainActivity", "Invalid transaction, hash:" + tx.getHashAsString());
- Toast.makeText(MainActivity.this, R.string.invalid_tx, Toast.LENGTH_SHORT).show();
- return;
- }
+ }
- final TextView tvHexTx = new TextView(MainActivity.this);
- tvHexTx.setSingleLine(false);
- tvHexTx.setLines(10);
- tvHexTx.setGravity(Gravity.START);
- tvHexTx.setText(hexTx);
+ private void doSendHex(final String hexTx, final NetworkParameters params) {
- AlertDialog.Builder dlg = new AlertDialog.Builder(MainActivity.this)
- .setTitle(R.string.app_name)
- .setMessage(msg)
- .setCancelable(true);
+ // show transaction log after sending a transaction
+ recyclerView.setVisibility(View.VISIBLE);
+ emptyView.setVisibility(View.GONE);
- if(relayViaGoTenna != null) {
- dlg.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int whichButton) {
+ if(!hexTx.matches("^[A-Fa-f0-9]+$")) {
+ return;
+ }
- dialog.dismiss();
+ Transaction tx = null;
+ String msg = null;
+ try {
+ tx = new Transaction(PrefsUtil.getInstance(MainActivity.this).getValue(PrefsUtil.USE_MAINNET, true) == true ? MainNetParams.get() : TestNet3Params.get(), Hex.decode(hexTx));
+ Log.d("MainActivity", "hash:" + tx.getHashAsString());
+ tx.verify();
+ }
+ catch(VerificationException ve) {
+ Log.d("MainActivity", "Invalid transaction, hash:" + tx.getHashAsString());
+ Toast.makeText(MainActivity.this, R.string.invalid_tx, Toast.LENGTH_SHORT).show();
+ return;
+ }
- List payload = PayloadFactory.toJSON(hexTx, relayViaGoTenna, params);
- PayloadFactory.getInstance(MainActivity.this, transactionHandler).relayPayload(payload, relayViaGoTenna);
- relayViaGoTenna = null;
- }
+ final TextView tvHexTx = new TextView(MainActivity.this);
+ tvHexTx.setSingleLine(false);
+ tvHexTx.setLines(10);
+ tvHexTx.setGravity(Gravity.START);
+ tvHexTx.setText(hexTx);
- });
- dlg.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int whichButton) {
+ AlertDialog.Builder dlg = new AlertDialog.Builder(MainActivity.this)
+ .setTitle(R.string.app_name)
+ .setMessage(msg)
+ .setCancelable(true);
- dialog.dismiss();
- relayViaGoTenna = null;
+ if(relayViaGoTenna != null) {
+ dlg.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int whichButton) {
- }
- });
- }
- else {
- dlg.setPositiveButton(R.string.gotenna_mesh, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int whichButton) {
+ dialog.dismiss();
- dialog.dismiss();
+ List payload = PayloadFactory.toJSON(hexTx, relayViaGoTenna, params);
+ PayloadFactory.getInstance(MainActivity.this, transactionHandler).relayPayload(payload, relayViaGoTenna);
+ relayViaGoTenna = null;
+ }
- List payload = PayloadFactory.toJSON(hexTx, true, params);
- PayloadFactory.getInstance(MainActivity.this, transactionHandler).relayPayload(payload, true);
- relayViaGoTenna = null;
+ });
+ dlg.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int whichButton) {
- }
+ dialog.dismiss();
+ relayViaGoTenna = null;
- });
- dlg.setNeutralButton(R.string.cancel, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int whichButton) {
+ }
+ });
+ }
+ else {
+ dlg.setPositiveButton(R.string.gotenna_mesh, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int whichButton) {
- dialog.dismiss();
- relayViaGoTenna = null;
+ dialog.dismiss();
- }
+ List payload = PayloadFactory.toJSON(hexTx, true, params);
+ PayloadFactory.getInstance(MainActivity.this, transactionHandler).relayPayload(payload, true);
+ relayViaGoTenna = null;
- });
- dlg.setNegativeButton(R.string.sms_broadcast, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int whichButton) {
+ }
- dialog.dismiss();
+ });
+ dlg.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int whichButton) {
- List payload = PayloadFactory.toJSON(hexTx, false, params);
- PayloadFactory.getInstance(MainActivity.this, transactionHandler).relayPayload(payload, false);
- relayViaGoTenna = null;
- }
- });
- }
+ dialog.dismiss();
+ relayViaGoTenna = null;
- dlg.show();
+ }
+ });
}
- public void onIncomingMessage(Message incomingMessage) {
+ dlg.show();
+ }
- // show transaction log after receiving an incoming message
- recyclerView.setVisibility(View.VISIBLE);
- emptyView.setVisibility(View.GONE);
+ public void onIncomingMessage(Message incomingMessage) {
- try {
- JSONObject obj = new JSONObject(incomingMessage.getText());
- if(obj.has("i")) {
- String id = obj.getString("i");
- int idx = 0;
- if (obj.has("c")) {
- idx = obj.getInt("c");
- }
+ // show transaction log after receiving an incoming message
+ recyclerView.setVisibility(View.VISIBLE);
+ emptyView.setVisibility(View.GONE);
- if (!SentTxUtil.getInstance().contains(id, idx)) {
- // handle upload of segment to server
- // if(ConnectivityStatus.hasConnectivity(this)) {
- PayloadFactory.getInstance(this, transactionHandler).broadcastPayload(obj.toString(), incomingMessage.getSenderGID());
- // }
- // else {
- // rebroadcast
- // }
- }
+ try {
+ JSONObject obj = new JSONObject(incomingMessage.getText());
+ if(obj.has("i")) {
+ String id = obj.getString("i");
+ int idx = 0;
+ if (obj.has("c")) {
+ idx = obj.getInt("c");
}
- else if (obj.has("b") && incomingMessage.getReceiverGID() == goTennaUtil.getGID()) {
- // handle return receipt message
- transactionHandler.confirmFromGateway(incomingMessage.getText());
+
+ if (!SentTxUtil.getInstance().contains(id, idx)) {
+ // handle upload of segment to server
+ // if(ConnectivityStatus.hasConnectivity(this)) {
+ PayloadFactory.getInstance(this, transactionHandler).broadcastPayload(obj.toString(), incomingMessage.getSenderGID());
+ // }
+ // else {
+ // rebroadcast
+ // }
}
}
- catch(JSONException je) {
- ;
+ else if (obj.has("b") && incomingMessage.getReceiverGID() == goTennaUtil.getGID()) {
+ if (transactionHandler == null) {
+ Log.d("MainActivity", "onIncomingMessage, transactionHandler is null!! " + Integer.toHexString(this.hashCode()) + " [lifecycle]");
+ }
+ // handle return receipt message
+ transactionHandler.confirmFromGateway(incomingMessage.getText());
}
}
+ catch(JSONException je) {
+ Log.d("MainActivity", "onIncomingMessage, JSONException = " + je);
+ }
}
+}
diff --git a/app/src/main/java/com/samourai/txtenna/NetworkingActivity.java b/app/src/main/java/com/samourai/txtenna/NetworkingActivity.java
index b0047ba..b45a95e 100644
--- a/app/src/main/java/com/samourai/txtenna/NetworkingActivity.java
+++ b/app/src/main/java/com/samourai/txtenna/NetworkingActivity.java
@@ -43,6 +43,7 @@ public class NetworkingActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+
setContentView(R.layout.activity_networking);
ConstraintGroup = findViewById(R.id.mesh_card_group);
mesh_card_detail = findViewById(R.id.mesh_card_detail);
@@ -76,7 +77,7 @@ public void onClick(View view) {
btPair.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
- if(GoTenna.tokenIsVerified()) {
+ if(goTennaUtil.tokenIsVerified()) {
if (!hasBluetoothPermisson()) {
requestBluetoothPermission();
}
@@ -123,12 +124,14 @@ public void onClick(View view) {
}
});
- Log.d("NetworkActivity", "gtConnectionState:" + goTennaUtil.getInstance(NetworkingActivity.this).getGtConnectionManager().getGtConnectionState());
- Log.d("NetworkActivity", "connected address:" + goTennaUtil.getInstance(NetworkingActivity.this).getGtConnectionManager().getConnectedGotennaAddress());
+ if (goTennaUtil.tokenIsVerified()) {
+ Log.d("NetworkActivity", "gtConnectionState:" + goTennaUtil.getInstance(NetworkingActivity.this).getGtConnectionManager().getGtConnectionState());
+ Log.d("NetworkActivity", "connected address:" + goTennaUtil.getInstance(NetworkingActivity.this).getGtConnectionManager().getConnectedGotennaAddress());
+ }
}
public void setStatusText(boolean isPaired, boolean isScanning) {
- String deviceName = goTennaUtil.getInstance(NetworkingActivity.this).getGtConnectionManager().getConnectedGotennaAddress();
+ String deviceName = goTennaUtil.tokenIsVerified() ? goTennaUtil.getInstance(NetworkingActivity.this).getGtConnectionManager().getConnectedGotennaAddress() : null;
int pairText = R.string.scan;
if(isPaired && deviceName != null) {
mesh_card_detail.setText(getText(R.string.mesh_device_detected) + ": " + deviceName);
diff --git a/app/src/main/java/com/samourai/txtenna/SettingsActivity.java b/app/src/main/java/com/samourai/txtenna/SettingsActivity.java
index fdded50..bd46390 100644
--- a/app/src/main/java/com/samourai/txtenna/SettingsActivity.java
+++ b/app/src/main/java/com/samourai/txtenna/SettingsActivity.java
@@ -35,6 +35,7 @@
public class SettingsActivity extends PreferenceActivity {
private static final String regex_url = "^(https?)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]";
+ private static final String regex_token = "[a-zA-Z0-9]{64}";
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -134,6 +135,22 @@ public boolean onPreferenceClick(Preference preference) {
}
});
+ final EditTextPreference tokenPref = (EditTextPreference) findPreference("token");
+ tokenPref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ String token = newValue.toString();
+ if (token != null && token.length() > 0) {
+ if (token.matches(regex_token)) {
+ PrefsUtil.getInstance(SettingsActivity.this).setValue(PrefsUtil.GOTENNA_TOKEN, token);
+ }
+ else {
+ Toast.makeText(SettingsActivity.this, R.string.invalid_token, Toast.LENGTH_SHORT).show();
+ }
+ }
+ return true;
+ }
+ });
+
Preference clearLogsPref = (Preference) findPreference("clearlogs");
clearLogsPref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
public boolean onPreferenceClick(Preference preference) {
diff --git a/app/src/main/java/com/samourai/txtenna/payload/PayloadFactory.java b/app/src/main/java/com/samourai/txtenna/payload/PayloadFactory.java
index ca98155..f47b130 100644
--- a/app/src/main/java/com/samourai/txtenna/payload/PayloadFactory.java
+++ b/app/src/main/java/com/samourai/txtenna/payload/PayloadFactory.java
@@ -10,7 +10,6 @@
import com.google.gson.GsonBuilder;
import com.gotenna.sdk.gids.GIDManager;
-import com.samourai.sms.SMSSender;
import com.samourai.txtenna.utils.Message;
import com.samourai.txtenna.R;
import com.samourai.txtenna.utils.SendMessageInteractor;
@@ -365,14 +364,6 @@ public void onMessageResponseReceived()
Log.d("PayloadFactory", "goTenna relayed: " + s + " gid: " + gid);
}
- else {
- SMSSender.getInstance(context).send(s, PrefsUtil.getInstance(context).getValue(PrefsUtil.SMS_RELAY, context.getString(R.string.default_relay)));
- Log.d("PayloadFactory", "sms relayed:" + s);
-
- // add messages that were relayed over the SMS network to the broadcast log
- BroadcastLogUtil.getInstance().add(payload.get(0), true, true, false, 0);
- transactionHandler.refresh();
- }
handler.post(new Runnable() {
@Override
diff --git a/app/src/main/java/com/samourai/txtenna/prefs/PrefsUtil.java b/app/src/main/java/com/samourai/txtenna/prefs/PrefsUtil.java
index 40f2f2a..d52c227 100644
--- a/app/src/main/java/com/samourai/txtenna/prefs/PrefsUtil.java
+++ b/app/src/main/java/com/samourai/txtenna/prefs/PrefsUtil.java
@@ -13,7 +13,7 @@ public class PrefsUtil {
public static final String USE_Z85 = "z85";
public static final String MESSAGE_IDX = "msgIdx";
public static final String REGION = "region";
-
+ public static final String GOTENNA_TOKEN = "token";
public static final String GOTENNA_UID = "goTennaID";
private static Context context = null;
diff --git a/app/src/main/java/com/samourai/txtenna/utils/BroadcastLogUtil.java b/app/src/main/java/com/samourai/txtenna/utils/BroadcastLogUtil.java
index 1e8c2c3..4827b15 100644
--- a/app/src/main/java/com/samourai/txtenna/utils/BroadcastLogUtil.java
+++ b/app/src/main/java/com/samourai/txtenna/utils/BroadcastLogUtil.java
@@ -10,9 +10,12 @@
import org.json.JSONException;
import org.json.JSONObject;
+import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
+import static java.lang.StrictMath.abs;
+
public class BroadcastLogUtil {
public class BroadcastLogEntry {
@@ -152,4 +155,19 @@ public int findTransaction(String txid) {
}
return -1;
}
+
+ // return GID from last unconfirmed broadcast transaction, otherwise a new random GID
+ public long lastGID() {
+
+ // set new random GID every time we connect to a goTenna device
+ long gid = abs(new SecureRandom().nextLong()) % 9999999999L;
+
+ for (BroadcastLogEntry entry : broadcastLog) {
+ // use gid from last unconfirmed transaction
+ if (entry.confirmed == false) {
+ gid = entry.gid;
+ }
+ }
+ return gid;
+ }
}
diff --git a/app/src/main/java/com/samourai/txtenna/utils/IncomingMessagesManager.java b/app/src/main/java/com/samourai/txtenna/utils/IncomingMessagesManager.java
index cda7379..8562f39 100644
--- a/app/src/main/java/com/samourai/txtenna/utils/IncomingMessagesManager.java
+++ b/app/src/main/java/com/samourai/txtenna/utils/IncomingMessagesManager.java
@@ -74,8 +74,14 @@ public void addIncomingMessageListener(IncomingMessageListener incomingMessageLi
if (incomingMessageListener != null)
{
incomingMessageListeners.remove(incomingMessageListener);
+ if (incomingMessageListeners.size() > 0) {
+ Log.d("IncomingMessagesManager", "addIncomingMessageListener, NOT empty " + Integer.toHexString(this.hashCode()) + " [lifecycle]");
+ }
incomingMessageListeners.add(incomingMessageListener);
}
+ else {
+ Log.d("IncomingMessagesManager", "addIncomingMessageListener, incomingMessageListener == null " + Integer.toHexString(this.hashCode()) + " [lifecycle]");
+ }
}
}
@@ -87,6 +93,12 @@ public void removeIncomingMessageListener(IncomingMessageListener incomingMessag
{
incomingMessageListeners.remove(incomingMessageListener);
}
+ else {
+ Log.d("IncomingMessagesManager", "removeIncomingMessageListener, incomingMessageListener == null " + Integer.toHexString(this.hashCode()) + " [lifecycle]");
+ }
+ if (incomingMessageListeners.size() > 0) {
+ Log.d("IncomingMessagesManager", "removeIncomingMessageListener, NOT empty " + Integer.toHexString(this.hashCode()) + " [lifecycle]");
+ }
}
}
diff --git a/app/src/main/java/com/samourai/txtenna/utils/TransactionHandler.java b/app/src/main/java/com/samourai/txtenna/utils/TransactionHandler.java
index 189c605..2835dbc 100644
--- a/app/src/main/java/com/samourai/txtenna/utils/TransactionHandler.java
+++ b/app/src/main/java/com/samourai/txtenna/utils/TransactionHandler.java
@@ -11,6 +11,7 @@
import org.json.JSONObject;
import java.io.IOException;
+import java.net.UnknownHostException;
import ch.boye.httpclientandroidlib.HttpResponse;
import ch.boye.httpclientandroidlib.client.HttpClient;
@@ -28,13 +29,13 @@ public class TransactionHandler extends HandlerThread {
public TransactionHandler(String name, BroadcastLogsAdapter adapter) {
super(name);
this.adapter = adapter;
+ Log.d("TransactionHandler", "create object: " + Integer.toHexString(this.hashCode()) + " [lifecycle]");
}
public synchronized void refresh() {
try {
android.os.Message message = new android.os.Message();
message.arg1 = 0;
- waitUntilReady();
this.handler.sendMessage(message);
}
catch (Exception e) {
@@ -47,7 +48,6 @@ public synchronized void confirmFromGateway(String segment) {
android.os.Message message = new android.os.Message();
message.arg1 = 1;
message.obj = segment;
- waitUntilReady();
this.handler.sendMessage(message);
}
catch (Exception e) {
@@ -82,7 +82,7 @@ public void handleMessage(android.os.Message msg) {
if (pos > -1) {
BroadcastLogUtil.BroadcastLogEntry entry = BroadcastLogUtil.getInstance().getBroadcastLog().get(pos);
entry.broadcast = true;
- if (blockHeight > 1) {
+ if (blockHeight >= 1) {
entry.confirmed = true;
}
adapter.notifyDataSetChanged();
@@ -101,10 +101,10 @@ public void handleMessage(android.os.Message msg) {
notify();
}
- public synchronized void waitUntilReady() throws InterruptedException {
- while (this.handler == null) {
- wait();
- }
+ @Override
+ protected void finalize () throws Throwable {
+ super.finalize();
+ Log.d("TransactionHandler", "finalize object: @" + Integer.toHexString(this.hashCode()) + " [lifecycle]");
}
Runnable transactionChecker = new Runnable() {
@@ -122,7 +122,6 @@ public void run() {
public void startTransactionChecker() {
try {
- waitUntilReady();
transactionChecker.run();
}
catch (Exception e) {
@@ -132,7 +131,6 @@ public void startTransactionChecker() {
public void stopTransactionChecker() {
try {
- waitUntilReady();
this.handler.removeCallbacks(transactionChecker);
}
catch (Exception e) {
@@ -227,6 +225,9 @@ public void onMessageResponseReceived() {
refresh();
}
}
+ catch(UnknownHostException e) {
+ Log.d("TransactionHandler", "No Internet Connection. " + e);
+ }
catch(IOException e) {
Log.d("TransactionHandler", e.getMessage());
e.printStackTrace();
diff --git a/app/src/main/java/com/samourai/txtenna/utils/goTennaUtil.java b/app/src/main/java/com/samourai/txtenna/utils/goTennaUtil.java
index 8c40324..85af1fc 100644
--- a/app/src/main/java/com/samourai/txtenna/utils/goTennaUtil.java
+++ b/app/src/main/java/com/samourai/txtenna/utils/goTennaUtil.java
@@ -23,6 +23,7 @@
import com.samourai.txtenna.NetworkingActivity;
import com.gotenna.sdk.bluetooth.GTConnectionManager.GTDeviceType;
import com.gotenna.sdk.bluetooth.GTConnectionManager.GTConnectionListener;
+import com.samourai.txtenna.prefs.PrefsUtil;
import java.security.SecureRandom;
import java.util.UUID;
@@ -57,26 +58,39 @@ public static goTennaUtil getInstance(Context ctx) {
return instance;
}
+ public static boolean tokenIsVerified() {
+ goTennaUtil gt = getInstance(null);
+ return (gt != null && gt.getGtConnectionManager() != null && GoTenna.tokenIsVerified());
+ }
+
public String getAppToken() {
- return GOTENNA_APP_TOKEN;
+ String token = PrefsUtil.getInstance(context.getApplicationContext()).getValue(PrefsUtil.GOTENNA_TOKEN, "");
+ if (token == "") {
+ return GOTENNA_APP_TOKEN;
+ }
+ return token;
}
public boolean isPaired() {
- if(getGtConnectionManager().getGtConnectionState() == GTConnectionState.CONNECTED) {
+ if(tokenIsVerified() && getGtConnectionManager().getGtConnectionState() == GTConnectionState.CONNECTED) {
return true;
}
return false;
}
public String GetHardwareAddress() {
- return getGtConnectionManager().getConnectedGotennaAddress();
+ if (tokenIsVerified()) {
+ return getGtConnectionManager().getConnectedGotennaAddress();
+ }
+ else {
+ return "";
+ }
}
public void init() throws StringIndexOutOfBoundsException, GTInvalidAppTokenException {
-
GoTenna.setApplicationToken(context.getApplicationContext(), goTennaUtil.getInstance(context).getAppToken());
- if(GoTenna.tokenIsVerified()) {
+ if (GoTenna.tokenIsVerified()) {
gtConnectionManager = GTConnectionManager.getInstance();
Log.d("goTennaUtil", "goTenna token is verified:" + GoTenna.tokenIsVerified());
Log.d("goTennaUtil", "connected address:" + gtConnectionManager.getConnectedGotennaAddress());
@@ -84,8 +98,8 @@ public void init() throws StringIndexOutOfBoundsException, GTInvalidAppTokenExce
handler = new Handler(Looper.getMainLooper()) {
@Override
- public void handleMessage(Message msg){
- if(msg.what == 0 && callbackActivity != null) {
+ public void handleMessage(Message msg) {
+ if (msg.what == 0 && callbackActivity != null) {
// no connection, scanning timed out
callbackActivity.setStatusText(false, false);
}
@@ -158,16 +172,18 @@ public void onError(GTError error) {
}
public static void setGID(long gid) {
- GTCommandCenter.getInstance().setGoTennaGID(gid, UUID.randomUUID().toString(), new GTErrorListener() {
- @Override
- public void onError(GTError error) {
- User gtUser = UserDataStore.getInstance().getCurrentUser();
- Log.d("goTennaUtil", error.toString() + "," + error.getCode() + " gid: " + gtUser.getGID());
- }
- });
+ if (tokenIsVerified()) {
+ GTCommandCenter.getInstance().setGoTennaGID(gid, UUID.randomUUID().toString(), new GTErrorListener() {
+ @Override
+ public void onError(GTError error) {
+ User gtUser = UserDataStore.getInstance().getCurrentUser();
+ Log.d("goTennaUtil", error.toString() + "," + error.getCode() + " gid: " + gtUser.getGID());
+ }
+ });
- User gtUser = UserDataStore.getInstance().getCurrentUser();
- Log.d("goTennaUtil", "gtUser.getGID: " + gtUser.getGID());
+ User gtUser = UserDataStore.getInstance().getCurrentUser();
+ Log.d("goTennaUtil", "gtUser.getGID: " + gtUser.getGID());
+ }
}
public static long getGID() {
@@ -185,15 +201,17 @@ public void connect(NetworkingActivity activity, int region) {
long gid = abs(new SecureRandom().nextLong()) % 9999999999L;
setGID(gid);
- callbackActivity = activity;
- regionIndex = region;
- gtConnectionManager.addGtConnectionListener(this);
- gtConnectionManager.scanAndConnect(GTDeviceType.MESH);
- handler.postDelayed(scanTimeoutRunnable, SCAN_TIMEOUT);
+ if (tokenIsVerified()) {
+ callbackActivity = activity;
+ regionIndex = region;
+ gtConnectionManager.addGtConnectionListener(this);
+ gtConnectionManager.scanAndConnect(GTDeviceType.MESH);
+ handler.postDelayed(scanTimeoutRunnable, SCAN_TIMEOUT);
+ }
}
public void sendEchoCommand() {
- if(GTConnectionManager.getInstance().isConnected())
+ if(tokenIsVerified() && GTConnectionManager.getInstance().isConnected())
{
GTCommandCenter.getInstance().sendEchoCommand(null, null);
}
diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml
index ad325f0..61bbb48 100644
--- a/app/src/main/res/values-fr/strings.xml
+++ b/app/src/main/res/values-fr/strings.xml
@@ -31,6 +31,8 @@
Économiser de l\'espace en encodant les octets de transaction en Z85
Région géographique
Sélectionner la région géographique où se situe votre GoTenna.
+ goTenna Jeton
+ Entrez votre jeton personnel goTenna ou laissez le champ vide pour le jeton par défaut.
Supprimer contenus journal
Supprimer contenus journal émis.
Utiliser le format d\'appel international. Ex.:\'+447385555555\'
@@ -39,6 +41,8 @@
https://api.samouraiwallet.com/test/v2/pushtx/
https://api.samouraiwallet.com/v2/txtenna/segments
URL invalide
+ Votre jeton SDK n\'est pas valide.
+ Veuillez obtenir un jeton valide auprès de goTenna.
MuleTools
Scanner QR
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index d5b51cf..9b5ac7f 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -31,6 +31,8 @@
Save space by encoding transaction bytes in Z85
Geographical region
Select geographical region where your goTenna is located.
+ goTenna Token
+ Enter your personal goTenna token, or leave blank for default token.
Clear logs
Clear broadcast logs.
Use international dialing format. Ex.:\'+447385555555\'
@@ -85,7 +87,8 @@
Scanning
Are you sure you want to clear the broadcast logs?
- Your SDK token is invalid. Please obtain a valid token from goTenna.
+ Your SDK token is invalid.
+ Please obtain a valid token from goTenna.
Scanning for goTenna Mesh device. Please wait.
diff --git a/app/src/main/res/xml/settings.xml b/app/src/main/res/xml/settings.xml
index 7eca7d7..c1da218 100644
--- a/app/src/main/res/xml/settings.xml
+++ b/app/src/main/res/xml/settings.xml
@@ -42,16 +42,31 @@
android:key="region"
/>
-
+
+
-
+
+
+
+