Implemented remote service using Messenger.
This commit is contained in:
parent
33be741881
commit
961fb203df
|
@ -14,7 +14,7 @@
|
||||||
android:largeHeap="true"
|
android:largeHeap="true"
|
||||||
android:theme="@style/AppTheme" >
|
android:theme="@style/AppTheme" >
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".RemoteMainActivity"
|
||||||
android:label="@string/app_name" >
|
android:label="@string/app_name" >
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
@ -28,11 +28,22 @@
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name="org.ethereum.android_app.EthereumService"
|
android:name=".EthereumService"
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:process=":ethereum_process" >
|
android:process=":ethereum_process" >
|
||||||
</service>
|
</service>
|
||||||
|
<service
|
||||||
|
android:name=".EthereumRemoteService"
|
||||||
|
android:enabled="true"
|
||||||
|
android:exported="true"
|
||||||
|
android:process=":ethereum_remote_process" >
|
||||||
|
</service>
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name=".AidlMainActivity"
|
||||||
|
android:label="@string/app_name" >
|
||||||
|
</activity>
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package org.ethereum.android_app;
|
package org.ethereum.android_app;
|
||||||
|
|
||||||
|
|
||||||
import android.support.v4.app.Fragment;
|
|
||||||
|
|
||||||
public interface ActivityInterface {
|
public interface ActivityInterface {
|
||||||
|
|
||||||
void registerFragment(FragmentInterface fragment);
|
void registerFragment(FragmentInterface fragment);
|
||||||
|
|
|
@ -4,11 +4,9 @@ import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.ServiceConnection;
|
import android.content.ServiceConnection;
|
||||||
import android.os.AsyncTask;
|
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.support.v4.app.Fragment;
|
|
||||||
import android.support.v4.view.ViewPager;
|
import android.support.v4.view.ViewPager;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v7.app.ActionBarActivity;
|
import android.support.v7.app.ActionBarActivity;
|
||||||
|
@ -16,10 +14,8 @@ import android.support.v7.widget.Toolbar;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.os.Build;
|
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import org.ethereum.android.EthereumManager;
|
|
||||||
import org.ethereum.android.interop.IEthereumService;
|
import org.ethereum.android.interop.IEthereumService;
|
||||||
import org.ethereum.android.interop.IListener;
|
import org.ethereum.android.interop.IListener;
|
||||||
import org.ethereum.config.SystemProperties;
|
import org.ethereum.config.SystemProperties;
|
||||||
|
@ -28,7 +24,7 @@ import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
|
||||||
public class MainActivity extends ActionBarActivity implements ActivityInterface {
|
public class AidlMainActivity extends ActionBarActivity implements ActivityInterface {
|
||||||
|
|
||||||
private static final String TAG = "MyActivity";
|
private static final String TAG = "MyActivity";
|
||||||
|
|
||||||
|
@ -67,7 +63,7 @@ public class MainActivity extends ActionBarActivity implements ActivityInterface
|
||||||
// service through an IDL interface, so get a client-side
|
// service through an IDL interface, so get a client-side
|
||||||
// representation of that from the raw service object.
|
// representation of that from the raw service object.
|
||||||
ethereumService = IEthereumService.Stub.asInterface(service);
|
ethereumService = IEthereumService.Stub.asInterface(service);
|
||||||
Toast.makeText(MainActivity.this, "service attached", Toast.LENGTH_SHORT).show();
|
Toast.makeText(AidlMainActivity.this, "service attached", Toast.LENGTH_SHORT).show();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
@ -93,7 +89,7 @@ public class MainActivity extends ActionBarActivity implements ActivityInterface
|
||||||
SystemProperties.CONFIG.activePeerPort(),
|
SystemProperties.CONFIG.activePeerPort(),
|
||||||
SystemProperties.CONFIG.activePeerNodeid());
|
SystemProperties.CONFIG.activePeerNodeid());
|
||||||
}
|
}
|
||||||
Toast.makeText(MainActivity.this, "connected to service", Toast.LENGTH_SHORT).show();
|
Toast.makeText(AidlMainActivity.this, "connected to service", Toast.LENGTH_SHORT).show();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logMessage("Error adding listener: " + e.getMessage());
|
logMessage("Error adding listener: " + e.getMessage());
|
||||||
}
|
}
|
||||||
|
@ -104,7 +100,7 @@ public class MainActivity extends ActionBarActivity implements ActivityInterface
|
||||||
// This is called when the connection with the service has been
|
// This is called when the connection with the service has been
|
||||||
// unexpectedly disconnected -- that is, its process crashed.
|
// unexpectedly disconnected -- that is, its process crashed.
|
||||||
ethereumService = null;
|
ethereumService = null;
|
||||||
Toast.makeText(MainActivity.this, "service disconnected", Toast.LENGTH_SHORT).show();
|
Toast.makeText(AidlMainActivity.this, "service disconnected", Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -125,7 +121,7 @@ public class MainActivity extends ActionBarActivity implements ActivityInterface
|
||||||
tabs.setDistributeEvenly(true);
|
tabs.setDistributeEvenly(true);
|
||||||
tabs.setViewPager(viewPager);
|
tabs.setViewPager(viewPager);
|
||||||
|
|
||||||
ComponentName myService = startService(new Intent(MainActivity.this, EthereumService.class));
|
ComponentName myService = startService(new Intent(AidlMainActivity.this, EthereumService.class));
|
||||||
doBindService();
|
doBindService();
|
||||||
|
|
||||||
//StrictMode.enableDefaults();
|
//StrictMode.enableDefaults();
|
||||||
|
@ -133,13 +129,13 @@ public class MainActivity extends ActionBarActivity implements ActivityInterface
|
||||||
|
|
||||||
protected void logMessage(String message) {
|
protected void logMessage(String message) {
|
||||||
|
|
||||||
MainActivity.consoleLog += message + "\n";
|
AidlMainActivity.consoleLog += message + "\n";
|
||||||
int consoleLength = MainActivity.consoleLog.length();
|
int consoleLength = AidlMainActivity.consoleLog.length();
|
||||||
if (consoleLength > 5000) {
|
if (consoleLength > 5000) {
|
||||||
MainActivity.consoleLog = MainActivity.consoleLog.substring(4000);
|
AidlMainActivity.consoleLog = AidlMainActivity.consoleLog.substring(4000);
|
||||||
}
|
}
|
||||||
|
|
||||||
broadcastFragments(MainActivity.consoleLog);
|
broadcastFragments(AidlMainActivity.consoleLog);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -155,9 +151,9 @@ public class MainActivity extends ActionBarActivity implements ActivityInterface
|
||||||
// Establish a connection with the service. We use an explicit
|
// Establish a connection with the service. We use an explicit
|
||||||
// class name because there is no reason to be able to let other
|
// class name because there is no reason to be able to let other
|
||||||
// applications replace our component.
|
// applications replace our component.
|
||||||
bindService(new Intent(MainActivity.this, EthereumService.class), serviceConnection, Context.BIND_AUTO_CREATE);
|
bindService(new Intent(AidlMainActivity.this, EthereumService.class), serviceConnection, Context.BIND_AUTO_CREATE);
|
||||||
isBound = true;
|
isBound = true;
|
||||||
Toast.makeText(MainActivity.this, "binding to service", Toast.LENGTH_SHORT).show();
|
Toast.makeText(AidlMainActivity.this, "binding to service", Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
void doUnbindService() {
|
void doUnbindService() {
|
||||||
|
@ -177,7 +173,7 @@ public class MainActivity extends ActionBarActivity implements ActivityInterface
|
||||||
// Detach our existing connection.
|
// Detach our existing connection.
|
||||||
unbindService(serviceConnection);
|
unbindService(serviceConnection);
|
||||||
isBound = false;
|
isBound = false;
|
||||||
Toast.makeText(MainActivity.this, "unbinding from service", Toast.LENGTH_SHORT).show();
|
Toast.makeText(AidlMainActivity.this, "unbinding from service", Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,7 +187,6 @@ public class MainActivity extends ActionBarActivity implements ActivityInterface
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreateOptionsMenu(Menu menu) {
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
|
|
||||||
//return super.onCreateOptionsMenu(menu);
|
|
||||||
getMenuInflater().inflate(R.menu.menu_main, menu);
|
getMenuInflater().inflate(R.menu.menu_main, menu);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
|
@ -3,11 +3,23 @@ package org.ethereum.android_app;
|
||||||
|
|
||||||
import android.support.multidex.MultiDexApplication;
|
import android.support.multidex.MultiDexApplication;
|
||||||
|
|
||||||
|
import org.ethereum.android.service.EthereumConnector;
|
||||||
|
|
||||||
public class EthereumApplication extends MultiDexApplication {
|
public class EthereumApplication extends MultiDexApplication {
|
||||||
|
|
||||||
|
EthereumConnector ethereum = null;
|
||||||
|
|
||||||
@Override public void onCreate() {
|
@Override public void onCreate() {
|
||||||
|
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
|
ethereum = new EthereumConnector(this, EthereumRemoteService.class);
|
||||||
|
ethereum.bindService();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTerminate() {
|
||||||
|
|
||||||
|
super.onTerminate();
|
||||||
|
ethereum.unbindService();
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package org.ethereum.android_app;
|
||||||
|
|
||||||
|
|
||||||
|
public class EthereumRemoteService extends org.ethereum.android.service.EthereumRemoteService {
|
||||||
|
|
||||||
|
public EthereumRemoteService() {
|
||||||
|
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
package org.ethereum.android_app;
|
package org.ethereum.android_app;
|
||||||
|
|
||||||
import org.ethereum.android.EthereumAidlService;
|
import org.ethereum.android.service.EthereumAidlService;
|
||||||
import org.ethereum.android.interop.IListener;
|
import org.ethereum.android.interop.IListener;
|
||||||
|
|
||||||
public class EthereumService extends EthereumAidlService {
|
public class EthereumService extends EthereumAidlService {
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
package org.ethereum.android_app;
|
||||||
|
|
||||||
|
import android.support.v4.view.ViewPager;
|
||||||
|
import android.support.v7.app.ActionBarActivity;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v7.widget.Toolbar;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
|
||||||
|
public class RemoteMainActivity extends ActionBarActivity implements ActivityInterface {
|
||||||
|
|
||||||
|
private Toolbar toolbar;
|
||||||
|
private ViewPager viewPager;
|
||||||
|
private SlidingTabLayout tabs;
|
||||||
|
private TabsPagerAdapter adapter;
|
||||||
|
protected ArrayList<FragmentInterface> fragments = new ArrayList<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.activity_main);
|
||||||
|
|
||||||
|
toolbar = (Toolbar) findViewById(R.id.tool_bar);
|
||||||
|
setSupportActionBar(toolbar);
|
||||||
|
|
||||||
|
adapter = new TabsPagerAdapter(getSupportFragmentManager());
|
||||||
|
viewPager = (ViewPager) findViewById(R.id.pager);
|
||||||
|
viewPager.setAdapter(adapter);;
|
||||||
|
|
||||||
|
tabs = (SlidingTabLayout) findViewById(R.id.tabs);
|
||||||
|
tabs.setDistributeEvenly(true);
|
||||||
|
tabs.setViewPager(viewPager);
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 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) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerFragment(FragmentInterface fragment) {
|
||||||
|
|
||||||
|
if (!fragments.contains(fragment)) {
|
||||||
|
fragments.add(fragment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,12 +10,14 @@ public class TestActivity extends ActionBarActivity {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_test);
|
setContentView(R.layout.activity_test);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreateOptionsMenu(Menu menu) {
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
|
|
||||||
// Inflate the menu; this adds items to the action bar if it is present.
|
// Inflate the menu; this adds items to the action bar if it is present.
|
||||||
getMenuInflater().inflate(R.menu.menu_test, menu);
|
getMenuInflater().inflate(R.menu.menu_test, menu);
|
||||||
return true;
|
return true;
|
||||||
|
@ -23,6 +25,7 @@ public class TestActivity extends ActionBarActivity {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
|
||||||
// Handle action bar item clicks here. The action bar will
|
// Handle action bar item clicks here. The action bar will
|
||||||
// automatically handle clicks on the Home/Up button, so long
|
// automatically handle clicks on the Home/Up button, so long
|
||||||
// as you specify a parent activity in AndroidManifest.xml.
|
// as you specify a parent activity in AndroidManifest.xml.
|
||||||
|
|
|
@ -1,22 +1,132 @@
|
||||||
package org.ethereum.android_app;
|
package org.ethereum.android_app;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.Message;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
import org.ethereum.android.EthereumManager;
|
import org.ethereum.android.EthereumManager;
|
||||||
|
import org.ethereum.android.interop.AdminInfo;
|
||||||
|
import org.ethereum.android.service.ConnectorHandler;
|
||||||
|
import org.ethereum.android.service.EthereumClientMessage;
|
||||||
|
import org.ethereum.config.SystemProperties;
|
||||||
|
|
||||||
public class TestsFragment extends Fragment {
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
EthereumManager ethereumManager;
|
import static org.ethereum.config.SystemProperties.CONFIG;
|
||||||
|
|
||||||
|
public class TestsFragment extends Fragment implements ConnectorHandler {
|
||||||
|
|
||||||
|
TextView connectionStatus;
|
||||||
|
TextView blockchainStatus;
|
||||||
|
TextView startupTime;
|
||||||
|
TextView isConsensus;
|
||||||
|
TextView blockExecTime;
|
||||||
|
|
||||||
|
Button connectButton;
|
||||||
|
Button getEthereumStatus;
|
||||||
|
Button getBlockchainStatus;
|
||||||
|
|
||||||
|
String identifier = UUID.randomUUID().toString();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||||
|
|
||||||
View view = inflater.inflate(R.layout.fragment_tests, container, false);
|
View view = inflater.inflate(R.layout.fragment_tests, container, false);
|
||||||
|
|
||||||
|
connectionStatus = (TextView)view.findViewById(R.id.connectionStatus);
|
||||||
|
blockchainStatus = (TextView)view.findViewById(R.id.blockchainStatus);
|
||||||
|
startupTime = (TextView)view.findViewById(R.id.startupTime);
|
||||||
|
isConsensus = (TextView)view.findViewById(R.id.isConsensus);
|
||||||
|
blockExecTime = (TextView)view.findViewById(R.id.blockExecTime);
|
||||||
|
connectButton = (Button)view.findViewById(R.id.connectButton);
|
||||||
|
getEthereumStatus = (Button)view.findViewById(R.id.getEthereumStatus);
|
||||||
|
getBlockchainStatus = (Button)view.findViewById(R.id.getBlockchainStatus);
|
||||||
|
|
||||||
|
connectButton.setOnClickListener(onClickListener);
|
||||||
|
getEthereumStatus.setOnClickListener(onClickListener);
|
||||||
|
getBlockchainStatus.setOnClickListener(onClickListener);
|
||||||
|
|
||||||
|
EthereumApplication app = (EthereumApplication)getActivity().getApplication();
|
||||||
|
app.ethereum.registerHandler(this);
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private View.OnClickListener onClickListener = new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(final View v) {
|
||||||
|
|
||||||
|
EthereumApplication app = (EthereumApplication)getActivity().getApplication();
|
||||||
|
switch(v.getId()){
|
||||||
|
case R.id.connectButton:
|
||||||
|
app.ethereum.connect(CONFIG.activePeerIP(), CONFIG.activePeerPort(), CONFIG.activePeerNodeid());
|
||||||
|
break;
|
||||||
|
case R.id.getEthereumStatus:
|
||||||
|
app.ethereum.getConnectionStatus(identifier);
|
||||||
|
app.ethereum.getAdminInfo(identifier);
|
||||||
|
break;
|
||||||
|
case R.id.getBlockchainStatus:
|
||||||
|
app.ethereum.getBlockchainStatus(identifier);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
protected void updateTextView(final TextView view, final String text) {
|
||||||
|
|
||||||
|
view.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
view.setText(text);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean handleMessage(final Message message) {
|
||||||
|
|
||||||
|
boolean isClaimed = true;
|
||||||
|
switch(message.what) {
|
||||||
|
case EthereumClientMessage.MSG_CONNECTION_STATUS:
|
||||||
|
updateTextView(connectionStatus, message.getData().getString("status"));
|
||||||
|
break;
|
||||||
|
case EthereumClientMessage.MSG_BLOCKCHAIN_STATUS:
|
||||||
|
updateTextView(blockchainStatus, message.getData().getString("status"));
|
||||||
|
break;
|
||||||
|
case EthereumClientMessage.MSG_ADMIN_INFO:
|
||||||
|
Bundle data = message.getData();
|
||||||
|
data.setClassLoader(AdminInfo.class.getClassLoader());
|
||||||
|
AdminInfo adminInfo = data.getParcelable("adminInfo");
|
||||||
|
updateTextView(startupTime, new SimpleDateFormat("yyyy MM dd HH:mm:ss").format(new Date(adminInfo.getStartupTimeStamp())));
|
||||||
|
updateTextView(isConsensus, adminInfo.isConsensus() ? "true" : "false");
|
||||||
|
updateTextView(blockExecTime, adminInfo.getExecAvg().toString());
|
||||||
|
break;
|
||||||
|
case EthereumClientMessage.MSG_ONLINE_PEER:
|
||||||
|
break;
|
||||||
|
case EthereumClientMessage.MSG_PEERS:
|
||||||
|
break;
|
||||||
|
case EthereumClientMessage.MSG_PENDING_TRANSACTIONS:
|
||||||
|
break;
|
||||||
|
case EthereumClientMessage.MSG_SUBMIT_TRANSACTION_RESULT:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
isClaimed = false;
|
||||||
|
}
|
||||||
|
return isClaimed;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getID() {
|
||||||
|
|
||||||
|
return identifier;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
|
||||||
|
android:paddingRight="@dimen/activity_horizontal_margin"
|
||||||
|
android:paddingTop="@dimen/activity_vertical_margin"
|
||||||
|
android:paddingBottom="@dimen/activity_vertical_margin"
|
||||||
|
tools:context="org.ethereum.android_app.RemoteMainActivity">
|
||||||
|
|
||||||
|
<TextView android:text="@string/hello_world" android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
|
</RelativeLayout>
|
|
@ -7,5 +7,162 @@
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:text="@string/ethereumj_tests"
|
android:text="@string/ethereumj_tests"
|
||||||
android:textSize="20sp"
|
android:textSize="20sp"
|
||||||
android:layout_centerInParent="true"/>
|
android:id="@+id/textView2"
|
||||||
|
android:layout_alignParentTop="true"
|
||||||
|
android:layout_alignParentLeft="true"
|
||||||
|
android:layout_alignParentStart="true" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_below="@+id/textView2"
|
||||||
|
android:layout_alignParentLeft="true"
|
||||||
|
android:layout_alignParentStart="true"
|
||||||
|
android:weightSum="1">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Connect"
|
||||||
|
android:id="@+id/connectButton"
|
||||||
|
android:layout_below="@+id/textView2"
|
||||||
|
android:layout_alignLeft="@+id/getBlockchainStatus"
|
||||||
|
android:layout_alignStart="@+id/getBlockchainStatus"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:textSize="10sp" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Ethereum Status"
|
||||||
|
android:id="@+id/getEthereumStatus"
|
||||||
|
android:layout_alignTop="@+id/connectButton"
|
||||||
|
android:layout_toRightOf="@+id/textView"
|
||||||
|
android:layout_toEndOf="@+id/textView"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:textSize="10sp" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Blockchain Status"
|
||||||
|
android:id="@+id/getBlockchainStatus"
|
||||||
|
android:layout_marginBottom="42dp"
|
||||||
|
android:layout_above="@+id/textView"
|
||||||
|
android:layout_centerHorizontal="true"
|
||||||
|
android:textSize="10sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
|
android:text="Ethereum Status: "
|
||||||
|
android:id="@+id/textView" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
|
android:text="Not Connected"
|
||||||
|
android:id="@+id/connectionStatus" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
|
android:text="Blockchain Status: "
|
||||||
|
android:id="@+id/textView4" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
|
android:text="None"
|
||||||
|
android:id="@+id/blockchainStatus" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
|
android:text="Startup Time:"
|
||||||
|
android:id="@+id/textView6" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
|
android:text="None"
|
||||||
|
android:id="@+id/startupTime" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content" >
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
|
android:text="Is Consensus:"
|
||||||
|
android:id="@+id/textView3" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
|
android:text="None"
|
||||||
|
android:id="@+id/isConsensus" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content" >
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
|
android:text="Average block exec time:"
|
||||||
|
android:id="@+id/textView7" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
|
android:text="None"
|
||||||
|
android:id="@+id/blockExecTime" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity">
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
tools:context="org.ethereum.android_app.RemoteMainActivity">
|
||||||
<item android:id="@+id/action_settings" android:title="@string/action_settings"
|
<item android:id="@+id/action_settings" android:title="@string/action_settings"
|
||||||
android:orderInCategory="100" app:showAsAction="never" />
|
android:orderInCategory="100" app:showAsAction="never" />
|
||||||
</menu>
|
</menu>
|
||||||
|
|
|
@ -9,5 +9,6 @@
|
||||||
<string name="title_activity_test">TestActivity</string>
|
<string name="title_activity_test">TestActivity</string>
|
||||||
|
|
||||||
<string name="hello_world">Hello world!</string>
|
<string name="hello_world">Hello world!</string>
|
||||||
|
<string name="title_activity_remote_main">RemoteMainActivity</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:label="@string/app_name" >
|
android:label="@string/app_name" >
|
||||||
<service
|
<service
|
||||||
android:name=".EthereumAidlService"
|
android:name=".service.EthereumAidlService"
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:process=":ethereum_process" >
|
android:process=":ethereum_process" >
|
||||||
|
@ -15,13 +15,13 @@
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</service>
|
</service>
|
||||||
<service
|
<service
|
||||||
android:name=".EthereumRemoteService"
|
android:name=".service.EthereumRemoteService"
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:process=":ethereum_process" >
|
android:process=":ethereum_process" >
|
||||||
</service>
|
</service>
|
||||||
<service
|
<service
|
||||||
android:name=".EthereumService"
|
android:name=".service.EthereumService"
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
android:exported="true" >
|
android:exported="true" >
|
||||||
</service>
|
</service>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<!-- Create a logcat appender -->
|
<!-- Create a logcat appender -->
|
||||||
<appender name="logcat" class="ch.qos.logback.classic.android.LogcatAppender">
|
<appender name="logcat" class="ch.qos.logback.classic.android.LogcatAppender">
|
||||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||||
<level>ERROR</level>
|
<level>INFO</level>
|
||||||
<onMatch>ACCEPT</onMatch>
|
<onMatch>ACCEPT</onMatch>
|
||||||
<onMismatch>DENY</onMismatch>
|
<onMismatch>DENY</onMismatch>
|
||||||
</filter>
|
</filter>
|
||||||
|
|
|
@ -2,8 +2,6 @@ package org.ethereum.android;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
import com.j256.ormlite.android.apptools.OpenHelperManager;
|
|
||||||
|
|
||||||
import org.ethereum.android.di.modules.EthereumModule;
|
import org.ethereum.android.di.modules.EthereumModule;
|
||||||
import org.ethereum.android.di.components.DaggerEthereumComponent;
|
import org.ethereum.android.di.components.DaggerEthereumComponent;
|
||||||
import org.ethereum.config.SystemProperties;
|
import org.ethereum.config.SystemProperties;
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
package org.ethereum.android;
|
|
||||||
|
|
||||||
import android.app.Service;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.os.IBinder;
|
|
||||||
|
|
||||||
public class EthereumRemoteService extends Service {
|
|
||||||
public EthereumRemoteService() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IBinder onBind(Intent intent) {
|
|
||||||
// TODO: Return the communication channel to the service.
|
|
||||||
throw new UnsupportedOperationException("Not yet implemented");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
package org.ethereum.android;
|
|
||||||
|
|
||||||
import android.app.Service;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.os.IBinder;
|
|
||||||
|
|
||||||
public class EthereumService extends Service {
|
|
||||||
public EthereumService() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IBinder onBind(Intent intent) {
|
|
||||||
// TODO: Return the communication channel to the service.
|
|
||||||
throw new UnsupportedOperationException("Not yet implemented");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
package org.ethereum.android.interop;
|
||||||
|
|
||||||
|
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class AdminInfo extends org.ethereum.manager.AdminInfo implements Parcelable {
|
||||||
|
|
||||||
|
public AdminInfo(org.ethereum.manager.AdminInfo adminInfo) {
|
||||||
|
|
||||||
|
startupTimeStamp = adminInfo.getStartupTimeStamp();
|
||||||
|
consensus = adminInfo.isConsensus();
|
||||||
|
blockExecTime = adminInfo.getBlockExecTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int describeContents() {
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(Parcel parcel, int i) {
|
||||||
|
|
||||||
|
parcel.writeLong(getStartupTimeStamp());
|
||||||
|
parcel.writeByte((byte) (isConsensus() ? 1 : 0));
|
||||||
|
parcel.writeLongArray(listToArray(getBlockExecTime()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private long[] listToArray(List<Long> list) {
|
||||||
|
|
||||||
|
int length = list.size();
|
||||||
|
int arrayLength = 0;
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
if (list.get(i) != null) {
|
||||||
|
arrayLength++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
long[] array = new long[arrayLength];
|
||||||
|
int arrayIndex = 0;
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
Long item = list.get(i);
|
||||||
|
if (item != null) {
|
||||||
|
array[arrayIndex] = item;
|
||||||
|
arrayIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Long> arrayToList(long[] array) {
|
||||||
|
|
||||||
|
ArrayList<Long> list = new ArrayList<>(array.length);
|
||||||
|
for (long item : array) {
|
||||||
|
list.add(item);
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Parcelable.Creator<AdminInfo> CREATOR = new Parcelable.Creator<AdminInfo>() {
|
||||||
|
|
||||||
|
public AdminInfo createFromParcel(Parcel in) {
|
||||||
|
|
||||||
|
return new AdminInfo(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AdminInfo[] newArray(int size) {
|
||||||
|
|
||||||
|
return new AdminInfo[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private AdminInfo(Parcel in) {
|
||||||
|
|
||||||
|
startupTimeStamp = in.readLong();
|
||||||
|
consensus = in.readByte() == 1 ? true : false;
|
||||||
|
blockExecTime = arrayToList(in.createLongArray());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
package org.ethereum.android.interop;
|
||||||
|
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
|
||||||
|
public class PeerInfo extends org.ethereum.net.peerdiscovery.PeerInfo implements Parcelable {
|
||||||
|
|
||||||
|
public PeerInfo(InetAddress ip, int port, String peerId) {
|
||||||
|
|
||||||
|
super(ip, port, peerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PeerInfo(org.ethereum.net.peerdiscovery.PeerInfo peerInfo) {
|
||||||
|
|
||||||
|
super(peerInfo.getAddress(), peerInfo.getPort(), peerInfo.getPeerId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int describeContents() {
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(Parcel parcel, int i) {
|
||||||
|
|
||||||
|
parcel.writeByteArray(address.getAddress());
|
||||||
|
parcel.writeInt(port);
|
||||||
|
parcel.writeString(peerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Parcelable.Creator<PeerInfo> CREATOR = new Parcelable.Creator<PeerInfo>() {
|
||||||
|
|
||||||
|
public PeerInfo createFromParcel(Parcel in) {
|
||||||
|
|
||||||
|
return new PeerInfo(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PeerInfo[] newArray(int size) {
|
||||||
|
|
||||||
|
return new PeerInfo[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private PeerInfo(Parcel in) {
|
||||||
|
|
||||||
|
super(null, 0, "");
|
||||||
|
InetAddress ip = null;
|
||||||
|
try {
|
||||||
|
address = InetAddress.getByAddress(in.createByteArray());
|
||||||
|
} catch (UnknownHostException e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
port = in.readInt();
|
||||||
|
peerId = in.readString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
package org.ethereum.android.interop;
|
||||||
|
|
||||||
|
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
|
||||||
|
public class Transaction extends org.ethereum.core.Transaction implements Parcelable{
|
||||||
|
|
||||||
|
|
||||||
|
public Transaction(org.ethereum.core.Transaction transaction) {
|
||||||
|
|
||||||
|
super(transaction.getEncoded());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int describeContents() {
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(Parcel parcel, int i) {
|
||||||
|
|
||||||
|
parcel.writeByteArray(getEncoded());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Parcelable.Creator<Transaction> CREATOR = new Parcelable.Creator<Transaction>() {
|
||||||
|
|
||||||
|
public Transaction createFromParcel(Parcel in) {
|
||||||
|
|
||||||
|
return new Transaction(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Transaction[] newArray(int size) {
|
||||||
|
|
||||||
|
return new Transaction[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private Transaction(Parcel in) {
|
||||||
|
|
||||||
|
super(in.createByteArray());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package org.ethereum.android.service;
|
||||||
|
|
||||||
|
|
||||||
|
import android.os.Message;
|
||||||
|
|
||||||
|
public interface ConnectorHandler {
|
||||||
|
|
||||||
|
boolean handleMessage(Message message);
|
||||||
|
String getID();
|
||||||
|
}
|
|
@ -0,0 +1,101 @@
|
||||||
|
package org.ethereum.android.service;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.os.RemoteException;
|
||||||
|
|
||||||
|
import org.ethereum.android.jsonrpc.JsonRpcServer;
|
||||||
|
import org.ethereum.android.manager.BlockLoader;
|
||||||
|
import org.ethereum.android.interop.*;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class EthereumAidlService extends EthereumService {
|
||||||
|
|
||||||
|
protected ArrayList<IListener> clientListeners = new ArrayList<>();
|
||||||
|
|
||||||
|
public static String log = "";
|
||||||
|
|
||||||
|
IEthereumService.Stub binder = null;
|
||||||
|
|
||||||
|
public EthereumAidlService() {
|
||||||
|
|
||||||
|
initializeBinder();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void initializeBinder() {
|
||||||
|
|
||||||
|
binder = new IEthereumService.Stub() {
|
||||||
|
|
||||||
|
public void loadBlocks(String dumpFile) throws RemoteException {
|
||||||
|
|
||||||
|
BlockLoader blockLoader = (BlockLoader)ethereum.getBlockLoader();
|
||||||
|
blockLoader.loadBlocks(dumpFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void connect(String ip, int port, String remoteId) throws RemoteException {
|
||||||
|
|
||||||
|
if (!isConnected) {
|
||||||
|
System.out.println("Connecting to : " + ip);
|
||||||
|
ethereum.connect(ip, port, remoteId);
|
||||||
|
isConnected = true;
|
||||||
|
} else {
|
||||||
|
System.out.println("Already connected");
|
||||||
|
System.out.println("x " + ethereum.isConnected());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addListener(IListener listener) throws RemoteException {
|
||||||
|
|
||||||
|
clientListeners.clear();
|
||||||
|
clientListeners.add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeListener(IListener listener) throws RemoteException {
|
||||||
|
|
||||||
|
try {
|
||||||
|
clientListeners.remove(listener);
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println("ERRORRRR: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startJsonRpcServer() throws RemoteException {
|
||||||
|
|
||||||
|
jsonRpcServer = new JsonRpcServer(ethereum);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void getLog(IAsyncCallback callback) throws RemoteException {
|
||||||
|
|
||||||
|
callback.handleResponse(EthereumAidlService.log);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void broadcastMessage(String message) {
|
||||||
|
|
||||||
|
for (IListener listener: clientListeners) {
|
||||||
|
try {
|
||||||
|
listener.trace(message);
|
||||||
|
} catch (Exception e) {
|
||||||
|
// Remove listener
|
||||||
|
System.out.println("ERRORRRR: " + e.getMessage());
|
||||||
|
clientListeners.remove(listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate() {
|
||||||
|
|
||||||
|
super.onCreate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBinder onBind(Intent intent) {
|
||||||
|
|
||||||
|
return binder;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
package org.ethereum.android.service;
|
||||||
|
|
||||||
|
public class EthereumClientMessage {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send online peer to the client ("peerInfo" => PeerInfo)
|
||||||
|
*/
|
||||||
|
public static final int MSG_ONLINE_PEER = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send peers to the client ("peers" => PeerInfo[])
|
||||||
|
*/
|
||||||
|
public static final int MSG_PEERS = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send blockchain status to the client ("status" => "Loaded/Loading")
|
||||||
|
*/
|
||||||
|
public static final int MSG_BLOCKCHAIN_STATUS = 3;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send ethereum connection status to the client
|
||||||
|
*/
|
||||||
|
public static final int MSG_CONNECTION_STATUS = 4;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send submitted transaction to client
|
||||||
|
*/
|
||||||
|
public static final int MSG_SUBMIT_TRANSACTION_RESULT = 5;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send admin info to client
|
||||||
|
*/
|
||||||
|
public static final int MSG_ADMIN_INFO = 6;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send peers to the client
|
||||||
|
*/
|
||||||
|
public static final int MSG_PENDING_TRANSACTIONS = 7;
|
||||||
|
}
|
|
@ -0,0 +1,391 @@
|
||||||
|
package org.ethereum.android.service;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.Message;
|
||||||
|
import android.os.RemoteException;
|
||||||
|
|
||||||
|
import org.ethereum.core.Transaction;
|
||||||
|
import org.ethereum.net.peerdiscovery.PeerInfo;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
|
||||||
|
public class EthereumConnector extends ServiceConnector {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger("EthereumConnector");
|
||||||
|
|
||||||
|
public EthereumConnector(Context context, Class serviceClass) {
|
||||||
|
|
||||||
|
super(context, serviceClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connect ethereum to peer
|
||||||
|
* @param ip String Peer ip address
|
||||||
|
* @param port int Peer port
|
||||||
|
* @param remoteId String Peer remote id
|
||||||
|
*
|
||||||
|
* Sends message parameters ( "key": type [description] ):
|
||||||
|
* {
|
||||||
|
* "ip": String [Peer ip address]
|
||||||
|
* "port": int [Peer port]
|
||||||
|
* "remoteId": String [Peer remote id]
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
public void connect(String ip, int port, String remoteId) {
|
||||||
|
|
||||||
|
if (!isBound)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Message msg = Message.obtain(null, EthereumServiceMessage.MSG_CONNECT, 0, 0);
|
||||||
|
Bundle data = new Bundle();
|
||||||
|
data.putString("ip", ip);
|
||||||
|
data.putInt("port", port);
|
||||||
|
data.putString("remoteId", remoteId);
|
||||||
|
msg.setData(data);
|
||||||
|
try {
|
||||||
|
serviceMessenger.send(msg);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
logger.error("Exception sending message(connect) to service: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load blocks from dump file
|
||||||
|
* @param dumpFile String Blocks dump file path
|
||||||
|
*
|
||||||
|
* Sends message parameters ( "key": type [description] ):
|
||||||
|
* {
|
||||||
|
* "dumpFile": String [Blocks dump file paths]
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
public void loadBlocks(String dumpFile) {
|
||||||
|
|
||||||
|
if (!isBound)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Message msg = Message.obtain(null, EthereumServiceMessage.MSG_LOAD_BLOCKS, 0, 0);
|
||||||
|
Bundle data = new Bundle();
|
||||||
|
data.putString("dumpFile", dumpFile);
|
||||||
|
msg.setData(data);
|
||||||
|
try {
|
||||||
|
serviceMessenger.send(msg);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
logger.error("Exception sending message(loadBlocks) to service: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start the json rpc server
|
||||||
|
*
|
||||||
|
* Sends message parameters: none
|
||||||
|
*/
|
||||||
|
public void startJsonRpc() {
|
||||||
|
|
||||||
|
if (!isBound)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Message msg = Message.obtain(null, EthereumServiceMessage.MSG_START_JSON_RPC_SERVER, 0, 0);
|
||||||
|
try {
|
||||||
|
serviceMessenger.send(msg);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
logger.error("Exception sending message(startJsonRpc) to service: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find an online peer
|
||||||
|
* @param identifier String Caller identifier used to return the response
|
||||||
|
*
|
||||||
|
* Sends message parameters: none
|
||||||
|
*/
|
||||||
|
public void findOnlinePeer(String identifier) {
|
||||||
|
|
||||||
|
if (!isBound)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Message msg = Message.obtain(null, EthereumServiceMessage.MSG_FIND_ONLINE_PEER, 0, 0);
|
||||||
|
msg.replyTo = clientMessenger;
|
||||||
|
msg.obj = getIdentifierBundle(identifier);
|
||||||
|
try {
|
||||||
|
serviceMessenger.send(msg);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
logger.error("Exception sending message(findOnlinePeer1) to service: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find an online peer
|
||||||
|
* @param identifier String Caller identifier used to return the response
|
||||||
|
* @param excludePeer PeerInfo Excluded peer from search
|
||||||
|
*
|
||||||
|
* Sends message parameters ( "key": type [description] ):
|
||||||
|
* {
|
||||||
|
* "excludePeer": Parcelable(PeerInfo) [Exclude peer from search]
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
public void findOnlinePeer(String identifier, PeerInfo excludePeer) {
|
||||||
|
|
||||||
|
if (!isBound)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Message msg = Message.obtain(null, EthereumServiceMessage.MSG_FIND_ONLINE_PEER, 0, 0);
|
||||||
|
msg.replyTo = clientMessenger;
|
||||||
|
msg.obj = getIdentifierBundle(identifier);
|
||||||
|
Bundle data = new Bundle();
|
||||||
|
data.putParcelable("excludePeer", (org.ethereum.android.interop.PeerInfo)excludePeer);
|
||||||
|
msg.setData(data);
|
||||||
|
try {
|
||||||
|
serviceMessenger.send(msg);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
logger.error("Exception sending message(findOnlinePeer2) to service: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find an online peer
|
||||||
|
* @param identifier String Caller identifier used to return the response
|
||||||
|
* @param excludePeerSet PeerInfo[] Excluded peers from search
|
||||||
|
*
|
||||||
|
* Sends message parameters ( "key": type [description] ):
|
||||||
|
* {
|
||||||
|
* "excludePeerSet": ParcelableArray(PeerInfo[]) [Excluded peers from search]
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
public void findOnlinePeer(String identifier, PeerInfo[] excludePeerSet) {
|
||||||
|
|
||||||
|
if (!isBound)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Message msg = Message.obtain(null, EthereumServiceMessage.MSG_FIND_ONLINE_PEER, 0, 0);
|
||||||
|
msg.replyTo = clientMessenger;
|
||||||
|
msg.obj = getIdentifierBundle(identifier);
|
||||||
|
Bundle data = new Bundle();
|
||||||
|
data.putParcelableArray("excludePeerSet", (org.ethereum.android.interop.PeerInfo[]) excludePeerSet);
|
||||||
|
msg.setData(data);
|
||||||
|
try {
|
||||||
|
serviceMessenger.send(msg);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
logger.error("Exception sending message(findOnlinePeer3) to service: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get etherum peers
|
||||||
|
* @param identifier String Caller identifier used to return the response
|
||||||
|
*
|
||||||
|
* Sends message parameters: none
|
||||||
|
*/
|
||||||
|
public void getPeers(String identifier) {
|
||||||
|
|
||||||
|
if (!isBound)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Message msg = Message.obtain(null, EthereumServiceMessage.MSG_GET_PEERS, 0, 0);
|
||||||
|
msg.replyTo = clientMessenger;
|
||||||
|
msg.obj = getIdentifierBundle(identifier);
|
||||||
|
try {
|
||||||
|
serviceMessenger.send(msg);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
logger.error("Exception sending message(getPeers) to service: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts ethereum peer discovery
|
||||||
|
*
|
||||||
|
* Sends message parameters: none
|
||||||
|
*/
|
||||||
|
public void startPeerDiscovery() {
|
||||||
|
|
||||||
|
if (!isBound)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Message msg = Message.obtain(null, EthereumServiceMessage.MSG_START_PEER_DISCOVERY, 0, 0);
|
||||||
|
try {
|
||||||
|
serviceMessenger.send(msg);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
logger.error("Exception sending message(startPeerDiscovery) to service: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops ethereum peer discovery
|
||||||
|
*
|
||||||
|
* Sends message parameters: none
|
||||||
|
*/
|
||||||
|
public void stopPeerDiscovery() {
|
||||||
|
|
||||||
|
if (!isBound)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Message msg = Message.obtain(null, EthereumServiceMessage.MSG_LOAD_BLOCKS, 0, 0);
|
||||||
|
try {
|
||||||
|
serviceMessenger.send(msg);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
logger.error("Exception sending message(stopPeerDiscovery) to service: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Bundle getIdentifierBundle(String identifier) {
|
||||||
|
|
||||||
|
Bundle bundle = new Bundle();
|
||||||
|
bundle.putString("identifier", identifier);
|
||||||
|
return bundle;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the blockchain status
|
||||||
|
* @param identifier String Caller identifier used to return the response
|
||||||
|
*
|
||||||
|
* Sends message parameters: none
|
||||||
|
*/
|
||||||
|
public void getBlockchainStatus(String identifier) {
|
||||||
|
|
||||||
|
if (!isBound)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Message msg = Message.obtain(null, EthereumServiceMessage.MSG_GET_BLOCKCHAIN_STATUS, 0, 0);
|
||||||
|
msg.replyTo = clientMessenger;
|
||||||
|
msg.obj = getIdentifierBundle(identifier);
|
||||||
|
try {
|
||||||
|
serviceMessenger.send(msg);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
logger.error("Exception sending message(getBlockchainStatus) to service: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add ethereum event listener
|
||||||
|
* @param identifier String Caller identifier used to return the response
|
||||||
|
*
|
||||||
|
* Sends message parameters: none
|
||||||
|
*/
|
||||||
|
public void addListener(String identifier) {
|
||||||
|
|
||||||
|
if (!isBound)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Message msg = Message.obtain(null, EthereumServiceMessage.MSG_ADD_LISTENER, 0, 0);
|
||||||
|
msg.replyTo = clientMessenger;
|
||||||
|
msg.obj = getIdentifierBundle(identifier);
|
||||||
|
// TODO: Add event flags to message
|
||||||
|
try {
|
||||||
|
serviceMessenger.send(msg);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
logger.error("Exception sending message(addListener) to service: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes ethereum
|
||||||
|
*
|
||||||
|
* Sends message parameters: none
|
||||||
|
*/
|
||||||
|
public void closeEthereum() {
|
||||||
|
|
||||||
|
if (!isBound)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Message msg = Message.obtain(null, EthereumServiceMessage.MSG_CLOSE, 0, 0);
|
||||||
|
try {
|
||||||
|
serviceMessenger.send(msg);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
logger.error("Exception sending message(closeEthereum) to service: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get connection status
|
||||||
|
* @param identifier String Caller identifier used to return the response
|
||||||
|
*
|
||||||
|
* Sends message parameters: none
|
||||||
|
*/
|
||||||
|
public void getConnectionStatus(String identifier) {
|
||||||
|
|
||||||
|
if (!isBound)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Message msg = Message.obtain(null, EthereumServiceMessage.MSG_GET_CONNECTION_STATUS, 0, 0);
|
||||||
|
msg.replyTo = clientMessenger;
|
||||||
|
msg.obj = getIdentifierBundle(identifier);
|
||||||
|
try {
|
||||||
|
serviceMessenger.send(msg);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
logger.error("Exception sending message(getConnectionStatus) to service: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Submit ethereum transaction
|
||||||
|
* @param identifier String Caller identifier used to return the response
|
||||||
|
* @param transaction Transaction Transaction to submit
|
||||||
|
*
|
||||||
|
* Sends message parameters ( "key": type [description] ):
|
||||||
|
* {
|
||||||
|
* "transaction": Parcelable(Transaction) [transaction to submit]
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
public void submitTransaction(String identifier, Transaction transaction) {
|
||||||
|
|
||||||
|
if (!isBound)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Message msg = Message.obtain(null, EthereumServiceMessage.MSG_SUBMIT_TRANSACTION, 0, 0);
|
||||||
|
msg.replyTo = clientMessenger;
|
||||||
|
msg.obj = getIdentifierBundle(identifier);
|
||||||
|
Bundle data = new Bundle();
|
||||||
|
data.putParcelable("transaction", (org.ethereum.android.interop.Transaction)transaction);
|
||||||
|
msg.setData(data);
|
||||||
|
try {
|
||||||
|
serviceMessenger.send(msg);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
logger.error("Exception sending message(submitTransaction) to service: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get admin info
|
||||||
|
* @param identifier String Caller identifier used to return the response
|
||||||
|
*
|
||||||
|
* Sends message parameters: none
|
||||||
|
*/
|
||||||
|
public void getAdminInfo(String identifier) {
|
||||||
|
|
||||||
|
if (!isBound)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Message msg = Message.obtain(null, EthereumServiceMessage.MSG_GET_ADMIN_INFO, 0, 0);
|
||||||
|
msg.replyTo = clientMessenger;
|
||||||
|
msg.obj = getIdentifierBundle(identifier);
|
||||||
|
try {
|
||||||
|
serviceMessenger.send(msg);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
logger.error("Exception sending message(getAdminInfo) to service: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get pending transactions
|
||||||
|
* @param identifier String Caller identifier used to return the response
|
||||||
|
*
|
||||||
|
* Sends message parameters: none
|
||||||
|
*/
|
||||||
|
public void getPendingTransactions(String identifier) {
|
||||||
|
|
||||||
|
if (!isBound)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Message msg = Message.obtain(null, EthereumServiceMessage.MSG_GET_PENDING_TRANSACTIONS, 0, 0);
|
||||||
|
msg.replyTo = clientMessenger;
|
||||||
|
msg.obj = getIdentifierBundle(identifier);
|
||||||
|
try {
|
||||||
|
serviceMessenger.send(msg);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
logger.error("Exception sending message(getPendingTransactions) to service: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,542 @@
|
||||||
|
package org.ethereum.android.service;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.os.Message;
|
||||||
|
import android.os.Messenger;
|
||||||
|
import android.os.RemoteException;
|
||||||
|
|
||||||
|
import org.ethereum.android.jsonrpc.JsonRpcServer;
|
||||||
|
import org.ethereum.android.manager.BlockLoader;
|
||||||
|
import org.ethereum.core.Transaction;
|
||||||
|
import org.ethereum.facade.Ethereum;
|
||||||
|
import org.ethereum.manager.AdminInfo;
|
||||||
|
import org.ethereum.net.peerdiscovery.PeerInfo;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import static org.ethereum.config.SystemProperties.CONFIG;
|
||||||
|
|
||||||
|
public class EthereumRemoteService extends EthereumService {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger("EthereumRemoteService");
|
||||||
|
|
||||||
|
ArrayList<Messenger> clientListeners = new ArrayList<>();
|
||||||
|
|
||||||
|
public EthereumRemoteService() {
|
||||||
|
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Handles incoming messages from clients. */
|
||||||
|
static class IncomingHandler extends Handler {
|
||||||
|
|
||||||
|
private final WeakReference<EthereumRemoteService> service;
|
||||||
|
|
||||||
|
IncomingHandler(EthereumRemoteService service) {
|
||||||
|
|
||||||
|
this.service = new WeakReference<EthereumRemoteService>(service);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleMessage(Message message) {
|
||||||
|
|
||||||
|
EthereumRemoteService service = this.service.get();
|
||||||
|
if (service != null) {
|
||||||
|
if (!service.handleMessage(message)) {
|
||||||
|
super.handleMessage(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Target we publish for clients to send messages to IncomingHandler.Note
|
||||||
|
* that calls to its binder are sequential!
|
||||||
|
*/
|
||||||
|
final Messenger serviceMessenger = new Messenger(new IncomingHandler(this));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When binding to the service, we return an interface to our messenger for
|
||||||
|
* sending messages to the service.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public IBinder onBind(Intent intent) {
|
||||||
|
|
||||||
|
return serviceMessenger.getBinder();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate() {
|
||||||
|
|
||||||
|
super.onCreate();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean handleMessage(Message message) {
|
||||||
|
|
||||||
|
switch (message.what) {
|
||||||
|
|
||||||
|
case EthereumServiceMessage.MSG_CONNECT:
|
||||||
|
connect(message);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EthereumServiceMessage.MSG_LOAD_BLOCKS:
|
||||||
|
loadBlocks(message);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EthereumServiceMessage.MSG_START_JSON_RPC_SERVER:
|
||||||
|
startJsonRpc(message);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EthereumServiceMessage.MSG_FIND_ONLINE_PEER:
|
||||||
|
findOnlinePeer(message);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EthereumServiceMessage.MSG_GET_PEERS:
|
||||||
|
getPeers(message);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EthereumServiceMessage.MSG_START_PEER_DISCOVERY:
|
||||||
|
startPeerDiscovery(message);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EthereumServiceMessage.MSG_STOP_PEER_DISCOVERY:
|
||||||
|
stopPeerDiscovery(message);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EthereumServiceMessage.MSG_GET_BLOCKCHAIN_STATUS:
|
||||||
|
getBlockchainStatus(message);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EthereumServiceMessage.MSG_ADD_LISTENER:
|
||||||
|
addListener(message);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EthereumServiceMessage.MSG_GET_CONNECTION_STATUS:
|
||||||
|
getConnectionStatus(message);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EthereumServiceMessage.MSG_CLOSE:
|
||||||
|
closeEthereum(message);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EthereumServiceMessage.MSG_SUBMIT_TRANSACTION:
|
||||||
|
submitTransaction(message);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EthereumServiceMessage.MSG_GET_ADMIN_INFO:
|
||||||
|
getAdminInfo(message);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EthereumServiceMessage.MSG_GET_PENDING_TRANSACTIONS:
|
||||||
|
getPendingTransactions(message);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connect to peer
|
||||||
|
*
|
||||||
|
* Incoming message parameters ( "key": type [description] ):
|
||||||
|
* {
|
||||||
|
* "ip": String [peer ip address]
|
||||||
|
* "port": int [peer port]
|
||||||
|
* "remoteId": String [peer remoteId]
|
||||||
|
* }
|
||||||
|
* Sends message: none
|
||||||
|
*/
|
||||||
|
protected void connect(Message message) {
|
||||||
|
|
||||||
|
if (!isConnected) {
|
||||||
|
isConnected = true;
|
||||||
|
new ConnectTask(message).execute(ethereum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class ConnectTask extends AsyncTask<Ethereum, Message, Void> {
|
||||||
|
|
||||||
|
String ip;
|
||||||
|
int port;
|
||||||
|
String remoteId;
|
||||||
|
|
||||||
|
public ConnectTask(Message message) {
|
||||||
|
|
||||||
|
Bundle data = message.getData();
|
||||||
|
ip = data.getString("ip");
|
||||||
|
port = data.getInt("port");
|
||||||
|
remoteId = data.getString("remoteId");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Void doInBackground(Ethereum... args) {
|
||||||
|
|
||||||
|
Ethereum ethereum = args[0];
|
||||||
|
ethereum.connect(ip, port, remoteId);
|
||||||
|
logger.info("Ethereum connecting to : " + ip + ":" + port);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onPostExecute(Void results) {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load blocks from dump file
|
||||||
|
*
|
||||||
|
* Incoming message parameters ( "key": type [description] ):
|
||||||
|
* {
|
||||||
|
* "dumpFile": String [blocks dump file path]
|
||||||
|
* }
|
||||||
|
* Sends message: none
|
||||||
|
*/
|
||||||
|
protected void loadBlocks(Message message) {
|
||||||
|
|
||||||
|
if (!isConnected) {
|
||||||
|
isConnected = true;
|
||||||
|
new LoadBlocksTask(message).execute(ethereum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class LoadBlocksTask extends AsyncTask<Ethereum, Message, Void> {
|
||||||
|
|
||||||
|
String dumpFile;
|
||||||
|
|
||||||
|
public LoadBlocksTask(Message message) {
|
||||||
|
|
||||||
|
Bundle data = message.getData();
|
||||||
|
dumpFile = data.getString("dumpFile");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Void doInBackground(Ethereum... args) {
|
||||||
|
|
||||||
|
Ethereum ethereum = args[0];
|
||||||
|
logger.info("Loading blocks from: " + dumpFile);
|
||||||
|
BlockLoader blockLoader = (BlockLoader)ethereum.getBlockLoader();
|
||||||
|
blockLoader.loadBlocks(dumpFile);
|
||||||
|
logger.info("Finished loading blocks from: " + dumpFile);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onPostExecute(Void results) {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start the json rpc server
|
||||||
|
*
|
||||||
|
* Incoming message parameters: none
|
||||||
|
* Sends message: none
|
||||||
|
*/
|
||||||
|
protected void startJsonRpc(Message message) {
|
||||||
|
|
||||||
|
// TODO: Maybe send back if it started succesfully ?
|
||||||
|
jsonRpcServer = new JsonRpcServer(ethereum);
|
||||||
|
try {
|
||||||
|
jsonRpcServer.start();
|
||||||
|
logger.info("Started json rpc server!");
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("Exception starting json rpc server: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find an online peer
|
||||||
|
*
|
||||||
|
* Incoming message parameters ( "key": type [description] ):
|
||||||
|
* {
|
||||||
|
* "excludePeer": Parcelable(PeerInfo) [peer to exclude from search]
|
||||||
|
* }
|
||||||
|
* Sends message parameters ( "key": type [description] ):
|
||||||
|
* {
|
||||||
|
* "peerInfo": Parcelable(PeerInfo) [found online peer, or null if error / online peer not found]
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
protected void findOnlinePeer(Message message) {
|
||||||
|
|
||||||
|
Bundle data = message.getData();
|
||||||
|
PeerInfo foundPeerInfo;
|
||||||
|
PeerInfo peerInfo = data.getParcelable("excludePeer");
|
||||||
|
if (peerInfo != null) {
|
||||||
|
foundPeerInfo = ethereum.findOnlinePeer(peerInfo);
|
||||||
|
} else {
|
||||||
|
PeerInfo[] excludePeerSet = (PeerInfo[])data.getParcelableArray("excludePeerSet");
|
||||||
|
if (excludePeerSet != null) {
|
||||||
|
foundPeerInfo = ethereum.findOnlinePeer(new HashSet<>(Arrays.asList(excludePeerSet)));
|
||||||
|
} else {
|
||||||
|
foundPeerInfo = ethereum.findOnlinePeer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Send reply
|
||||||
|
Message replyMessage = Message.obtain(null, EthereumClientMessage.MSG_ONLINE_PEER, 0, 0, message.obj);
|
||||||
|
Bundle replyData = new Bundle();
|
||||||
|
replyData.putParcelable("peerInfo", new org.ethereum.android.interop.PeerInfo(foundPeerInfo));
|
||||||
|
replyMessage.setData(replyData);
|
||||||
|
try {
|
||||||
|
message.replyTo.send(replyMessage);
|
||||||
|
logger.info("Sent online peer to client: " + foundPeerInfo.toString());
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
logger.error("Exception sending online peer to client: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get etherum peers
|
||||||
|
*
|
||||||
|
* Incoming message parameters: none
|
||||||
|
* Sends message ( "key": type [description] ):
|
||||||
|
* {
|
||||||
|
* "peers": Parcelable[](PeerInfo[]) [ethereum peers]
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
protected void getPeers(Message message) {
|
||||||
|
|
||||||
|
Set<PeerInfo> peers = ethereum.getPeers();
|
||||||
|
Message replyMessage = Message.obtain(null, EthereumClientMessage.MSG_PEERS, 0, 0, message.obj);
|
||||||
|
Bundle replyData = new Bundle();
|
||||||
|
org.ethereum.android.interop.PeerInfo[] convertedPeers = new org.ethereum.android.interop.PeerInfo[peers.size()];
|
||||||
|
int index = 0;
|
||||||
|
for (PeerInfo peerInfo: peers) {
|
||||||
|
convertedPeers[index] = new org.ethereum.android.interop.PeerInfo(peerInfo);
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
replyData.putParcelableArray("peers", convertedPeers);
|
||||||
|
replyMessage.setData(replyData);
|
||||||
|
try {
|
||||||
|
message.replyTo.send(replyMessage);
|
||||||
|
logger.info("Sent peers to client: " + peers.size());
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
logger.error("Exception sending peers to client: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts ethereum peer discovery
|
||||||
|
* Incoming message parameters: none
|
||||||
|
* Sends message: none
|
||||||
|
*/
|
||||||
|
protected void startPeerDiscovery(Message message) {
|
||||||
|
|
||||||
|
ethereum.startPeerDiscovery();
|
||||||
|
logger.info("Started peer discovery.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops ethereum peer discovery
|
||||||
|
* Incoming message parameters: none
|
||||||
|
* Sends message: none
|
||||||
|
*/
|
||||||
|
protected void stopPeerDiscovery(Message message) {
|
||||||
|
|
||||||
|
ethereum.stopPeerDiscovery();
|
||||||
|
logger.info("Stopped peer discovery.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the blockchain status
|
||||||
|
*
|
||||||
|
* Incoming message parameters: none
|
||||||
|
* Sends message ( "key": type [description] ):
|
||||||
|
* {
|
||||||
|
* "status": String [blockchain status: Loading/Loaded]
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
protected void getBlockchainStatus(Message message) {
|
||||||
|
|
||||||
|
boolean isLoading = ethereum.isBlockchainLoading();
|
||||||
|
String status = isLoading ? "Loading" : "Loaded";
|
||||||
|
Message replyMessage = Message.obtain(null, EthereumClientMessage.MSG_BLOCKCHAIN_STATUS, 0, 0, message.obj);
|
||||||
|
Bundle replyData = new Bundle();
|
||||||
|
replyData.putString("status", status);
|
||||||
|
replyMessage.setData(replyData);
|
||||||
|
try {
|
||||||
|
message.replyTo.send(replyMessage);
|
||||||
|
logger.info("Sent blockchain status: " + status);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
logger.error("Exception sending blockchain status to client: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add ethereum event listener
|
||||||
|
*
|
||||||
|
* Incoming message parameters: none
|
||||||
|
* Sends message: none
|
||||||
|
*/
|
||||||
|
protected void addListener(Message message) {
|
||||||
|
|
||||||
|
// Register the client's messenger
|
||||||
|
clientListeners.add(message.replyTo);
|
||||||
|
// TODO: Add channel listener types flags
|
||||||
|
logger.info("Client listener registered!");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes ethereum
|
||||||
|
*
|
||||||
|
* Incoming message parameters: none
|
||||||
|
* Sends message: none
|
||||||
|
*/
|
||||||
|
protected void closeEthereum(Message message) {
|
||||||
|
|
||||||
|
ethereum.close();
|
||||||
|
logger.info("Closed ethereum.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get connection status
|
||||||
|
*
|
||||||
|
* Incoming message parameters: none
|
||||||
|
* Sends message ( "key": type [description] ):
|
||||||
|
* {
|
||||||
|
* "status": String [ethereum connection status: Connected/Not Connected]
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
protected void getConnectionStatus(Message message) {
|
||||||
|
|
||||||
|
String status = ethereum.isConnected() ? "Connected" : "Not Connected";
|
||||||
|
Message replyMessage = Message.obtain(null, EthereumClientMessage.MSG_CONNECTION_STATUS, 0, 0, message.obj);
|
||||||
|
Bundle replyData = new Bundle();
|
||||||
|
replyData.putString("status", status);
|
||||||
|
replyMessage.setData(replyData);
|
||||||
|
try {
|
||||||
|
message.replyTo.send(replyMessage);
|
||||||
|
logger.info("Sent ethereum connection status: " + status);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
logger.error("Exception sending ethereum connection status to client: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Submit ethereum transaction
|
||||||
|
*
|
||||||
|
* Incoming message parameters ( "key": type [description] ):
|
||||||
|
* {
|
||||||
|
* "transaction": Parcelable(Transaction) [ethereum transaction to submit]
|
||||||
|
* }
|
||||||
|
* Sends message ( "key": type [description] ):
|
||||||
|
* {
|
||||||
|
* "transaction": Parcelable(Transaction) [submitted transaction]
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
protected void submitTransaction(Message message) {
|
||||||
|
|
||||||
|
if (!isConnected) {
|
||||||
|
isConnected = true;
|
||||||
|
new SubmitTransactionTask(message).execute(ethereum);
|
||||||
|
} else {
|
||||||
|
logger.warn("Ethereum not connected.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class SubmitTransactionTask extends AsyncTask<Ethereum, Void, Transaction> {
|
||||||
|
|
||||||
|
Transaction transaction;
|
||||||
|
Message message;
|
||||||
|
|
||||||
|
public SubmitTransactionTask(Message message) {
|
||||||
|
|
||||||
|
this.message = message;
|
||||||
|
Bundle data = message.getData();
|
||||||
|
transaction = data.getParcelable("transaction");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Transaction doInBackground(Ethereum... args) {
|
||||||
|
|
||||||
|
Transaction submitedTransaction = null;
|
||||||
|
try {
|
||||||
|
submitedTransaction = ethereum.submitTransaction(transaction).get(CONFIG.transactionApproveTimeout(), TimeUnit.SECONDS);
|
||||||
|
logger.info("Submitted transaction.");
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("Exception submitting transaction: " + e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return submitedTransaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onPostExecute(Transaction submittedTransaction) {
|
||||||
|
|
||||||
|
Message replyMessage = Message.obtain(null, EthereumClientMessage.MSG_SUBMIT_TRANSACTION_RESULT, 0, 0, message.obj);
|
||||||
|
Bundle replyData = new Bundle();
|
||||||
|
replyData.putParcelable("transaction", new org.ethereum.android.interop.Transaction(submittedTransaction));
|
||||||
|
replyMessage.setData(replyData);
|
||||||
|
try {
|
||||||
|
message.replyTo.send(replyMessage);
|
||||||
|
logger.info("Sent submitted transaction: " + submittedTransaction.toString());
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
logger.error("Exception sending submitted transaction to client: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get admin info
|
||||||
|
*
|
||||||
|
* Incoming message parameters: none
|
||||||
|
* Sends message ( "key": type [description] ):
|
||||||
|
* {
|
||||||
|
* "adminInfo": Parcelable(AdminInfo) [ethereum admin info]
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
protected void getAdminInfo(Message message) {
|
||||||
|
|
||||||
|
Message replyMessage = Message.obtain(null, EthereumClientMessage.MSG_ADMIN_INFO, 0, 0, message.obj);
|
||||||
|
Bundle replyData = new Bundle();
|
||||||
|
AdminInfo info = ethereum.getAdminInfo();
|
||||||
|
replyData.putParcelable("adminInfo", new org.ethereum.android.interop.AdminInfo(info));
|
||||||
|
replyMessage.setData(replyData);
|
||||||
|
try {
|
||||||
|
message.replyTo.send(replyMessage);
|
||||||
|
logger.info("Sent admin info: " + info.toString());
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
logger.error("Exception sending admin info to client: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get pending transactions
|
||||||
|
*
|
||||||
|
* Incoming message parameters: none
|
||||||
|
* Sends message ( "key": type [description] ):
|
||||||
|
* {
|
||||||
|
* "transactions": ParcelableArray(Transaction[]) [ethereum pending transactions]
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
protected void getPendingTransactions(Message message) {
|
||||||
|
|
||||||
|
Message replyMessage = Message.obtain(null, EthereumClientMessage.MSG_PENDING_TRANSACTIONS, 0, 0, message.obj);
|
||||||
|
Bundle replyData = new Bundle();
|
||||||
|
Set<Transaction> transactions = ethereum.getPendingTransactions();
|
||||||
|
org.ethereum.android.interop.Transaction[] convertedTransactions = new org.ethereum.android.interop.Transaction[transactions.size()];
|
||||||
|
int index = 0;
|
||||||
|
for (Transaction transaction: transactions) {
|
||||||
|
convertedTransactions[index] = new org.ethereum.android.interop.Transaction(transaction);
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
replyData.putParcelableArray("transactions", convertedTransactions);
|
||||||
|
replyMessage.setData(replyData);
|
||||||
|
try {
|
||||||
|
message.replyTo.send(replyMessage);
|
||||||
|
logger.info("Sent pending transactions: " + transactions.size());
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
logger.error("Exception sending pending transactions to client: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,52 +1,37 @@
|
||||||
package org.ethereum.android;
|
package org.ethereum.android.service;
|
||||||
|
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.RemoteException;
|
|
||||||
|
|
||||||
import org.ethereum.android.di.components.DaggerEthereumComponent;
|
import org.ethereum.android.di.components.DaggerEthereumComponent;
|
||||||
import org.ethereum.android.di.modules.EthereumModule;
|
import org.ethereum.android.di.modules.EthereumModule;
|
||||||
|
import org.ethereum.android.interop.IListener;
|
||||||
import org.ethereum.android.jsonrpc.JsonRpcServer;
|
import org.ethereum.android.jsonrpc.JsonRpcServer;
|
||||||
import org.ethereum.android.manager.BlockLoader;
|
|
||||||
import org.ethereum.config.SystemProperties;
|
import org.ethereum.config.SystemProperties;
|
||||||
import org.ethereum.core.*;
|
import org.ethereum.core.Transaction;
|
||||||
|
import org.ethereum.core.TransactionReceipt;
|
||||||
import org.ethereum.facade.Ethereum;
|
import org.ethereum.facade.Ethereum;
|
||||||
import org.ethereum.android.interop.*;
|
|
||||||
import org.ethereum.net.p2p.HelloMessage;
|
import org.ethereum.net.p2p.HelloMessage;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class EthereumAidlService extends Service {
|
public class EthereumService extends Service {
|
||||||
|
|
||||||
protected Ethereum ethereum = null;
|
|
||||||
|
|
||||||
protected JsonRpcServer jsonRpcServer;
|
|
||||||
|
|
||||||
protected ArrayList<IListener> clientListeners = new ArrayList<>();
|
|
||||||
|
|
||||||
public static String log = "";
|
|
||||||
|
|
||||||
boolean isConnected = false;
|
boolean isConnected = false;
|
||||||
|
|
||||||
boolean isInitialized = false;
|
boolean isInitialized = false;
|
||||||
|
|
||||||
public EthereumAidlService() {
|
protected Ethereum ethereum = null;
|
||||||
|
|
||||||
|
protected JsonRpcServer jsonRpcServer;
|
||||||
|
|
||||||
|
public EthereumService() {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void broadcastMessage(String message) {
|
protected void broadcastMessage(String message) {
|
||||||
|
|
||||||
for (IListener listener: clientListeners) {
|
|
||||||
try {
|
|
||||||
listener.trace(message);
|
|
||||||
} catch (Exception e) {
|
|
||||||
// Remove listener
|
|
||||||
System.out.println("ERRORRRR: " + e.getMessage());
|
|
||||||
clientListeners.remove(listener);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -85,56 +70,10 @@ public class EthereumAidlService extends Service {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IBinder onBind(Intent intent) {
|
public IBinder onBind(Intent intent) {
|
||||||
|
// TODO: Return the communication channel to the service.
|
||||||
return mBinder;
|
throw new UnsupportedOperationException("Not yet implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
IEthereumService.Stub mBinder = new IEthereumService.Stub() {
|
|
||||||
|
|
||||||
public void loadBlocks(String dumpFile) throws RemoteException {
|
|
||||||
|
|
||||||
BlockLoader blockLoader = (BlockLoader)ethereum.getBlockLoader();
|
|
||||||
blockLoader.loadBlocks(dumpFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void connect(String ip, int port, String remoteId) throws RemoteException {
|
|
||||||
|
|
||||||
if (!isConnected) {
|
|
||||||
System.out.println("Connecting to : " + ip);
|
|
||||||
ethereum.connect(ip, port, remoteId);
|
|
||||||
isConnected = true;
|
|
||||||
} else {
|
|
||||||
System.out.println("Already connected");
|
|
||||||
System.out.println("x " + ethereum.isConnected());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addListener(IListener listener) throws RemoteException {
|
|
||||||
|
|
||||||
clientListeners.clear();
|
|
||||||
clientListeners.add(listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeListener(IListener listener) throws RemoteException {
|
|
||||||
|
|
||||||
try {
|
|
||||||
clientListeners.remove(listener);
|
|
||||||
} catch (Exception e) {
|
|
||||||
System.out.println("ERRORRRR: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void startJsonRpcServer() throws RemoteException {
|
|
||||||
|
|
||||||
jsonRpcServer = new JsonRpcServer(ethereum);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void getLog(IAsyncCallback callback) throws RemoteException {
|
|
||||||
|
|
||||||
callback.handleResponse(EthereumAidlService.log);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
protected class EthereumListener implements org.ethereum.listener.EthereumListener {
|
protected class EthereumListener implements org.ethereum.listener.EthereumListener {
|
||||||
|
|
||||||
@Override
|
@Override
|
|
@ -0,0 +1,76 @@
|
||||||
|
package org.ethereum.android.service;
|
||||||
|
|
||||||
|
|
||||||
|
public class EthereumServiceMessage {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command to the service to connect to a peer
|
||||||
|
*/
|
||||||
|
public static final int MSG_CONNECT = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command to the service to load blocks dumpr
|
||||||
|
*/
|
||||||
|
public static final int MSG_LOAD_BLOCKS = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command to the service to start json rpc server
|
||||||
|
*/
|
||||||
|
public static final int MSG_START_JSON_RPC_SERVER = 3;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command to the service to find an online peer
|
||||||
|
*/
|
||||||
|
public static final int MSG_FIND_ONLINE_PEER = 4;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command to the service to list the peers
|
||||||
|
*/
|
||||||
|
public static final int MSG_GET_PEERS = 5;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command to the service to start peer discovery
|
||||||
|
*/
|
||||||
|
public static final int MSG_START_PEER_DISCOVERY = 6;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command to the service to stop peer discovery
|
||||||
|
*/
|
||||||
|
public static final int MSG_STOP_PEER_DISCOVERY = 7;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command to the service to get blockchain status (Loading/Loaded)
|
||||||
|
*/
|
||||||
|
public static final int MSG_GET_BLOCKCHAIN_STATUS = 8;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command to the service to add a listener
|
||||||
|
* <Not Implemented>
|
||||||
|
*/
|
||||||
|
public static final int MSG_ADD_LISTENER = 9;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command to the service to get connection status (Connected/Not Connected)
|
||||||
|
*/
|
||||||
|
public static final int MSG_GET_CONNECTION_STATUS = 10;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command to the service to close
|
||||||
|
*/
|
||||||
|
public static final int MSG_CLOSE = 11;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command to the service to submit a transaction
|
||||||
|
*/
|
||||||
|
public static final int MSG_SUBMIT_TRANSACTION = 12;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command to the service to get the admin info
|
||||||
|
*/
|
||||||
|
public static final int MSG_GET_ADMIN_INFO = 13;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command to the service to get the pernding transactions
|
||||||
|
*/
|
||||||
|
public static final int MSG_GET_PENDING_TRANSACTIONS = 14;
|
||||||
|
}
|
|
@ -0,0 +1,140 @@
|
||||||
|
package org.ethereum.android.service;
|
||||||
|
|
||||||
|
|
||||||
|
import android.content.ComponentName;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.ServiceConnection;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.HandlerThread;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.os.Message;
|
||||||
|
import android.os.Messenger;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class ServiceConnector {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Incoming message handler. Calls to its binder are sequential!
|
||||||
|
*/
|
||||||
|
protected final IncomingHandler handler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler thread to avoid running on the main UI thread
|
||||||
|
*/
|
||||||
|
protected final HandlerThread handlerThread;
|
||||||
|
|
||||||
|
/** Context of the activity from which this connector was launched */
|
||||||
|
protected Context context;
|
||||||
|
|
||||||
|
/** The class of the service we want to connect to */
|
||||||
|
protected Class serviceClass;
|
||||||
|
|
||||||
|
/** Flag indicating if the service is bound. */
|
||||||
|
boolean isBound;
|
||||||
|
|
||||||
|
/** Sends messages to the service. */
|
||||||
|
Messenger serviceMessenger = null;
|
||||||
|
|
||||||
|
/** Receives messages from the service. */
|
||||||
|
Messenger clientMessenger = null;
|
||||||
|
|
||||||
|
ArrayList<ConnectorHandler> handlers = new ArrayList<>();
|
||||||
|
|
||||||
|
/** Handles incoming messages from service. */
|
||||||
|
class IncomingHandler extends Handler {
|
||||||
|
|
||||||
|
public IncomingHandler(HandlerThread thread) {
|
||||||
|
|
||||||
|
super(thread.getLooper());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleMessage(Message message) {
|
||||||
|
|
||||||
|
boolean isClaimed = false;
|
||||||
|
String identifier = ((Bundle)message.obj).getString("identifier");
|
||||||
|
if (identifier != null) {
|
||||||
|
|
||||||
|
for (ConnectorHandler handler : handlers) {
|
||||||
|
if (identifier.equals(handler.getID())) {
|
||||||
|
isClaimed = handler.handleMessage(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!isClaimed) {
|
||||||
|
super.handleMessage(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class for interacting with the main interface of the service.
|
||||||
|
*/
|
||||||
|
protected ServiceConnection serviceConnection = null;
|
||||||
|
|
||||||
|
public ServiceConnector(Context context, Class serviceClass) {
|
||||||
|
|
||||||
|
this.context = context;
|
||||||
|
this.serviceClass = serviceClass;
|
||||||
|
handlerThread = new HandlerThread("HandlerThread");
|
||||||
|
handlerThread.start();
|
||||||
|
handler = new IncomingHandler(handlerThread);
|
||||||
|
clientMessenger = new Messenger(handler);
|
||||||
|
initializeServiceConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void initializeServiceConnection() {
|
||||||
|
|
||||||
|
serviceConnection = new ServiceConnection() {
|
||||||
|
|
||||||
|
public void onServiceConnected(ComponentName className, IBinder service) {
|
||||||
|
|
||||||
|
// This is called when the connection with the service has been
|
||||||
|
// established, giving us the object we can use to
|
||||||
|
// interact with the service. We are communicating with the
|
||||||
|
// service using a Messenger, so here we get a client-side
|
||||||
|
// representation of that from the raw IBinder object.
|
||||||
|
serviceMessenger = new Messenger(service);
|
||||||
|
isBound = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onServiceDisconnected(ComponentName className) {
|
||||||
|
|
||||||
|
// This is called when the connection with the service has been
|
||||||
|
// unexpectedly disconnected -- that is, its process crashed.
|
||||||
|
serviceMessenger = null;
|
||||||
|
isBound = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Bind to the service */
|
||||||
|
public boolean bindService() {
|
||||||
|
|
||||||
|
if (serviceConnection != null) {
|
||||||
|
Intent intent = new Intent(context, serviceClass);
|
||||||
|
return context.getApplicationContext().bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Unbind from the service */
|
||||||
|
public void unbindService() {
|
||||||
|
|
||||||
|
if (isBound && serviceConnection != null) {
|
||||||
|
context.getApplicationContext().unbindService(serviceConnection);
|
||||||
|
isBound = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerHandler(ConnectorHandler handler) {
|
||||||
|
|
||||||
|
handlers.add(handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -14,9 +14,9 @@ import javax.inject.Singleton;
|
||||||
public class AdminInfo {
|
public class AdminInfo {
|
||||||
|
|
||||||
|
|
||||||
private long startupTimeStamp;
|
protected long startupTimeStamp;
|
||||||
private boolean consensus = true;
|
protected boolean consensus = true;
|
||||||
private List<Long> blockExecTime = new LinkedList<>();
|
protected List<Long> blockExecTime = new LinkedList<>();
|
||||||
|
|
||||||
public AdminInfo() {
|
public AdminInfo() {
|
||||||
this.init();
|
this.init();
|
||||||
|
|
|
@ -14,9 +14,9 @@ import java.util.List;
|
||||||
*/
|
*/
|
||||||
public class PeerInfo {
|
public class PeerInfo {
|
||||||
|
|
||||||
private InetAddress address;
|
protected InetAddress address;
|
||||||
private int port;
|
protected int port;
|
||||||
private String peerId;
|
protected String peerId;
|
||||||
|
|
||||||
private List<Capability> capabilities;
|
private List<Capability> capabilities;
|
||||||
private HelloMessage handshakeHelloMessage;
|
private HelloMessage handshakeHelloMessage;
|
||||||
|
|
Loading…
Reference in New Issue