- Moved the NetworkService management logic to the newly introduced NetworkServiceManager class
This commit is contained in:
parent
beba8a0b40
commit
a6df7ed69e
9 changed files with 151 additions and 83 deletions
|
@ -10,7 +10,7 @@ android {
|
||||||
buildToolsVersion "25.0.0"
|
buildToolsVersion "25.0.0"
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdkVersion 9
|
minSdkVersion 14
|
||||||
targetSdkVersion 24
|
targetSdkVersion 24
|
||||||
versionCode 12
|
versionCode 12
|
||||||
versionName "0.4.7-alpha3"
|
versionName "0.4.7-alpha3"
|
||||||
|
|
|
@ -99,8 +99,12 @@ public class NetworkService extends Service {
|
||||||
return mCurrentId;
|
return mCurrentId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int sendMessage(ApiCallable apiCallable){
|
public int sendMessage(ApiCallable apiCallable, int requiredApi){
|
||||||
ApiCall call = apiCallable.toApiCall(mApiIds.get(ApiAccess.API_DATABASE), mCurrentId);
|
int apiId = 0;
|
||||||
|
if(requiredApi != -1){
|
||||||
|
apiId = mApiIds.get(requiredApi);
|
||||||
|
}
|
||||||
|
ApiCall call = apiCallable.toApiCall(apiId, mCurrentId);
|
||||||
if(mWebSocket.send(call.toJsonString())){
|
if(mWebSocket.send(call.toJsonString())){
|
||||||
Log.v(TAG,"> "+call.toJsonString());
|
Log.v(TAG,"> "+call.toJsonString());
|
||||||
}else{
|
}else{
|
||||||
|
@ -112,6 +116,7 @@ public class NetworkService extends Service {
|
||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
Log.d(TAG,"onDestroy");
|
Log.d(TAG,"onDestroy");
|
||||||
|
if(mWebSocket != null)
|
||||||
mWebSocket.close(NORMAL_CLOSURE_STATUS, null);
|
mWebSocket.close(NORMAL_CLOSURE_STATUS, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {}
|
||||||
|
};
|
||||||
|
}
|
|
@ -6,7 +6,6 @@ package cy.agorise.graphenej.api.bitshares;
|
||||||
|
|
||||||
public class Nodes {
|
public class Nodes {
|
||||||
public static final String[] NODE_URLS = {
|
public static final String[] NODE_URLS = {
|
||||||
"wss://bitshares.nus/ws",
|
|
||||||
"wss://dexnode.net/ws", // Dallas, USA
|
"wss://dexnode.net/ws", // Dallas, USA
|
||||||
"wss://bitshares.crypto.fans/ws", // Munich, Germany
|
"wss://bitshares.crypto.fans/ws", // Munich, Germany
|
||||||
"wss://bitshares.openledger.info/ws", // Openledger node
|
"wss://bitshares.openledger.info/ws", // Openledger node
|
||||||
|
|
|
@ -4,6 +4,7 @@ import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import cy.agorise.graphenej.RPC;
|
import cy.agorise.graphenej.RPC;
|
||||||
|
import cy.agorise.graphenej.api.ApiAccess;
|
||||||
import cy.agorise.graphenej.models.ApiCall;
|
import cy.agorise.graphenej.models.ApiCall;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -12,6 +13,8 @@ import cy.agorise.graphenej.models.ApiCall;
|
||||||
|
|
||||||
public class GetBlock implements ApiCallable {
|
public class GetBlock implements ApiCallable {
|
||||||
|
|
||||||
|
public static final int REQUIRED_API = ApiAccess.API_DATABASE;
|
||||||
|
|
||||||
private long blockNumber;
|
private long blockNumber;
|
||||||
|
|
||||||
public GetBlock(int blockNum){
|
public GetBlock(int blockNum){
|
||||||
|
|
|
@ -9,6 +9,7 @@ import cy.agorise.graphenej.BaseOperation;
|
||||||
import cy.agorise.graphenej.BlockData;
|
import cy.agorise.graphenej.BlockData;
|
||||||
import cy.agorise.graphenej.RPC;
|
import cy.agorise.graphenej.RPC;
|
||||||
import cy.agorise.graphenej.Transaction;
|
import cy.agorise.graphenej.Transaction;
|
||||||
|
import cy.agorise.graphenej.api.ApiAccess;
|
||||||
import cy.agorise.graphenej.models.ApiCall;
|
import cy.agorise.graphenej.models.ApiCall;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -17,6 +18,8 @@ import cy.agorise.graphenej.models.ApiCall;
|
||||||
|
|
||||||
public class GetRequiredFees implements ApiCallable {
|
public class GetRequiredFees implements ApiCallable {
|
||||||
|
|
||||||
|
public static final int REQUIRED_API = ApiAccess.API_DATABASE;
|
||||||
|
|
||||||
private Transaction mTransaction;
|
private Transaction mTransaction;
|
||||||
private Asset mFeeAsset;
|
private Asset mFeeAsset;
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,7 @@ public class MainActivity extends AppCompatActivity {
|
||||||
@OnClick(R.id.send_message)
|
@OnClick(R.id.send_message)
|
||||||
public void onSendMesage(View v){
|
public void onSendMesage(View v){
|
||||||
GetBlock getBlock = new GetBlock(1000000);
|
GetBlock getBlock = new GetBlock(1000000);
|
||||||
mService.sendMessage(getBlock);
|
mService.sendMessage(getBlock, GetBlock.REQUIRED_API);
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnClick(R.id.next_activity)
|
@OnClick(R.id.next_activity)
|
||||||
|
@ -93,8 +93,6 @@ public class MainActivity extends AppCompatActivity {
|
||||||
super.onStart();
|
super.onStart();
|
||||||
// Bind to LocalService
|
// Bind to LocalService
|
||||||
Intent intent = new Intent(this, NetworkService.class);
|
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);
|
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,91 +1,24 @@
|
||||||
package com.luminiasoft.labs.sample;
|
package com.luminiasoft.labs.sample;
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.app.Application;
|
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
|
* Sample application class
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class SampleApplication extends Application implements Application.ActivityLifecycleCallbacks {
|
public class SampleApplication extends Application {
|
||||||
private final String TAG = this.getClass().getName();
|
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
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.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
|
* 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
|
* better estimate when the user has left the app and it is safe to disconnect the websocket connection
|
||||||
*/
|
*/
|
||||||
registerActivityLifecycleCallbacks(this);
|
registerActivityLifecycleCallbacks(new NetworkServiceManager(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) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@ import cy.agorise.graphenej.models.JsonRpcResponse;
|
||||||
import cy.agorise.graphenej.operations.LimitOrderCreateOperation;
|
import cy.agorise.graphenej.operations.LimitOrderCreateOperation;
|
||||||
import cy.agorise.graphenej.operations.TransferOperation;
|
import cy.agorise.graphenej.operations.TransferOperation;
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
|
import io.reactivex.disposables.Disposable;
|
||||||
import io.reactivex.functions.Consumer;
|
import io.reactivex.functions.Consumer;
|
||||||
|
|
||||||
public class SecondActivity extends AppCompatActivity {
|
public class SecondActivity extends AppCompatActivity {
|
||||||
|
@ -46,14 +47,17 @@ public class SecondActivity extends AppCompatActivity {
|
||||||
|
|
||||||
private Gson gson = new Gson();
|
private Gson gson = new Gson();
|
||||||
|
|
||||||
|
private Disposable mDisposable;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_second);
|
setContentView(R.layout.activity_second);
|
||||||
|
Log.d(TAG,"onCreate");
|
||||||
|
|
||||||
ButterKnife.bind(this);
|
ButterKnife.bind(this);
|
||||||
|
|
||||||
RxBus.getBusInstance()
|
mDisposable = RxBus.getBusInstance()
|
||||||
.asFlowable()
|
.asFlowable()
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(new Consumer<Object>() {
|
.subscribe(new Consumer<Object>() {
|
||||||
|
@ -86,6 +90,12 @@ public class SecondActivity extends AppCompatActivity {
|
||||||
unbindService(mConnection);
|
unbindService(mConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
mDisposable.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
/** Defines callbacks for backend binding, passed to bindService() */
|
/** Defines callbacks for backend binding, passed to bindService() */
|
||||||
private ServiceConnection mConnection = new ServiceConnection() {
|
private ServiceConnection mConnection = new ServiceConnection() {
|
||||||
|
|
||||||
|
@ -107,25 +117,25 @@ public class SecondActivity extends AppCompatActivity {
|
||||||
@OnClick(R.id.transfer_fee_usd)
|
@OnClick(R.id.transfer_fee_usd)
|
||||||
public void onTransferFeeUsdClicked(View v){
|
public void onTransferFeeUsdClicked(View v){
|
||||||
List<BaseOperation> operations = getTransferOperation();
|
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)
|
@OnClick(R.id.transfer_fee_bts)
|
||||||
public void onTransferFeeBtsClicked(View v){
|
public void onTransferFeeBtsClicked(View v){
|
||||||
List<BaseOperation> operations = getTransferOperation();
|
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)
|
@OnClick(R.id.exchange_fee_usd)
|
||||||
public void onExchangeFeeUsdClicked(View v){
|
public void onExchangeFeeUsdClicked(View v){
|
||||||
List<BaseOperation> operations = getExchangeOperation();
|
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)
|
@OnClick(R.id.exchange_fee_bts)
|
||||||
public void onExchangeFeeBtsClicked(View v){
|
public void onExchangeFeeBtsClicked(View v){
|
||||||
List<BaseOperation> operations = getExchangeOperation();
|
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(){
|
private List<BaseOperation> getTransferOperation(){
|
||||||
|
|
Loading…
Reference in a new issue