- Moved the NetworkService management logic to the newly introduced NetworkServiceManager class

develop
Nelson R. Perez 2018-04-05 17:35:34 -05:00
parent beba8a0b40
commit a6df7ed69e
9 changed files with 151 additions and 83 deletions

View File

@ -10,7 +10,7 @@ android {
buildToolsVersion "25.0.0"
defaultConfig {
minSdkVersion 9
minSdkVersion 14
targetSdkVersion 24
versionCode 12
versionName "0.4.7-alpha3"

View File

@ -99,8 +99,12 @@ public class NetworkService extends Service {
return mCurrentId;
}
public int sendMessage(ApiCallable apiCallable){
ApiCall call = apiCallable.toApiCall(mApiIds.get(ApiAccess.API_DATABASE), mCurrentId);
public int sendMessage(ApiCallable apiCallable, int requiredApi){
int apiId = 0;
if(requiredApi != -1){
apiId = mApiIds.get(requiredApi);
}
ApiCall call = apiCallable.toApiCall(apiId, mCurrentId);
if(mWebSocket.send(call.toJsonString())){
Log.v(TAG,"> "+call.toJsonString());
}else{
@ -112,7 +116,8 @@ public class NetworkService extends Service {
@Override
public void onDestroy() {
Log.d(TAG,"onDestroy");
mWebSocket.close(NORMAL_CLOSURE_STATUS, null);
if(mWebSocket != null)
mWebSocket.close(NORMAL_CLOSURE_STATUS, null);
}
@Override

View File

@ -0,0 +1,117 @@
package cy.agorise.graphenej.api.android;
import android.app.Activity;
import android.app.Application;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import java.lang.ref.WeakReference;
/**
* This class should be instantiated at the application level of the android app.
*
* It will monitor the interaction between the different activities of an app and help us decide
* when the connection to the full node should be interrupted.
*/
public class NetworkServiceManager implements Application.ActivityLifecycleCallbacks {
private final String TAG = this.getClass().getName();
/**
* Constant used to specify how long will the app wait for another activity to go through its starting life
* cycle events before running the teardownConnectionTask task.
*
* This is used as a means to detect whether or not the user has left the app.
*/
private final int DISCONNECT_DELAY = 1500;
/**
* Handler instance used to schedule tasks back to the main thread
*/
private Handler mHandler = new Handler();
/**
* Weak reference to the application context
*/
private WeakReference<Context> mContextReference;
// In case we want to interact directly with the service
private NetworkService mService;
/**
* Runnable used to schedule a service disconnection once the app is not visible to the user for
* more than DISCONNECT_DELAY milliseconds.
*/
private final Runnable mDisconnectRunnable = new Runnable() {
@Override
public void run() {
Context context = mContextReference.get();
if(mService != null){
context.unbindService(mServiceConnection);
mService = null;
}
context.stopService(new Intent(context, NetworkService.class));
}
};
public NetworkServiceManager(Context context){
mContextReference = new WeakReference<Context>(context);
}
@Override
public void onActivityCreated(Activity activity, Bundle bundle) {
if(mService == null){
// Starting a NetworkService instance
Context context = mContextReference.get();
Intent intent = new Intent(context, NetworkService.class);
context.startService(intent);
}
}
@Override
public void onActivityStarted(Activity activity) {
mHandler.removeCallbacks(mDisconnectRunnable);
if(mService == null){
Context context = mContextReference.get();
Intent intent = new Intent(context, NetworkService.class);
context.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
}
}
@Override
public void onActivityResumed(Activity activity) {}
@Override
public void onActivityPaused(Activity activity) {
mHandler.postDelayed(mDisconnectRunnable, DISCONNECT_DELAY);
}
@Override
public void onActivityStopped(Activity activity) {}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {}
@Override
public void onActivityDestroyed(Activity activity) {}
/** Defines callbacks for backend binding, passed to bindService() */
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className,
IBinder service) {
// We've bound to LocalService, cast the IBinder and get LocalService instance
NetworkService.LocalBinder binder = (NetworkService.LocalBinder) service;
mService = binder.getService();
}
@Override
public void onServiceDisconnected(ComponentName componentName) {}
};
}

View File

@ -6,7 +6,6 @@ package cy.agorise.graphenej.api.bitshares;
public class Nodes {
public static final String[] NODE_URLS = {
"wss://bitshares.nus/ws",
"wss://dexnode.net/ws", // Dallas, USA
"wss://bitshares.crypto.fans/ws", // Munich, Germany
"wss://bitshares.openledger.info/ws", // Openledger node

View File

@ -4,6 +4,7 @@ import java.io.Serializable;
import java.util.ArrayList;
import cy.agorise.graphenej.RPC;
import cy.agorise.graphenej.api.ApiAccess;
import cy.agorise.graphenej.models.ApiCall;
/**
@ -12,6 +13,8 @@ import cy.agorise.graphenej.models.ApiCall;
public class GetBlock implements ApiCallable {
public static final int REQUIRED_API = ApiAccess.API_DATABASE;
private long blockNumber;
public GetBlock(int blockNum){

View File

@ -9,6 +9,7 @@ import cy.agorise.graphenej.BaseOperation;
import cy.agorise.graphenej.BlockData;
import cy.agorise.graphenej.RPC;
import cy.agorise.graphenej.Transaction;
import cy.agorise.graphenej.api.ApiAccess;
import cy.agorise.graphenej.models.ApiCall;
/**
@ -17,6 +18,8 @@ import cy.agorise.graphenej.models.ApiCall;
public class GetRequiredFees implements ApiCallable {
public static final int REQUIRED_API = ApiAccess.API_DATABASE;
private Transaction mTransaction;
private Asset mFeeAsset;

View File

@ -79,7 +79,7 @@ public class MainActivity extends AppCompatActivity {
@OnClick(R.id.send_message)
public void onSendMesage(View v){
GetBlock getBlock = new GetBlock(1000000);
mService.sendMessage(getBlock);
mService.sendMessage(getBlock, GetBlock.REQUIRED_API);
}
@OnClick(R.id.next_activity)
@ -93,8 +93,6 @@ public class MainActivity extends AppCompatActivity {
super.onStart();
// Bind to LocalService
Intent intent = new Intent(this, NetworkService.class);
int requestedApis = ApiAccess.API_DATABASE | ApiAccess.API_HISTORY | ApiAccess.API_NETWORK_BROADCAST;
intent.putExtra(NetworkService.KEY_REQUESTED_APIS, requestedApis);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}

View File

@ -1,91 +1,24 @@
package com.luminiasoft.labs.sample;
import android.app.Activity;
import android.app.Application;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import cy.agorise.graphenej.api.android.NetworkService;
import cy.agorise.graphenej.api.android.NetworkServiceManager;
/**
* Sample application class
*/
public class SampleApplication extends Application implements Application.ActivityLifecycleCallbacks {
public class SampleApplication extends Application {
private final String TAG = this.getClass().getName();
/**
* Handler instance used to schedule tasks back to the main thread
*/
private Handler mHandler = new Handler();
/**
* Constant used to specify how long will the app wait for another activity to go through its starting life
* cycle events before running the teardownConnectionTask task.
*
* This is used as a means to detect whether or not the user has left the app.
*/
private final int DISCONNECT_DELAY = 1500;
/**
* Runnable used to schedule a service disconnection once the app is not visible to the user for
* more than DISCONNECT_DELAY milliseconds.
*/
private final Runnable mDisconnectRunnable = new Runnable() {
@Override
public void run() {
Log.d(TAG,"Runing stopService");
stopService(new Intent(getApplicationContext(), NetworkService.class));
}
};
@Override
public void onCreate() {
super.onCreate();
Intent intent = new Intent(this, NetworkService.class);
startService(intent);
/*
* Registering this class as a listener to all activity's callback cycle events, in order to
* better estimate when the user has left the app and it is safe to disconnect the websocket connection
*/
registerActivityLifecycleCallbacks(this);
}
@Override
public void onActivityCreated(Activity activity, Bundle bundle) {
}
@Override
public void onActivityStarted(Activity activity) {
mHandler.removeCallbacks(mDisconnectRunnable);
}
@Override
public void onActivityResumed(Activity activity) {
}
@Override
public void onActivityPaused(Activity activity) {
mHandler.postDelayed(mDisconnectRunnable, DISCONNECT_DELAY);
}
@Override
public void onActivityStopped(Activity activity) {
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {
}
@Override
public void onActivityDestroyed(Activity activity) {
registerActivityLifecycleCallbacks(new NetworkServiceManager(this));
}
}

View File

@ -32,6 +32,7 @@ import cy.agorise.graphenej.models.JsonRpcResponse;
import cy.agorise.graphenej.operations.LimitOrderCreateOperation;
import cy.agorise.graphenej.operations.TransferOperation;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
public class SecondActivity extends AppCompatActivity {
@ -46,14 +47,17 @@ public class SecondActivity extends AppCompatActivity {
private Gson gson = new Gson();
private Disposable mDisposable;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
Log.d(TAG,"onCreate");
ButterKnife.bind(this);
RxBus.getBusInstance()
mDisposable = RxBus.getBusInstance()
.asFlowable()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Object>() {
@ -86,6 +90,12 @@ public class SecondActivity extends AppCompatActivity {
unbindService(mConnection);
}
@Override
protected void onDestroy() {
super.onDestroy();
mDisposable.dispose();
}
/** Defines callbacks for backend binding, passed to bindService() */
private ServiceConnection mConnection = new ServiceConnection() {
@ -107,25 +117,25 @@ public class SecondActivity extends AppCompatActivity {
@OnClick(R.id.transfer_fee_usd)
public void onTransferFeeUsdClicked(View v){
List<BaseOperation> operations = getTransferOperation();
mService.sendMessage(new GetRequiredFees(operations, new Asset("1.3.121")));
mService.sendMessage(new GetRequiredFees(operations, new Asset("1.3.121")), GetRequiredFees.REQUIRED_API);
}
@OnClick(R.id.transfer_fee_bts)
public void onTransferFeeBtsClicked(View v){
List<BaseOperation> operations = getTransferOperation();
mService.sendMessage(new GetRequiredFees(operations, new Asset("1.3.0")));
mService.sendMessage(new GetRequiredFees(operations, new Asset("1.3.0")), GetRequiredFees.REQUIRED_API);
}
@OnClick(R.id.exchange_fee_usd)
public void onExchangeFeeUsdClicked(View v){
List<BaseOperation> operations = getExchangeOperation();
mService.sendMessage(new GetRequiredFees(operations, new Asset("1.3.121")));
mService.sendMessage(new GetRequiredFees(operations, new Asset("1.3.121")), GetRequiredFees.REQUIRED_API);
}
@OnClick(R.id.exchange_fee_bts)
public void onExchangeFeeBtsClicked(View v){
List<BaseOperation> operations = getExchangeOperation();
mService.sendMessage(new GetRequiredFees(operations, new Asset("1.3.0")));
mService.sendMessage(new GetRequiredFees(operations, new Asset("1.3.0")), GetRequiredFees.REQUIRED_API);
}
private List<BaseOperation> getTransferOperation(){