-Fix code Migration of kotlin:

annotationProcessor  to kapt
-In screen IntroActivity: Show toast when there is not connection with server
-In screen Create Seed: Code to interface when error ocurs in WebSocketThread and GrapheneApiGenerator
-Fixes to class WebSocketThread for error Report to user
-Fixes to class BitsharesCryptoNetVerifier for error Report to user
-Fixes to class CryptoNetVerifier for error Report to user
-Fixes to class CryptoNetManager for error Report to user
-In the IntroScreen: If there is not server connection show a simple user message of that
-Create class ToastIt in kotlin
-Create class NetworkUtility in kotlin
-In the IntroScreen: When the user Press button “create account” it has to validate connection to server to continue
-In the IntroScreen: When the user Press button “Import account” it has to validate connection to server to continue
master
dtvv 2018-08-15 17:36:20 -05:00
parent da8eda93b5
commit f9995bf284
9 changed files with 349 additions and 40 deletions

View File

@ -12,6 +12,7 @@ import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import java.util.List;
@ -19,23 +20,29 @@ import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import cy.agorise.crystalwallet.R;
import cy.agorise.crystalwallet.apigenerator.GrapheneApiGenerator;
import cy.agorise.crystalwallet.application.CrystalApplication;
import cy.agorise.crystalwallet.dao.CrystalDatabase;
import cy.agorise.crystalwallet.dialogs.material.ToastIt;
import cy.agorise.crystalwallet.enums.CryptoNet;
import cy.agorise.crystalwallet.fragments.ImportAccountOptionsFragment;
import cy.agorise.crystalwallet.models.AccountSeed;
import cy.agorise.crystalwallet.models.CryptoCoinBalance;
import cy.agorise.crystalwallet.models.CryptoCoinTransaction;
import cy.agorise.crystalwallet.models.CryptoNetAccount;
import cy.agorise.crystalwallet.models.GeneralSetting;
import cy.agorise.crystalwallet.network.CryptoNetManager;
import cy.agorise.crystalwallet.randomdatagenerators.RandomCryptoCoinBalanceGenerator;
import cy.agorise.crystalwallet.randomdatagenerators.RandomCryptoNetAccountGenerator;
import cy.agorise.crystalwallet.randomdatagenerators.RandomSeedGenerator;
import cy.agorise.crystalwallet.randomdatagenerators.RandomTransactionsGenerator;
import cy.agorise.crystalwallet.application.CrystalSecurityMonitor;
import cy.agorise.crystalwallet.util.NetworkUtility;
import cy.agorise.crystalwallet.viewmodels.AccountSeedListViewModel;
import cy.agorise.crystalwallet.viewmodels.TransactionListViewModel;
import cy.agorise.crystalwallet.views.TransactionListView;
public class IntroActivity extends AppCompatActivity {
public class IntroActivity extends CustomActivity {
TransactionListViewModel transactionListViewModel;
TransactionListView transactionListView;
@ -53,8 +60,16 @@ public class IntroActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_intro);
ButterKnife.bind(this);
/*
* Test connection with server
* */
NetworkUtility.testServerConnnection(this);
// Appbar animation
mSurfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
@Override
@ -136,21 +151,56 @@ public class IntroActivity extends AppCompatActivity {
@OnClick(R.id.btnCreateAccount)
public void createAccount() {
Intent intent = new Intent(this, CreateSeedActivity.class);
startActivity(intent);
/*
* Test connection with server, if no conection user can not continue
*
* */
final GrapheneApiGenerator.OnResponsesWebSocket onResponsesWebSocket = new GrapheneApiGenerator.OnResponsesWebSocket() {
@Override
public void onSuccess() {
/*
* Open the window to create seed and account
* */
Intent intent = new Intent(globalActivity, CreateSeedActivity.class);
startActivity(intent);
}
@Override
public void onError(Exception exception) {
//Nothing to implement, internally the user will see a toast
}
};
NetworkUtility.testServerConnnectionNormalError(this,onResponsesWebSocket);
}
@OnClick(R.id.btnImportAccount)
public void importAccount() {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
Fragment prev = getSupportFragmentManager().findFragmentByTag("importAccountOptions");
if (prev != null) {
ft.remove(prev);
}
ft.addToBackStack(null);
// Create and show the dialog.
ImportAccountOptionsFragment newFragment = ImportAccountOptionsFragment.newInstance();
newFragment.show(ft, "importAccountOptions");
/*
* Test connection with server, if no conection user can not continue
*
* */
final GrapheneApiGenerator.OnResponsesWebSocket onResponsesWebSocket = new GrapheneApiGenerator.OnResponsesWebSocket() {
@Override
public void onSuccess() {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
Fragment prev = getSupportFragmentManager().findFragmentByTag("importAccountOptions");
if (prev != null) {
ft.remove(prev);
}
ft.addToBackStack(null);
// Create and show the dialog.
ImportAccountOptionsFragment newFragment = ImportAccountOptionsFragment.newInstance();
newFragment.show(ft, "importAccountOptions");
}
@Override
public void onError(Exception exception) {
//Nothing to implement, internally the user will see a toast
}
};
NetworkUtility.testServerConnnectionNormalError(this,onResponsesWebSocket);
}
}

View File

@ -10,8 +10,11 @@ import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import cy.agorise.crystalwallet.R;
import cy.agorise.crystalwallet.application.CrystalApplication;
import cy.agorise.crystalwallet.dao.CrystalDatabase;
import cy.agorise.crystalwallet.enums.CryptoNet;
import cy.agorise.crystalwallet.models.GeneralSetting;
import cy.agorise.crystalwallet.network.CryptoNetManager;
public class LicenseActivity extends AppCompatActivity {
@ -23,6 +26,7 @@ public class LicenseActivity extends AppCompatActivity {
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_license);
ButterKnife.bind(this);
// TODO check if license has been agreed

View File

@ -1,5 +1,6 @@
package cy.agorise.crystalwallet.apigenerator;
import android.app.Activity;
import android.content.Context;
import java.io.Serializable;
@ -81,6 +82,30 @@ public abstract class GrapheneApiGenerator {
*/
private static HashMap<Long, SubscriptionListener> currentBitsharesListener = new HashMap<>();
/*
*
* To present erros to user
* */
private static Activity activity;
/*
*
* Interface to catch only errors in connection with sockets
* */
private static GrapheneApiGenerator.OnErrorWebSocker onErrorWebSocker;
/*
*
* Interface to catch both errors and success in connection with sockets
* */
private static OnResponsesWebSocket onResponsesWebSocker;
/**
* Retrieves the data of an account searching by it's id
*
@ -221,6 +246,8 @@ public abstract class GrapheneApiGenerator {
request.getListener().fail(request.getId());
}
}), CryptoNetManager.getURL(CryptoNet.BITSHARES));
thread.setActivity(activity); //To catch websocket errors to user interface
thread.setOnErrorWebSocker(onErrorWebSocker); //To deliver websocket errors to user interface
thread.start();
}
@ -703,4 +730,35 @@ public abstract class GrapheneApiGenerator {
}
}
public static void setActivity(Activity activity) {
GrapheneApiGenerator.activity = activity;
}
public static void setOnResponsesWebSocker(OnResponsesWebSocket onResponsesWebSocker) {
GrapheneApiGenerator.onResponsesWebSocker = onResponsesWebSocker;
}
public static void setOnErrorWebSocker(OnErrorWebSocker onErrorWebSocker) {
GrapheneApiGenerator.onErrorWebSocker = onErrorWebSocker;
}
/*
*
* Interface to catch errors in connection with sockets
* */
public interface OnErrorWebSocker{
void onError(Exception exception);
}
/*
*
* Interface to catch succesfully connection with sockets
* */
public interface OnResponsesWebSocket {
void onSuccess();
void onError(Exception exception);
}
}

View File

@ -1,5 +1,6 @@
package cy.agorise.crystalwallet.application;
import android.app.Activity;
import android.app.Application;
import android.content.Intent;
import android.content.res.Configuration;
@ -11,6 +12,7 @@ import com.idescout.sql.SqlScoutServer;
import java.util.Locale;
import cy.agorise.crystalwallet.R;
import cy.agorise.crystalwallet.apigenerator.GrapheneApiGenerator;
import cy.agorise.crystalwallet.dao.CrystalDatabase;
import cy.agorise.crystalwallet.enums.CryptoNet;
import cy.agorise.crystalwallet.models.BitsharesAsset;
@ -60,7 +62,7 @@ public class CrystalApplication extends Application {
SqlScoutServer.create(this, getPackageName());
//Using Bitshares Agorise Testnet
CryptoNetManager.addCryptoNetURL(CryptoNet.BITSHARES,BITSHARES_TESTNET_URL);
//CryptoNetManager.addCryptoNetURL(CryptoNet.BITSHARES,BITSHARES_TESTNET_URL);
//This is for testing the equivalent values on the testnet TODO remove
if(db.bitsharesAssetDao().getBitsharesAssetInfoById(bitEURAsset.getBitsharesId())== null){

View File

@ -1,5 +1,6 @@
package cy.agorise.crystalwallet.network;
import cy.agorise.crystalwallet.apigenerator.GrapheneApiGenerator;
import cy.agorise.crystalwallet.enums.CryptoNet;
import cy.agorise.graphenej.interfaces.WitnessResponseListener;
import cy.agorise.graphenej.models.BaseResponse;
@ -23,15 +24,21 @@ public class BitsharesCryptoNetVerifier extends CryptoNetVerifier {
private final String CHAIN_ID = "9cf6f255a208100d2bb275a3c52f4b1589b7ec9c9bfc2cb2a5fe6411295106d8";//testnet
//private final String CHAIN_ID = "4018d7844c78f6a6c41c6a552b898022310fc5dec06da467ee7905a8dad512c8";//mainnet
@Override
public void checkURL(final String url) {
public BitsharesCryptoNetVerifier(){
/**/
final long startTime = System.currentTimeMillis();
WebSocketThread thread = new WebSocketThread(new GetChainId(new WitnessResponseListener() {
thread = new WebSocketThread(new GetChainId(new WitnessResponseListener() {
@Override
public void onSuccess(WitnessResponse response) {
if(response.result instanceof String) {
if(response.result.equals(CHAIN_ID)) {
CryptoNetManager.verifiedCryptoNetURL(cryptoNet, url, System.currentTimeMillis() - startTime);
CryptoNetManager.verifiedCryptoNetURL(cryptoNet, null, System.currentTimeMillis() - startTime);
}else{
System.out.println(" BitsharesCryptoNetVerifier Error we are not in the net current chain id " + response.result + " excepted " + CHAIN_ID);
//TODO handle error bad chain
@ -43,8 +50,15 @@ public class BitsharesCryptoNetVerifier extends CryptoNetVerifier {
public void onError(BaseResponse.Error error) {
//TODO handle error
}
}),url);
thread.start();
}),null);
}
@Override
public void checkURL(final String url) {
thread.setmUrl(url); //Set the url
thread.start(); //Run the thread connection
}
@Override

View File

@ -1,5 +1,6 @@
package cy.agorise.crystalwallet.network;
import android.app.Activity;
import android.support.annotation.NonNull;
import android.util.Log;
@ -9,6 +10,7 @@ import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import cy.agorise.crystalwallet.apigenerator.GrapheneApiGenerator;
import cy.agorise.crystalwallet.enums.CryptoNet;
/**
@ -61,20 +63,63 @@ public abstract class CryptoNetManager {
}
}
public static void addCryptoNetURL(CryptoNet crypto, String[] urls){
if(!CryptoNetURLs.containsKey(crypto)){
CryptoNetURLs.put(crypto,new HashSet<String>());
}
CryptoNetVerifier verifier = CryptoNetVerifier.getNetworkVerify(crypto);
for(String url : urls) {
/*
* Add url with listener on error only for sockets
* */
public static void addCryptoNetURL(CryptoNet crypto,
String[] urls,
final Activity activity,
final GrapheneApiGenerator.OnErrorWebSocker onErrorWebSocker,
final boolean showNormalError){
addCryptoNetURL(crypto,urls,activity,onErrorWebSocker,null,showNormalError);
}
/*
* Add url with listener on error and response for sockets
* */
public static void addCryptoNetURL(CryptoNet crypto,
String[] urls,
final Activity activity,
final GrapheneApiGenerator.OnResponsesWebSocket onResponsesWebSocket,
final boolean showNormalError){
addCryptoNetURL(crypto,urls,activity,null,onResponsesWebSocket,showNormalError);
}
/*
* Utility for above methods
*
* */
public static void addCryptoNetURL(CryptoNet crypto,
String[] urls,
final Activity activity,
final GrapheneApiGenerator.OnErrorWebSocker onErrorWebSocker,
final GrapheneApiGenerator.OnResponsesWebSocket onResponsesWebSocket,
final boolean showNormalError) {
if (!CryptoNetURLs.containsKey(crypto)) {
CryptoNetURLs.put(crypto, new HashSet<String>());
}
CryptoNetVerifier verifier = CryptoNetVerifier.getNetworkVerify(crypto);
verifier.getThread().setActivity(activity); //Logical connection to ui
verifier.getThread().setOnErrorWebSocker(onErrorWebSocker); //Connect response web socket error to ui response
verifier.getThread().setOnResponsesWebSocket(onResponsesWebSocket); //Connect response and error web socket error to ui response
verifier.getThread().setShowNormalMessage(showNormalError); //Not show native message error, we handle it
for (String url : urls) {
CryptoNetURLs.get(crypto).add(url);
if(verifier != null) {
if (verifier != null) {
verifier.checkURL(url);
}
}
}
public static void removeCryptoNetURL(CryptoNet crypto, String url){
if(CryptoNetURLs.containsKey(crypto)){
CryptoNetURLs.get(crypto).remove(url);
@ -145,5 +190,4 @@ public abstract class CryptoNetManager {
return (int) (this.getTime() - testedURL.getTime());
}
}
}

View File

@ -1,5 +1,8 @@
package cy.agorise.crystalwallet.network;
import android.app.Activity;
import cy.agorise.crystalwallet.apigenerator.GrapheneApiGenerator;
import cy.agorise.crystalwallet.enums.CryptoNet;
/**
@ -12,6 +15,14 @@ import cy.agorise.crystalwallet.enums.CryptoNet;
public abstract class CryptoNetVerifier {
/*
* Contains the worker connection thread
*/
protected WebSocketThread thread;
static CryptoNetVerifier getNetworkVerify(CryptoNet cryptoNet){
if(cryptoNet.getLabel().equals(CryptoNet.BITSHARES.getLabel())){
return new BitsharesCryptoNetVerifier();
@ -22,4 +33,9 @@ public abstract class CryptoNetVerifier {
public abstract void checkURL(final String url);
public abstract String getChainId();
public WebSocketThread getThread() {
return thread;
}
}

View File

@ -1,6 +1,8 @@
package cy.agorise.crystalwallet.network;
import android.app.Activity;
import android.util.Log;
import android.widget.Toast;
import com.neovisionaries.ws.client.WebSocket;
import com.neovisionaries.ws.client.WebSocketException;
@ -10,6 +12,9 @@ import com.neovisionaries.ws.client.WebSocketListener;
import java.io.IOException;
import java.util.HashMap;
import cy.agorise.crystalwallet.apigenerator.GrapheneApiGenerator;
import cy.agorise.crystalwallet.dialogs.material.DialogMaterial;
/**
* Created by henry on 8/10/2017.
*/
@ -33,6 +38,34 @@ public class WebSocketThread extends Thread {
// If the parameters of this class can be change
private boolean canChange = true;
/*
*
* Interface to catch only errors in connection with sockets
* */
private GrapheneApiGenerator.OnErrorWebSocker onErrorWebSocker;
/*
*
* Interface to catch errors and success responses in connection with sockets
* */
private GrapheneApiGenerator.OnResponsesWebSocket onResponsesWebSocket;
/*
* To catch websocket errors
* */
private Activity activity;
/*
* To show normal error message or not
* */
private boolean showNormalMessage = true;
/*
* Object needed for socket connection
* */
private WebSocketFactory factory;
/**
* Basic constructor,
@ -43,16 +76,27 @@ public class WebSocketThread extends Thread {
* @param url The url to connect
*/
public WebSocketThread(WebSocketListener webSocketListener, String url) {
try {
WebSocketFactory factory = new WebSocketFactory().setConnectionTimeout(5000);
this.mUrl = url;
this.mWebSocketListener = webSocketListener;
this.mWebSocket = factory.createSocket(this.mUrl);
this.mWebSocket.addListener(this.mWebSocketListener);
} catch (IOException e) {
Log.e(TAG, "IOException. Msg: "+e.getMessage());
} catch(NullPointerException e){
Log.e(TAG, "NullPointerException at WebsocketWorkerThreas. Msg: "+e.getMessage());
/*
* The listener always can be setted
* */
this.mWebSocketListener = webSocketListener;
/*
*
* If at this point the url is not defined, this will be set after
* */
if(url!=null){
try {
factory = new WebSocketFactory().setConnectionTimeout(5000);
this.mUrl = url;
this.mWebSocket = factory.createSocket(this.mUrl);
this.mWebSocket.addListener(this.mWebSocketListener);
} catch (IOException e) {
Log.e(TAG, "IOException. Msg: "+e.getMessage());
} catch(NullPointerException e){
Log.e(TAG, "NullPointerException at WebsocketWorkerThreas. Msg: "+e.getMessage());
}
}
}
@ -110,16 +154,62 @@ public class WebSocketThread extends Thread {
@Override
public void run() {
canChange = false;
// Moves the current Thread into the background
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
try {
/*
* If the initialization of the socket comes after
* */
if(factory==null){
factory = new WebSocketFactory().setConnectionTimeout(5000);
this.mWebSocket = factory.createSocket(this.mUrl);
this.mWebSocket.addListener(this.mWebSocketListener);
}
WebSocketThread.currentThreads.put(this.getId(),this);
mWebSocket.connect();
} catch (WebSocketException e) {
/*
*
* Websocket success response
* */
if(onResponsesWebSocket!=null){
onResponsesWebSocket.onSuccess();
}
} catch (final Exception e) {
Log.e(TAG, "WebSocketException. Msg: "+e.getMessage());
} catch(NullPointerException e){
Log.e(TAG, "NullPointerException. Msg: "+e.getMessage());
//Deliver error to user
if(activity!=null){
/*
* Show error to user if aplies
* */
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
if(showNormalMessage){
Toast.makeText(activity, e.getMessage(), Toast.LENGTH_LONG).show();
}
}
});
/*Deliver response in the listeners*/
if(onErrorWebSocker!=null){
onErrorWebSocker.onError(e);
}
else if(onResponsesWebSocket!=null){
onResponsesWebSocket.onError(e);
}
}
}
WebSocketThread.currentThreads.remove(this.getId());
}
@ -127,4 +217,25 @@ public class WebSocketThread extends Thread {
public boolean isConnected(){
return mWebSocket.isOpen();
}
public void setOnErrorWebSocker(GrapheneApiGenerator.OnErrorWebSocker onErrorWebSocker) {
this.onErrorWebSocker = onErrorWebSocker;
}
public void setActivity(Activity activity) {
this.activity = activity;
}
public void setShowNormalMessage(boolean showNormalMessage) {
this.showNormalMessage = showNormalMessage;
}
public void setmUrl(String mUrl) {
this.mUrl = mUrl;
}
public void setOnResponsesWebSocket(GrapheneApiGenerator.OnResponsesWebSocket onResponsesWebSocket) {
this.onResponsesWebSocket = onResponsesWebSocket;
}
}

View File

@ -1,5 +1,7 @@
package cy.agorise.crystalwallet.requestmanagers;
import android.app.Activity;
import cy.agorise.crystalwallet.enums.CryptoCoin;
/**
@ -19,6 +21,13 @@ public abstract class CryptoNetInfoRequest {
*/
protected CryptoNetInfoRequestListener listener;
protected CryptoNetInfoRequest(CryptoCoin coin){
this.coin = coin;
}
@ -31,4 +40,5 @@ public abstract class CryptoNetInfoRequest {
listener.onCarryOut();
CryptoNetInfoRequests.getInstance().removeRequest(this);
}
}