Handling only credentials and API access messages locally, deferring all other messages to the bus
This commit is contained in:
parent
69a0a64d30
commit
628faf6109
14 changed files with 363 additions and 57 deletions
|
@ -5,21 +5,6 @@ apply plugin: 'com.android.library'
|
||||||
apply from: 'maven-push.gradle'
|
apply from: 'maven-push.gradle'
|
||||||
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
testCompile group: 'junit', name: 'junit', version: '4.12'
|
|
||||||
compile 'com.neovisionaries:nv-websocket-client:1.30'
|
|
||||||
compile 'org.bitcoinj:bitcoinj-core:0.14.3'
|
|
||||||
compile group: 'com.google.code.gson', name: 'gson', version: '2.8.0'
|
|
||||||
compile group: "org.tukaani", name: "xz", version: "1.6"
|
|
||||||
|
|
||||||
// Rx dependencies
|
|
||||||
compile 'io.reactivex.rxjava2:rxandroid:2.0.2'
|
|
||||||
compile 'io.reactivex.rxjava2:rxjava:2.1.9'
|
|
||||||
compile 'com.jakewharton.rxrelay2:rxrelay:2.0.0'
|
|
||||||
compile 'com.squareup.okhttp3:okhttp:3.5.0'
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 24
|
compileSdkVersion 24
|
||||||
buildToolsVersion "25.0.0"
|
buildToolsVersion "25.0.0"
|
||||||
|
@ -38,3 +23,17 @@ android {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
testCompile group: 'junit', name: 'junit', version: '4.12'
|
||||||
|
compile 'com.neovisionaries:nv-websocket-client:1.30'
|
||||||
|
compile 'org.bitcoinj:bitcoinj-core:0.14.3'
|
||||||
|
compile group: 'com.google.code.gson', name: 'gson', version: '2.8.0'
|
||||||
|
compile group: "org.tukaani", name: "xz", version: "1.6"
|
||||||
|
|
||||||
|
// Rx dependencies
|
||||||
|
compile 'io.reactivex.rxjava2:rxandroid:2.0.2'
|
||||||
|
compile 'io.reactivex.rxjava2:rxjava:2.1.9'
|
||||||
|
compile 'com.jakewharton.rxrelay2:rxrelay:2.0.0'
|
||||||
|
compile 'com.squareup.okhttp3:okhttp:3.5.0'
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
package cy.agorise.graphenej.api;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class used to list all currently supported API accesses
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class ApiAccess {
|
||||||
|
public static final int API_DATABASE = 0x01;
|
||||||
|
public static final int API_HISTORY = 0x02;
|
||||||
|
public static final int API_NETWORK_BROADCAST = 0x04;
|
||||||
|
}
|
|
@ -7,7 +7,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://bitshares.nus/ws",
|
||||||
"ws://echo.websocket.org",
|
|
||||||
"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
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
package cy.agorise.graphenej.api.calls;
|
||||||
|
|
||||||
|
import cy.agorise.graphenej.models.ApiCall;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface to be implemented by all classes that will produce an ApiCall object instance
|
||||||
|
* as a result.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public interface ApiCallable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return An instance of the {@link ApiCall} class
|
||||||
|
*/
|
||||||
|
ApiCall toApiCall(int apiId, long sequenceId);
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package cy.agorise.graphenej.api.calls;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import cy.agorise.graphenej.RPC;
|
||||||
|
import cy.agorise.graphenej.models.ApiCall;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper aroung the "get_block" API call.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class GetBlock implements ApiCallable {
|
||||||
|
|
||||||
|
private long blockNumber;
|
||||||
|
|
||||||
|
public GetBlock(int blockNum){
|
||||||
|
this.blockNumber = blockNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ApiCall toApiCall(int apiId, long sequenceId){
|
||||||
|
ArrayList<Serializable> params = new ArrayList<>();
|
||||||
|
String blockNum = String.format("%d", this.blockNumber);
|
||||||
|
params.add(blockNum);
|
||||||
|
return new ApiCall(apiId, RPC.CALL_GET_BLOCK, params, RPC.VERSION, sequenceId);
|
||||||
|
}
|
||||||
|
}
|
|
@ -66,6 +66,7 @@ public class ApiCall implements JsonSerializable {
|
||||||
paramsArray.add(this.methodToCall);
|
paramsArray.add(this.methodToCall);
|
||||||
JsonArray methodParams = new JsonArray();
|
JsonArray methodParams = new JsonArray();
|
||||||
|
|
||||||
|
if(this.params != null){
|
||||||
for(int i = 0; i < this.params.size(); i++){
|
for(int i = 0; i < this.params.size(); i++){
|
||||||
if(this.params.get(i) instanceof JsonSerializable) {
|
if(this.params.get(i) instanceof JsonSerializable) {
|
||||||
// Sometimes the parameters are objects
|
// Sometimes the parameters are objects
|
||||||
|
@ -95,6 +96,7 @@ public class ApiCall implements JsonSerializable {
|
||||||
System.out.println("Skipping parameter of type: "+this.params.get(i).getClass());
|
System.out.println("Skipping parameter of type: "+this.params.get(i).getClass());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
paramsArray.add(methodParams);
|
paramsArray.add(methodParams);
|
||||||
obj.add(KEY_PARAMS, paramsArray);
|
obj.add(KEY_PARAMS, paramsArray);
|
||||||
obj.addProperty(KEY_JSON_RPC, this.jsonrpc);
|
obj.addProperty(KEY_JSON_RPC, this.jsonrpc);
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
package cy.agorise.graphenej.models;
|
package cy.agorise.graphenej.models;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by nelson on 11/12/16.
|
* Base response class
|
||||||
|
* @deprecated Use {@link JsonRpcResponse} instead
|
||||||
*/
|
*/
|
||||||
public class BaseResponse {
|
public class BaseResponse {
|
||||||
public long id;
|
public long id;
|
||||||
public Error error;
|
public Error error;
|
||||||
|
public Object result;
|
||||||
|
|
||||||
public static class Error {
|
public static class Error {
|
||||||
public ErrorData data;
|
public ErrorData data;
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
package cy.agorise.graphenej.models;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to represent a JSON-RPC response object
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class JsonRpcResponse<T> {
|
||||||
|
public long id;
|
||||||
|
public Error error;
|
||||||
|
public T result;
|
||||||
|
|
||||||
|
public static class Error {
|
||||||
|
public ErrorData data;
|
||||||
|
public int code;
|
||||||
|
public String message;
|
||||||
|
public Error(String message){
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ErrorData {
|
||||||
|
public int code;
|
||||||
|
public String name;
|
||||||
|
public String message;
|
||||||
|
//TODO: Include stack data
|
||||||
|
|
||||||
|
public ErrorData(String message){
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@ package cy.agorise.graphenej.models;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generic witness response
|
* Generic witness response
|
||||||
|
* @deprecated Use {@link JsonRpcResponse} instead
|
||||||
*/
|
*/
|
||||||
public class WitnessResponse<T> extends BaseResponse{
|
public class WitnessResponse<T> extends BaseResponse{
|
||||||
public static final String KEY_ID = "id";
|
public static final String KEY_ID = "id";
|
||||||
|
|
|
@ -22,7 +22,6 @@ android {
|
||||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|
|
@ -6,16 +6,22 @@ import android.content.Intent;
|
||||||
import android.content.ServiceConnection;
|
import android.content.ServiceConnection;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
import butterknife.ButterKnife;
|
import butterknife.ButterKnife;
|
||||||
import butterknife.OnClick;
|
import butterknife.OnClick;
|
||||||
|
import cy.agorise.graphenej.api.ApiAccess;
|
||||||
import cy.agorise.graphenej.api.ConnectionStatusUpdate;
|
import cy.agorise.graphenej.api.ConnectionStatusUpdate;
|
||||||
import cy.agorise.graphenej.api.android.RxBus;
|
import cy.agorise.graphenej.api.android.RxBus;
|
||||||
|
import cy.agorise.graphenej.api.calls.GetBlock;
|
||||||
|
import cy.agorise.graphenej.models.JsonRpcResponse;
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
import io.reactivex.functions.Consumer;
|
import io.reactivex.functions.Consumer;
|
||||||
|
|
||||||
|
@ -31,25 +37,39 @@ public class MainActivity extends AppCompatActivity {
|
||||||
// In case we want to interact directly with the service
|
// In case we want to interact directly with the service
|
||||||
private NetworkService mService;
|
private NetworkService mService;
|
||||||
|
|
||||||
|
private Gson gson = new Gson();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_main);
|
setContentView(R.layout.activity_main);
|
||||||
ButterKnife.bind(this);
|
ButterKnife.bind(this);
|
||||||
|
|
||||||
|
// Specifying some important information regarding the connection, such as the
|
||||||
|
// credentials and the requested API accesses
|
||||||
|
int requestedApis = ApiAccess.API_DATABASE | ApiAccess.API_HISTORY | ApiAccess.API_NETWORK_BROADCAST;
|
||||||
|
PreferenceManager.getDefaultSharedPreferences(this)
|
||||||
|
.edit()
|
||||||
|
.putString(NetworkService.KEY_USERNAME, "nelson")
|
||||||
|
.putString(NetworkService.KEY_PASSWORD, "secret")
|
||||||
|
.putInt(NetworkService.KEY_REQUESTED_APIS, requestedApis)
|
||||||
|
.apply();
|
||||||
|
|
||||||
RxBus.getBusInstance()
|
RxBus.getBusInstance()
|
||||||
.asFlowable()
|
.asFlowable()
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(new Consumer<Object>() {
|
.subscribe(new Consumer<Object>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void accept(Object o) throws Exception {
|
public void accept(Object message) throws Exception {
|
||||||
if(o instanceof String){
|
if(message instanceof String){
|
||||||
Log.d(TAG,"Got message");
|
Log.d(TAG,"Got text message: "+(message));
|
||||||
mResponse.setText(mResponse.getText() + ((String)o) + "\n");
|
mResponse.setText(mResponse.getText() + ((String) message) + "\n");
|
||||||
}else if(o instanceof ConnectionStatusUpdate){
|
}else if(message instanceof ConnectionStatusUpdate){
|
||||||
Log.d(TAG,"Got connection update");
|
Log.d(TAG,"Got connection update. Status: "+((ConnectionStatusUpdate)message).getConnectionStatus());
|
||||||
mConnectionStatus.setText(((ConnectionStatusUpdate)o).getConnectionStatus());
|
mConnectionStatus.setText(((ConnectionStatusUpdate) message).getConnectionStatus());
|
||||||
|
}else if(message instanceof JsonRpcResponse){
|
||||||
|
mResponse.setText(mResponse.getText() + gson.toJson(message, JsonRpcResponse.class) + "\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -57,7 +77,8 @@ 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){
|
||||||
mService.sendMessage("Sample message");
|
GetBlock getBlock = new GetBlock(1000000);
|
||||||
|
mService.sendMessage(getBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnClick(R.id.next_activity)
|
@OnClick(R.id.next_activity)
|
||||||
|
@ -71,6 +92,8 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,14 +2,29 @@ package com.luminiasoft.labs.sample;
|
||||||
|
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import cy.agorise.graphenej.RPC;
|
||||||
|
import cy.agorise.graphenej.api.ApiAccess;
|
||||||
import cy.agorise.graphenej.api.ConnectionStatusUpdate;
|
import cy.agorise.graphenej.api.ConnectionStatusUpdate;
|
||||||
import cy.agorise.graphenej.api.android.RxBus;
|
import cy.agorise.graphenej.api.android.RxBus;
|
||||||
import cy.agorise.graphenej.api.bitshares.Nodes;
|
import cy.agorise.graphenej.api.bitshares.Nodes;
|
||||||
|
import cy.agorise.graphenej.api.calls.ApiCallable;
|
||||||
|
import cy.agorise.graphenej.models.ApiCall;
|
||||||
|
import cy.agorise.graphenej.models.JsonRpcResponse;
|
||||||
import okhttp3.OkHttpClient;
|
import okhttp3.OkHttpClient;
|
||||||
import okhttp3.Request;
|
import okhttp3.Request;
|
||||||
import okhttp3.Response;
|
import okhttp3.Response;
|
||||||
|
@ -25,12 +40,35 @@ public class NetworkService extends Service {
|
||||||
|
|
||||||
private static final int NORMAL_CLOSURE_STATUS = 1000;
|
private static final int NORMAL_CLOSURE_STATUS = 1000;
|
||||||
|
|
||||||
|
public static final String KEY_USERNAME = "key_username";
|
||||||
|
|
||||||
|
public static final String KEY_PASSWORD = "key_password";
|
||||||
|
|
||||||
|
public static final String KEY_REQUESTED_APIS = "key_requested_apis";
|
||||||
|
|
||||||
private final IBinder mBinder = new LocalBinder();
|
private final IBinder mBinder = new LocalBinder();
|
||||||
|
|
||||||
private WebSocket mWebSocket;
|
private WebSocket mWebSocket;
|
||||||
|
|
||||||
private int mSocketIndex;
|
private int mSocketIndex;
|
||||||
|
|
||||||
|
// Username and password used to connect to a specific node
|
||||||
|
private String mUsername;
|
||||||
|
private String mPassword;
|
||||||
|
|
||||||
|
private boolean isLoggedIn = false;
|
||||||
|
|
||||||
|
private String mLastCall;
|
||||||
|
private int mCurrentId = 0;
|
||||||
|
|
||||||
|
// Requested APIs passed to this service
|
||||||
|
private int mRequestedApis;
|
||||||
|
|
||||||
|
// Variable used to keep track of the currently obtained API accesses
|
||||||
|
private HashMap<Integer, Integer> mApiIds = new HashMap();
|
||||||
|
|
||||||
|
private Gson gson = new Gson();
|
||||||
|
|
||||||
private WebSocketListener mWebSocketListener = new WebSocketListener() {
|
private WebSocketListener mWebSocketListener = new WebSocketListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -38,13 +76,92 @@ public class NetworkService extends Service {
|
||||||
super.onOpen(webSocket, response);
|
super.onOpen(webSocket, response);
|
||||||
mWebSocket = webSocket;
|
mWebSocket = webSocket;
|
||||||
RxBus.getBusInstance().send(new ConnectionStatusUpdate(ConnectionStatusUpdate.CONNECTED));
|
RxBus.getBusInstance().send(new ConnectionStatusUpdate(ConnectionStatusUpdate.CONNECTED));
|
||||||
|
|
||||||
|
if(!isLoggedIn){
|
||||||
|
Log.d(TAG,"About to send login request");
|
||||||
|
ArrayList<Serializable> loginParams = new ArrayList<>();
|
||||||
|
loginParams.add(mUsername);
|
||||||
|
loginParams.add(mPassword);
|
||||||
|
ApiCall loginCall = new ApiCall(1, RPC.CALL_LOGIN, loginParams, RPC.VERSION, ++mCurrentId);
|
||||||
|
mLastCall = RPC.CALL_LOGIN;
|
||||||
|
sendMessage(loginCall.toJsonString());
|
||||||
|
}else{
|
||||||
|
Log.d(TAG,"Already logged in");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onMessage(WebSocket webSocket, String text) {
|
public void onMessage(WebSocket webSocket, String text) {
|
||||||
super.onMessage(webSocket, text);
|
super.onMessage(webSocket, text);
|
||||||
Log.d(TAG,"onMessage. text: "+text);
|
Log.v(TAG,"< "+text);
|
||||||
RxBus.getBusInstance().send(text);
|
JsonRpcResponse<?> response = gson.fromJson(text, JsonRpcResponse.class);
|
||||||
|
|
||||||
|
// We will only handle messages that relate to the login and API accesses here.
|
||||||
|
if(response.result != null){
|
||||||
|
if(mLastCall == RPC.CALL_LOGIN){
|
||||||
|
isLoggedIn = true;
|
||||||
|
|
||||||
|
checkNextRequestedApiAccess();
|
||||||
|
}else if(mLastCall == RPC.CALL_DATABASE){
|
||||||
|
// Deserializing integer response
|
||||||
|
Type IntegerJsonResponse = new TypeToken<JsonRpcResponse<Integer>>(){}.getType();
|
||||||
|
JsonRpcResponse<Integer> apiIdResponse = gson.fromJson(text, IntegerJsonResponse);
|
||||||
|
|
||||||
|
// Storing the "database" api id
|
||||||
|
mApiIds.put(ApiAccess.API_DATABASE, apiIdResponse.result);
|
||||||
|
|
||||||
|
checkNextRequestedApiAccess();
|
||||||
|
}else if(mLastCall == RPC.CALL_HISTORY){
|
||||||
|
// Deserializing integer response
|
||||||
|
Type IntegerJsonResponse = new TypeToken<JsonRpcResponse<Integer>>(){}.getType();
|
||||||
|
JsonRpcResponse<Integer> apiIdResponse = gson.fromJson(text, IntegerJsonResponse);
|
||||||
|
|
||||||
|
// Storing the "history" api id
|
||||||
|
mApiIds.put(ApiAccess.API_HISTORY, apiIdResponse.result);
|
||||||
|
|
||||||
|
checkNextRequestedApiAccess();
|
||||||
|
}else if(mLastCall == RPC.CALL_NETWORK_BROADCAST){
|
||||||
|
// Deserializing integer response
|
||||||
|
Type IntegerJsonResponse = new TypeToken<JsonRpcResponse<Integer>>(){}.getType();
|
||||||
|
JsonRpcResponse<Integer> apiIdResponse = gson.fromJson(text, IntegerJsonResponse);
|
||||||
|
|
||||||
|
// Storing the "network_broadcast" api access
|
||||||
|
mApiIds.put(ApiAccess.API_NETWORK_BROADCAST, apiIdResponse.result);
|
||||||
|
|
||||||
|
// All calls have been handled at this point
|
||||||
|
mLastCall = "";
|
||||||
|
}else{
|
||||||
|
Log.d(TAG,"New unhandled message");
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
Log.w(TAG,"Error.Msg: "+response.error.message);
|
||||||
|
}
|
||||||
|
RxBus.getBusInstance().send(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkNextRequestedApiAccess(){
|
||||||
|
if( (mRequestedApis & ApiAccess.API_DATABASE) == ApiAccess.API_DATABASE &&
|
||||||
|
mApiIds.get(ApiAccess.API_DATABASE) == null){
|
||||||
|
// If we need the "database" api access and we don't yet have it
|
||||||
|
|
||||||
|
ApiCall apiCall = new ApiCall(1, RPC.CALL_DATABASE, null, RPC.VERSION, ++mCurrentId);
|
||||||
|
mLastCall = RPC.CALL_DATABASE;
|
||||||
|
sendMessage(apiCall.toJsonString());
|
||||||
|
} else if( (mRequestedApis & ApiAccess.API_HISTORY) == ApiAccess.API_HISTORY &&
|
||||||
|
mApiIds.get(ApiAccess.API_HISTORY) == null){
|
||||||
|
// If we need the "history" api access and we don't yet have it
|
||||||
|
|
||||||
|
ApiCall apiCall = new ApiCall(1, RPC.CALL_HISTORY, null, RPC.VERSION, ++mCurrentId);
|
||||||
|
mLastCall = RPC.CALL_HISTORY;
|
||||||
|
sendMessage(apiCall.toJsonString());
|
||||||
|
}else if( (mRequestedApis & ApiAccess.API_NETWORK_BROADCAST) == ApiAccess.API_NETWORK_BROADCAST &&
|
||||||
|
mApiIds.get(ApiAccess.API_NETWORK_BROADCAST) == null){
|
||||||
|
// If we need the "network_broadcast" api access and we don't yet have it
|
||||||
|
|
||||||
|
ApiCall apiCall = new ApiCall(1, RPC.CALL_NETWORK_BROADCAST, null, RPC.VERSION, ++mCurrentId);
|
||||||
|
mLastCall = RPC.CALL_NETWORK_BROADCAST;
|
||||||
|
sendMessage(apiCall.toJsonString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -52,12 +169,21 @@ public class NetworkService extends Service {
|
||||||
super.onClosed(webSocket, code, reason);
|
super.onClosed(webSocket, code, reason);
|
||||||
Log.d(TAG,"onClosed");
|
Log.d(TAG,"onClosed");
|
||||||
RxBus.getBusInstance().send(new ConnectionStatusUpdate(ConnectionStatusUpdate.DISCONNECTED));
|
RxBus.getBusInstance().send(new ConnectionStatusUpdate(ConnectionStatusUpdate.DISCONNECTED));
|
||||||
|
|
||||||
|
isLoggedIn = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
|
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
|
||||||
super.onFailure(webSocket, t, response);
|
super.onFailure(webSocket, t, response);
|
||||||
Log.d(TAG,"onFailure. Msg: "+t.getMessage());
|
Log.e(TAG,"onFailure. Msg: "+t.getMessage());
|
||||||
|
isLoggedIn = false;
|
||||||
|
if(response != null){
|
||||||
|
Log.e(TAG,"Response: "+response.message());
|
||||||
|
}
|
||||||
|
for(StackTraceElement element : t.getStackTrace()){
|
||||||
|
Log.v(TAG,String.format("%s#%s:%d", element.getClassName(), element.getMethodName(), element.getLineNumber()));
|
||||||
|
}
|
||||||
RxBus.getBusInstance().send(new ConnectionStatusUpdate(ConnectionStatusUpdate.DISCONNECTED));
|
RxBus.getBusInstance().send(new ConnectionStatusUpdate(ConnectionStatusUpdate.DISCONNECTED));
|
||||||
mSocketIndex++;
|
mSocketIndex++;
|
||||||
connect();
|
connect();
|
||||||
|
@ -68,24 +194,42 @@ public class NetworkService extends Service {
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
Log.d(TAG,"onCreate");
|
Log.d(TAG,"onCreate");
|
||||||
|
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
|
||||||
|
|
||||||
|
// Retrieving credentials and requested API data from the shared preferences
|
||||||
|
mUsername = pref.getString(NetworkService.KEY_USERNAME, "");
|
||||||
|
mPassword = pref.getString(NetworkService.KEY_PASSWORD, "");
|
||||||
|
mRequestedApis = pref.getInt(NetworkService.KEY_REQUESTED_APIS, -1);
|
||||||
|
|
||||||
connect();
|
connect();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void connect(){
|
private void connect(){
|
||||||
OkHttpClient client = new OkHttpClient();
|
OkHttpClient client = new OkHttpClient();
|
||||||
String url = Nodes.NODE_URLS[mSocketIndex % Nodes.NODE_URLS.length];
|
String url = Nodes.NODE_URLS[mSocketIndex % Nodes.NODE_URLS.length];
|
||||||
|
Log.d(TAG,"Trying to connect with: "+url);
|
||||||
Request request = new Request.Builder().url(url).build();
|
Request request = new Request.Builder().url(url).build();
|
||||||
client.newWebSocket(request, mWebSocketListener);
|
client.newWebSocket(request, mWebSocketListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendMessage(String message){
|
public int sendMessage(String message){
|
||||||
if(mWebSocket.send(message)){
|
if(mWebSocket.send(message)){
|
||||||
Log.d(TAG,"Message enqueued");
|
Log.v(TAG,"> " + message);
|
||||||
}else{
|
}else{
|
||||||
Log.w(TAG,"Message not enqueued");
|
Log.w(TAG,"Message not enqueued");
|
||||||
}
|
}
|
||||||
|
return mCurrentId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int sendMessage(ApiCallable apiCallable){
|
||||||
|
ApiCall call = apiCallable.toApiCall(mApiIds.get(ApiAccess.API_DATABASE), mCurrentId);
|
||||||
|
if(mWebSocket.send(call.toJsonString())){
|
||||||
|
Log.v(TAG,"> "+call.toJsonString());
|
||||||
|
}else{
|
||||||
|
Log.w(TAG,"Message not enqueued");
|
||||||
|
}
|
||||||
|
return mCurrentId;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
|
|
|
@ -7,6 +7,8 @@ import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import cy.agorise.graphenej.api.ApiAccess;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sample application class
|
* Sample application class
|
||||||
*/
|
*/
|
||||||
|
@ -43,6 +45,8 @@ public class SampleApplication extends Application implements Application.Activi
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
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);
|
||||||
startService(intent);
|
startService(intent);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -1,13 +1,60 @@
|
||||||
package com.luminiasoft.labs.sample;
|
package com.luminiasoft.labs.sample;
|
||||||
|
|
||||||
|
import android.content.ComponentName;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.ServiceConnection;
|
||||||
|
import android.os.IBinder;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import cy.agorise.graphenej.api.ApiAccess;
|
||||||
|
|
||||||
public class SecondActivity extends AppCompatActivity {
|
public class SecondActivity extends AppCompatActivity {
|
||||||
|
|
||||||
|
private final String TAG = this.getClass().getName();
|
||||||
|
|
||||||
|
// In case we want to interact directly with the service
|
||||||
|
private NetworkService mService;
|
||||||
|
|
||||||
@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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onStart() {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPause() {
|
||||||
|
super.onPause();
|
||||||
|
unbindService(mConnection);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Defines callbacks for backend binding, passed to bindService() */
|
||||||
|
private ServiceConnection mConnection = new ServiceConnection() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onServiceConnected(ComponentName className,
|
||||||
|
IBinder service) {
|
||||||
|
Log.d(TAG,"onServiceConnected");
|
||||||
|
// 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) {
|
||||||
|
Log.d(TAG,"onServiceDisconnected");
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue