Implemented ethereum remote service using aidl.
Added some activity-fragment communication interfaces.
This commit is contained in:
parent
6c53a30ac6
commit
bc618bacc1
|
@ -159,7 +159,7 @@ public class InMemoryBlockStoreTest extends ActivityInstrumentationTestCase2<Tes
|
||||||
blockStore.saveBlock(blocks.get(i), null);
|
blockStore.saveBlock(blocks.get(i), null);
|
||||||
if ( i % 1000 == 0){
|
if ( i % 1000 == 0){
|
||||||
blockStore.flush();
|
blockStore.flush();
|
||||||
assertTrue(blockStore.blocks.size() == 1);
|
//assertTrue(blockStore.blocks.size() == 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,7 +110,6 @@ public class LevelDbDataSourceTest extends ActivityInstrumentationTestCase2<Test
|
||||||
private KeyValueDataSource createDataSource(String name) {
|
private KeyValueDataSource createDataSource(String name) {
|
||||||
|
|
||||||
LevelDbDataSource result = new LevelDbDataSource();
|
LevelDbDataSource result = new LevelDbDataSource();
|
||||||
result.setContext(activity);
|
|
||||||
result.setName(name);
|
result.setName(name);
|
||||||
result.init();
|
result.init();
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -26,6 +26,16 @@
|
||||||
android:name=".TestActivity"
|
android:name=".TestActivity"
|
||||||
android:label="@string/title_activity_test" >
|
android:label="@string/title_activity_test" >
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
|
<service
|
||||||
|
android:name="org.ethereum.android_app.EthereumService"
|
||||||
|
android:enabled="true"
|
||||||
|
android:exported="true"
|
||||||
|
android:process=":ethereum_process" >
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="org.ethereum.android_app.EthereumService" />
|
||||||
|
</intent-filter>
|
||||||
|
</service>
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
package org.ethereum.android_app;
|
||||||
|
|
||||||
|
|
||||||
|
import android.support.v4.app.Fragment;
|
||||||
|
|
||||||
|
public interface ActivityInterface {
|
||||||
|
|
||||||
|
void registerFragment(FragmentInterface fragment);
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
package org.ethereum.android_app;
|
package org.ethereum.android_app;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
|
@ -12,45 +13,54 @@ import android.widget.TextView;
|
||||||
import org.ethereum.android.EthereumManager;
|
import org.ethereum.android.EthereumManager;
|
||||||
import org.ethereum.listener.EthereumListenerAdapter;
|
import org.ethereum.listener.EthereumListenerAdapter;
|
||||||
|
|
||||||
public class ConsoleFragment extends Fragment {
|
public class ConsoleFragment extends Fragment implements FragmentInterface {
|
||||||
|
|
||||||
EthereumManager ethereumManager;
|
EthereumManager ethereumManager;
|
||||||
private TextView console;
|
private TextView console;
|
||||||
|
|
||||||
|
TextViewUpdater consoleUpdater = new TextViewUpdater();
|
||||||
|
|
||||||
|
private class TextViewUpdater implements Runnable {
|
||||||
|
|
||||||
|
private String txt;
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
|
||||||
|
console.setText(txt);
|
||||||
|
}
|
||||||
|
public void setText(String txt) {
|
||||||
|
|
||||||
|
this.txt = txt;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
|
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAttach(Activity activity) {
|
||||||
|
|
||||||
|
super.onAttach(activity);
|
||||||
|
ActivityInterface activityInterface = (ActivityInterface) activity;
|
||||||
|
activityInterface.registerFragment(this);
|
||||||
|
}
|
||||||
|
|
||||||
@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_console, container, false);
|
View view = inflater.inflate(R.layout.fragment_console, container, false);
|
||||||
console = (TextView) view.findViewById(R.id.console);
|
console = (TextView) view.findViewById(R.id.console);
|
||||||
console.setMovementMethod(new ScrollingMovementMethod());
|
console.setMovementMethod(new ScrollingMovementMethod());
|
||||||
console.append("aaaa");
|
|
||||||
return view;
|
return view;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setEthereumManager(EthereumManager ethereumManager) {
|
public void onMessage(String message) {
|
||||||
|
|
||||||
this.ethereumManager = ethereumManager;
|
consoleUpdater.setText(message);
|
||||||
/*
|
ConsoleFragment.this.console.post(consoleUpdater);
|
||||||
ethereumManager.addListener(new EthereumListenerAdapter() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void trace(final String output) {
|
|
||||||
getActivity().runOnUiThread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
//console.append(output);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateDuration(long duration) {
|
|
||||||
console.append(String.valueOf(duration/1000) + "seconds");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
package org.ethereum.android_app;
|
||||||
|
|
||||||
|
import org.ethereum.android.EthereumAidlService;
|
||||||
|
import org.ethereum.android.interop.IListener;
|
||||||
|
|
||||||
|
public class EthereumService extends EthereumAidlService {
|
||||||
|
|
||||||
|
public EthereumService() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void broadcastMessage(String message) {
|
||||||
|
|
||||||
|
updateLog(message);
|
||||||
|
for (IListener listener: clientListeners) {
|
||||||
|
try {
|
||||||
|
listener.trace(message);
|
||||||
|
} catch (Exception e) {
|
||||||
|
// Remove listener
|
||||||
|
clientListeners.remove(listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateLog(String message) {
|
||||||
|
|
||||||
|
EthereumService.log += message;
|
||||||
|
int logLength = EthereumService.log.length();
|
||||||
|
if (logLength > 5000) {
|
||||||
|
EthereumService.log = EthereumService.log.substring(2500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
package org.ethereum.android_app;
|
||||||
|
|
||||||
|
public interface FragmentInterface {
|
||||||
|
|
||||||
|
void onMessage(String message);
|
||||||
|
}
|
|
@ -1,8 +1,14 @@
|
||||||
package org.ethereum.android_app;
|
package org.ethereum.android_app;
|
||||||
|
|
||||||
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.ServiceConnection;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
|
import android.os.IBinder;
|
||||||
|
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;
|
||||||
|
@ -11,24 +17,96 @@ 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.os.Build;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import org.ethereum.android.EthereumManager;
|
import org.ethereum.android.EthereumManager;
|
||||||
|
import org.ethereum.android.interop.IEthereumService;
|
||||||
|
import org.ethereum.android.interop.IListener;
|
||||||
import org.ethereum.config.SystemProperties;
|
import org.ethereum.config.SystemProperties;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
|
||||||
public class MainActivity extends ActionBarActivity {
|
public class MainActivity extends ActionBarActivity implements ActivityInterface {
|
||||||
|
|
||||||
private static final String TAG = "MyActivity";
|
private static final String TAG = "MyActivity";
|
||||||
private static Integer quit = 0;
|
|
||||||
|
|
||||||
private Toolbar toolbar;
|
private Toolbar toolbar;
|
||||||
private ViewPager viewPager;
|
private ViewPager viewPager;
|
||||||
private SlidingTabLayout tabs;
|
private SlidingTabLayout tabs;
|
||||||
private TabsPagerAdapter adapter;
|
private TabsPagerAdapter adapter;
|
||||||
|
protected ArrayList<FragmentInterface> fragments = new ArrayList<>();
|
||||||
|
|
||||||
public EthereumManager ethereumManager = null;
|
protected static String consoleLog = "";
|
||||||
|
|
||||||
|
/** Ethereum Aidl Service. */
|
||||||
|
IEthereumService ethereumService = null;
|
||||||
|
|
||||||
|
IListener.Stub ethereumListener = new IListener.Stub() {
|
||||||
|
|
||||||
|
public void trace(String message) throws RemoteException {
|
||||||
|
|
||||||
|
logMessage(message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Flag indicating whether we have called bind on the service. */
|
||||||
|
boolean isBound;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class for interacting with the main interface of the service.
|
||||||
|
*/
|
||||||
|
protected ServiceConnection 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 service object we can use to
|
||||||
|
// interact with the service. We are communicating with our
|
||||||
|
// service through an IDL interface, so get a client-side
|
||||||
|
// representation of that from the raw service object.
|
||||||
|
ethereumService = IEthereumService.Stub.asInterface(service);
|
||||||
|
Toast.makeText(MainActivity.this, "service attached", Toast.LENGTH_SHORT).show();
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
|
||||||
|
// Try to load blocks dump file from /sdcard/poc-9-492k.dmp
|
||||||
|
String blocksDump = null;
|
||||||
|
File extStore = Environment.getExternalStorageDirectory();
|
||||||
|
if (extStore.exists()) {
|
||||||
|
String sdcardPath = extStore.getAbsolutePath();
|
||||||
|
File dumpFile = new File(extStore, "poc-9-492k.dmp");
|
||||||
|
if (dumpFile.exists()) {
|
||||||
|
blocksDump = dumpFile.getAbsolutePath();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Start json rpc server
|
||||||
|
ethereumService.startJsonRpcServer();
|
||||||
|
// If blocks dump not found, connect to peer
|
||||||
|
if (blocksDump != null) {
|
||||||
|
ethereumService.loadBlocks(blocksDump);
|
||||||
|
} else {
|
||||||
|
ethereumService.addListener(ethereumListener);
|
||||||
|
ethereumService.connect(SystemProperties.CONFIG.activePeerIP(),
|
||||||
|
SystemProperties.CONFIG.activePeerPort(),
|
||||||
|
SystemProperties.CONFIG.activePeerNodeid());
|
||||||
|
}
|
||||||
|
Toast.makeText(MainActivity.this, "connected to service", Toast.LENGTH_SHORT).show();
|
||||||
|
} catch (Exception e) {
|
||||||
|
logMessage("Error adding listener: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onServiceDisconnected(ComponentName className) {
|
||||||
|
|
||||||
|
// This is called when the connection with the service has been
|
||||||
|
// unexpectedly disconnected -- that is, its process crashed.
|
||||||
|
ethereumService = null;
|
||||||
|
Toast.makeText(MainActivity.this, "service disconnected", Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
@ -39,17 +117,7 @@ public class MainActivity extends ActionBarActivity {
|
||||||
toolbar = (Toolbar) findViewById(R.id.tool_bar);
|
toolbar = (Toolbar) findViewById(R.id.tool_bar);
|
||||||
setSupportActionBar(toolbar);
|
setSupportActionBar(toolbar);
|
||||||
|
|
||||||
String databaseFolder = null;
|
adapter = new TabsPagerAdapter(getSupportFragmentManager());
|
||||||
File extStore = Environment.getExternalStorageDirectory();
|
|
||||||
if (extStore.exists()) {
|
|
||||||
databaseFolder = extStore.getAbsolutePath();
|
|
||||||
} else {
|
|
||||||
databaseFolder = getApplicationInfo().dataDir;
|
|
||||||
}
|
|
||||||
|
|
||||||
ethereumManager = new EthereumManager(this, databaseFolder);
|
|
||||||
|
|
||||||
adapter = new TabsPagerAdapter(getSupportFragmentManager(), ethereumManager);
|
|
||||||
viewPager = (ViewPager) findViewById(R.id.pager);
|
viewPager = (ViewPager) findViewById(R.id.pager);
|
||||||
viewPager.setAdapter(adapter);;
|
viewPager.setAdapter(adapter);;
|
||||||
|
|
||||||
|
@ -57,21 +125,72 @@ public class MainActivity extends ActionBarActivity {
|
||||||
tabs.setDistributeEvenly(true);
|
tabs.setDistributeEvenly(true);
|
||||||
tabs.setViewPager(viewPager);
|
tabs.setViewPager(viewPager);
|
||||||
|
|
||||||
|
ComponentName myService = startService(new Intent("org.ethereum.android_app.EthereumService"));
|
||||||
|
doBindService();
|
||||||
|
|
||||||
//StrictMode.enableDefaults();
|
//StrictMode.enableDefaults();
|
||||||
|
}
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
|
protected void logMessage(String message) {
|
||||||
new PostTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
|
||||||
else
|
|
||||||
new PostTask().execute();
|
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
|
MainActivity.consoleLog += message + "\n";
|
||||||
new JsonRpcTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
int consoleLength = MainActivity.consoleLog.length();
|
||||||
else
|
if (consoleLength > 5000) {
|
||||||
new JsonRpcTask().execute();
|
MainActivity.consoleLog = MainActivity.consoleLog.substring(4000);
|
||||||
|
}
|
||||||
|
|
||||||
|
broadcastFragments(MainActivity.consoleLog);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected void broadcastFragments(String message) {
|
||||||
|
|
||||||
|
for (FragmentInterface fragment : fragments) {
|
||||||
|
fragment.onMessage(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void doBindService() {
|
||||||
|
|
||||||
|
// Establish a connection with the service. We use an explicit
|
||||||
|
// class name because there is no reason to be able to let other
|
||||||
|
// applications replace our component.
|
||||||
|
bindService(new Intent("org.ethereum.android_app.EthereumService"), serviceConnection, Context.BIND_AUTO_CREATE);
|
||||||
|
isBound = true;
|
||||||
|
Toast.makeText(MainActivity.this, "binding to service", Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void doUnbindService() {
|
||||||
|
|
||||||
|
if (isBound) {
|
||||||
|
// If we have received the service, and hence registered with
|
||||||
|
// it, then now is the time to unregister.
|
||||||
|
if (ethereumService != null) {
|
||||||
|
try {
|
||||||
|
ethereumService.removeListener(ethereumListener);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
// There is nothing special we need to do if the service
|
||||||
|
// has crashed.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detach our existing connection.
|
||||||
|
unbindService(serviceConnection);
|
||||||
|
isBound = false;
|
||||||
|
Toast.makeText(MainActivity.this, "unbinding from service", Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerFragment(FragmentInterface fragment) {
|
||||||
|
|
||||||
|
if (!fragments.contains(fragment)) {
|
||||||
|
fragments.add(fragment);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreateOptionsMenu(Menu menu) {
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
|
|
||||||
//return super.onCreateOptionsMenu(menu);
|
//return super.onCreateOptionsMenu(menu);
|
||||||
getMenuInflater().inflate(R.menu.menu_main, menu);
|
getMenuInflater().inflate(R.menu.menu_main, menu);
|
||||||
return true;
|
return true;
|
||||||
|
@ -79,6 +198,7 @@ public class MainActivity 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.
|
||||||
|
@ -94,97 +214,13 @@ public class MainActivity extends ActionBarActivity {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDestroy() {
|
protected void onDestroy() {
|
||||||
|
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
if (ethereumManager != null) {
|
doUnbindService();
|
||||||
ethereumManager.onDestroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The definition of our task class
|
|
||||||
private class PostTask extends AsyncTask<Context, Integer, String> {
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPreExecute() {
|
|
||||||
super.onPreExecute();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String doInBackground(Context... params) {
|
|
||||||
Log.v(TAG, "111");
|
|
||||||
|
|
||||||
Log.v(TAG, "222");
|
|
||||||
ThreadGroup group = new ThreadGroup("threadGroup");
|
|
||||||
new Thread(group, new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
long duration = ethereumManager.connect(SystemProperties.CONFIG.databaseDir() + File.separator + "poc-9-492k.dmp");
|
|
||||||
}
|
|
||||||
}, "EthereumConnect", 32768000).start();
|
|
||||||
|
|
||||||
//ConsoleFragment consoleeFrag = (ConsoleFragment)getSupportFragmentManager().findFragmentById(R.id.console);
|
|
||||||
//consoleeFrag.updateDuration(duration);
|
|
||||||
Log.v(TAG, "333");
|
|
||||||
while(true) {
|
|
||||||
|
|
||||||
try {
|
|
||||||
Thread.sleep(50);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (quit == 1) {
|
|
||||||
Log.v(TAG, "Ending background process.");
|
|
||||||
return "All Done!";
|
|
||||||
}
|
|
||||||
|
|
||||||
//publishProgress(1111);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onProgressUpdate(Integer... values) {
|
|
||||||
super.onProgressUpdate(values);
|
|
||||||
Log.v(TAG, values[0].toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPostExecute(String result) {
|
|
||||||
super.onPostExecute(result);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// The definition of our task class
|
|
||||||
private class JsonRpcTask extends AsyncTask<Context, Integer, String> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPreExecute() {
|
|
||||||
super.onPreExecute();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String doInBackground(Context... params) {
|
|
||||||
Log.v(TAG, "444");
|
|
||||||
try {
|
|
||||||
if (ethereumManager != null) {
|
|
||||||
ethereumManager.startJsonRpc();
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
}
|
|
||||||
Log.v(TAG, "555");
|
|
||||||
return "done";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onProgressUpdate(Integer... values) {
|
|
||||||
super.onProgressUpdate(values);
|
|
||||||
Log.v(TAG, values[0].toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPostExecute(String result) {
|
|
||||||
super.onPostExecute(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,13 +10,11 @@ public class TabsPagerAdapter extends FragmentPagerAdapter {
|
||||||
|
|
||||||
int tabsCount;
|
int tabsCount;
|
||||||
private String[] tabTitles = { "Console", "Tests" };
|
private String[] tabTitles = { "Console", "Tests" };
|
||||||
private EthereumManager ethereumManager;
|
|
||||||
|
|
||||||
public TabsPagerAdapter(FragmentManager fragmentManager, EthereumManager ethereumManager) {
|
public TabsPagerAdapter(FragmentManager fragmentManager) {
|
||||||
|
|
||||||
super(fragmentManager);
|
super(fragmentManager);
|
||||||
this.tabsCount = tabTitles.length;
|
this.tabsCount = tabTitles.length;
|
||||||
this.ethereumManager = ethereumManager;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -25,7 +23,6 @@ public class TabsPagerAdapter extends FragmentPagerAdapter {
|
||||||
switch (index) {
|
switch (index) {
|
||||||
case 0:
|
case 0:
|
||||||
ConsoleFragment consoleFragment = new ConsoleFragment();
|
ConsoleFragment consoleFragment = new ConsoleFragment();
|
||||||
consoleFragment.setEthereumManager(ethereumManager);
|
|
||||||
return consoleFragment;
|
return consoleFragment;
|
||||||
case 1:
|
case 1:
|
||||||
TestsFragment testsFragment = new TestsFragment();
|
TestsFragment testsFragment = new TestsFragment();
|
||||||
|
|
|
@ -4,11 +4,14 @@
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
<TextView android:layout_width="fill_parent"
|
<TextView android:layout_width="fill_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:gravity="top"
|
|
||||||
android:text="@string/console_output"
|
|
||||||
android:textSize="14sp"
|
android:textSize="14sp"
|
||||||
android:layout_centerInParent="true"
|
android:layout_centerInParent="true"
|
||||||
android:id="@+id/console"/>
|
android:id="@+id/console"
|
||||||
|
android:gravity="bottom"
|
||||||
|
android:scrollbars="vertical"
|
||||||
|
android:scrollbarStyle="insideOverlay"
|
||||||
|
android:scrollbarSize="25dip"
|
||||||
|
android:scrollbarFadeDuration="0"/>
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,30 @@
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.ethereum.android">
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
<application android:allowBackup="true" android:label="@string/app_name">
|
package="org.ethereum.android" >
|
||||||
|
|
||||||
|
<application
|
||||||
|
android:allowBackup="true"
|
||||||
|
android:label="@string/app_name" >
|
||||||
|
<service
|
||||||
|
android:name=".EthereumAidlService"
|
||||||
|
android:enabled="true"
|
||||||
|
android:exported="true"
|
||||||
|
android:process=":ethereum_process" >
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="org.ethereum.android.IEthereumAidl" />
|
||||||
|
</intent-filter>
|
||||||
|
</service>
|
||||||
|
<service
|
||||||
|
android:name=".EthereumRemoteService"
|
||||||
|
android:enabled="true"
|
||||||
|
android:exported="true"
|
||||||
|
android:process=":ethereum_process" >
|
||||||
|
</service>
|
||||||
|
<service
|
||||||
|
android:name=".EthereumService"
|
||||||
|
android:enabled="true"
|
||||||
|
android:exported="true" >
|
||||||
|
</service>
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
package org.ethereum.android.interop;
|
||||||
|
|
||||||
|
interface IAsyncCallback {
|
||||||
|
|
||||||
|
void handleResponse(String name);
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package org.ethereum.android.interop;
|
||||||
|
|
||||||
|
import org.ethereum.android.interop.IListener;
|
||||||
|
import org.ethereum.android.interop.IAsyncCallback;
|
||||||
|
|
||||||
|
oneway interface IEthereumService {
|
||||||
|
|
||||||
|
void loadBlocks(String dumpFile);
|
||||||
|
void connect(String ip, int port, String remoteId);
|
||||||
|
void startJsonRpcServer();
|
||||||
|
void addListener(IListener listener);
|
||||||
|
void removeListener(IListener listener);
|
||||||
|
void getLog(IAsyncCallback callback);
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
package org.ethereum.android.interop;
|
||||||
|
|
||||||
|
oneway interface IListener {
|
||||||
|
|
||||||
|
void trace(String output);
|
||||||
|
}
|
|
@ -0,0 +1,181 @@
|
||||||
|
package org.ethereum.android;
|
||||||
|
|
||||||
|
import android.app.Service;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.os.RemoteException;
|
||||||
|
|
||||||
|
import org.ethereum.android.di.components.DaggerEthereumComponent;
|
||||||
|
import org.ethereum.android.di.modules.EthereumModule;
|
||||||
|
import org.ethereum.android.jsonrpc.JsonRpcServer;
|
||||||
|
import org.ethereum.android.manager.BlockLoader;
|
||||||
|
import org.ethereum.config.SystemProperties;
|
||||||
|
import org.ethereum.core.*;
|
||||||
|
import org.ethereum.facade.Ethereum;
|
||||||
|
import org.ethereum.android.interop.*;
|
||||||
|
import org.ethereum.net.p2p.HelloMessage;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class EthereumAidlService extends Service {
|
||||||
|
|
||||||
|
protected Ethereum ethereum = null;
|
||||||
|
|
||||||
|
protected JsonRpcServer jsonRpcServer;
|
||||||
|
|
||||||
|
protected ArrayList<IListener> clientListeners = new ArrayList<>();
|
||||||
|
|
||||||
|
public static String log = "";
|
||||||
|
|
||||||
|
public EthereumAidlService() {
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void broadcastMessage(String message) {
|
||||||
|
|
||||||
|
for (IListener listener: clientListeners) {
|
||||||
|
try {
|
||||||
|
listener.trace(message);
|
||||||
|
} catch (Exception e) {
|
||||||
|
// Remove listener
|
||||||
|
clientListeners.remove(listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate() {
|
||||||
|
|
||||||
|
super.onCreate();
|
||||||
|
initializeEthereum();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void initializeEthereum() {
|
||||||
|
|
||||||
|
System.setProperty("sun.arch.data.model", "32");
|
||||||
|
System.setProperty("leveldb.mmap", "false");
|
||||||
|
|
||||||
|
String databaseFolder = getApplicationInfo().dataDir;
|
||||||
|
System.out.println("Database folder: " + databaseFolder);
|
||||||
|
SystemProperties.CONFIG.setDataBaseDir(databaseFolder);
|
||||||
|
|
||||||
|
ethereum = DaggerEthereumComponent.builder()
|
||||||
|
.ethereumModule(new EthereumModule(this))
|
||||||
|
.build().ethereum();
|
||||||
|
ethereum.addListener(new EthereumListener());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||||
|
|
||||||
|
return START_REDELIVER_INTENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBinder onBind(Intent intent) {
|
||||||
|
|
||||||
|
return mBinder;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
|
||||||
|
ethereum.connect(ip, port, remoteId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addListener(IListener listener) throws RemoteException {
|
||||||
|
|
||||||
|
if (!clientListeners.contains(listener)) {
|
||||||
|
clientListeners.add(listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeListener(IListener listener) throws RemoteException {
|
||||||
|
|
||||||
|
if (clientListeners.contains(listener)) {
|
||||||
|
clientListeners.remove(listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void trace(String output) {
|
||||||
|
|
||||||
|
broadcastMessage(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBlock(org.ethereum.core.Block block, List<TransactionReceipt> receipts) {
|
||||||
|
|
||||||
|
broadcastMessage("Added block.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRecvMessage(org.ethereum.net.message.Message message) {
|
||||||
|
|
||||||
|
broadcastMessage("Received message: " + message.getCommand().name());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSendMessage(org.ethereum.net.message.Message message) {
|
||||||
|
|
||||||
|
broadcastMessage("Sending message: " + message.getCommand().name());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPeerDisconnect(String host, long port) {
|
||||||
|
|
||||||
|
broadcastMessage("Peer disconnected: " + host + ":" + port);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPendingTransactionsReceived(Set<Transaction> transactions) {
|
||||||
|
|
||||||
|
broadcastMessage("Pending transactions received: " + transactions.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSyncDone() {
|
||||||
|
|
||||||
|
broadcastMessage("Sync done");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNoConnections() {
|
||||||
|
|
||||||
|
broadcastMessage("No connections");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onHandShakePeer(HelloMessage helloMessage) {
|
||||||
|
|
||||||
|
broadcastMessage("Peer handshaked: " + helloMessage.getCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onVMTraceCreated(String transactionHash, String trace) {
|
||||||
|
|
||||||
|
broadcastMessage("Trace created: " + " - ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -80,7 +80,6 @@ public class EthereumManager {
|
||||||
public void close() {
|
public void close() {
|
||||||
|
|
||||||
ethereum.close();
|
ethereum.close();
|
||||||
OpenHelperManager.releaseHelper();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,12 +26,22 @@ import java.util.concurrent.Callable;
|
||||||
|
|
||||||
public class OrmLiteBlockStoreDatabase extends OrmLiteSqliteOpenHelper implements BlockStoreDatabase {
|
public class OrmLiteBlockStoreDatabase extends OrmLiteSqliteOpenHelper implements BlockStoreDatabase {
|
||||||
|
|
||||||
|
private static OrmLiteBlockStoreDatabase instance;
|
||||||
|
|
||||||
private static final String DATABASE_NAME = "blockchain.db";
|
private static final String DATABASE_NAME = "blockchain.db";
|
||||||
private static final int DATABASE_VERSION = 1;
|
private static final int DATABASE_VERSION = 1;
|
||||||
|
|
||||||
private Dao<BlockVO, Integer> blockDao = null;
|
private Dao<BlockVO, Integer> blockDao = null;
|
||||||
private Dao<TransactionReceiptVO, Integer> transactionDao = null;
|
private Dao<TransactionReceiptVO, Integer> transactionDao = null;
|
||||||
|
|
||||||
|
public static synchronized OrmLiteBlockStoreDatabase getHelper(Context context)
|
||||||
|
{
|
||||||
|
if (instance == null)
|
||||||
|
instance = new OrmLiteBlockStoreDatabase(context);
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
public OrmLiteBlockStoreDatabase(Context context) {
|
public OrmLiteBlockStoreDatabase(Context context) {
|
||||||
super(context, SystemProperties.CONFIG.databaseDir()
|
super(context, SystemProperties.CONFIG.databaseDir()
|
||||||
+ File.separator + DATABASE_NAME, null, DATABASE_VERSION);
|
+ File.separator + DATABASE_NAME, null, DATABASE_VERSION);
|
||||||
|
|
|
@ -2,8 +2,6 @@ package org.ethereum.android.di.modules;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
import com.j256.ormlite.android.apptools.OpenHelperManager;
|
|
||||||
|
|
||||||
import org.ethereum.android.datasource.LevelDbDataSource;
|
import org.ethereum.android.datasource.LevelDbDataSource;
|
||||||
import org.ethereum.android.db.InMemoryBlockStore;
|
import org.ethereum.android.db.InMemoryBlockStore;
|
||||||
import org.ethereum.android.db.OrmLiteBlockStoreDatabase;
|
import org.ethereum.android.db.OrmLiteBlockStoreDatabase;
|
||||||
|
@ -75,7 +73,7 @@ public class EthereumModule {
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
BlockStore provideBlockStore() {
|
BlockStore provideBlockStore() {
|
||||||
OrmLiteBlockStoreDatabase database = OpenHelperManager.getHelper(context, OrmLiteBlockStoreDatabase.class);
|
OrmLiteBlockStoreDatabase database = OrmLiteBlockStoreDatabase.getHelper(context);
|
||||||
return new InMemoryBlockStore(database);
|
return new InMemoryBlockStore(database);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
package org.ethereum.android.interop;
|
||||||
|
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
|
||||||
|
public class Block extends org.ethereum.core.Block implements Parcelable {
|
||||||
|
|
||||||
|
public Block(byte[] rawData) {
|
||||||
|
|
||||||
|
super(rawData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Block(Parcel in) {
|
||||||
|
|
||||||
|
super(null);
|
||||||
|
rlpEncoded = new byte[in.readInt()];
|
||||||
|
in.readByteArray(rlpEncoded);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(Parcel parcel, int i) {
|
||||||
|
|
||||||
|
byte[] data = getEncoded();
|
||||||
|
parcel.writeInt(data.length);
|
||||||
|
parcel.writeByteArray(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int describeContents() {
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
|
||||||
|
|
||||||
|
public Block createFromParcel(Parcel in) {
|
||||||
|
|
||||||
|
return new Block(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Block[] newArray(int size) {
|
||||||
|
|
||||||
|
return new Block[size];
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
|
@ -46,7 +46,7 @@ public class Block {
|
||||||
|
|
||||||
/* Private */
|
/* Private */
|
||||||
|
|
||||||
private byte[] rlpEncoded;
|
protected byte[] rlpEncoded;
|
||||||
private boolean parsed = false;
|
private boolean parsed = false;
|
||||||
|
|
||||||
private Trie txsState;
|
private Trie txsState;
|
||||||
|
|
|
@ -16,7 +16,7 @@ import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import javax.swing.*;
|
//import javax.swing.*;
|
||||||
|
|
||||||
public class Utils {
|
public class Utils {
|
||||||
|
|
||||||
|
@ -51,11 +51,13 @@ public class Utils {
|
||||||
return formatter.format(date);
|
return formatter.format(date);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
public static ImageIcon getImageIcon(String resource) {
|
public static ImageIcon getImageIcon(String resource) {
|
||||||
URL imageURL = ClassLoader.getSystemResource(resource);
|
URL imageURL = ClassLoader.getSystemResource(resource);
|
||||||
ImageIcon image = new ImageIcon(imageURL);
|
ImageIcon image = new ImageIcon(imageURL);
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
static BigInteger _1000_ = new BigInteger("1000");
|
static BigInteger _1000_ = new BigInteger("1000");
|
||||||
|
|
||||||
|
|
|
@ -64,19 +64,19 @@ peer.discovery.workers = 3
|
||||||
|
|
||||||
# connection timeout for trying to
|
# connection timeout for trying to
|
||||||
# connect to a peer [seconds]
|
# connect to a peer [seconds]
|
||||||
peer.connection.timeout = 2
|
peer.connection.timeout = 300
|
||||||
|
|
||||||
# the time we wait to the network
|
# the time we wait to the network
|
||||||
# to approve the transaction, the
|
# to approve the transaction, the
|
||||||
# transaction got approved when
|
# transaction got approved when
|
||||||
# include into a transactions msg
|
# include into a transactions msg
|
||||||
# retrieved from the peer [seconds]
|
# retrieved from the peer [seconds]
|
||||||
transaction.approve.timeout = 15
|
transaction.approve.timeout = 300
|
||||||
|
|
||||||
# the parameter specifies how much
|
# the parameter specifies how much
|
||||||
# time we will wait for a message
|
# time we will wait for a message
|
||||||
# to come before closing the channel
|
# to come before closing the channel
|
||||||
peer.channel.read.timeout = 30
|
peer.channel.read.timeout = 300
|
||||||
|
|
||||||
# default directory where we keep
|
# default directory where we keep
|
||||||
# basic Serpent samples relative
|
# basic Serpent samples relative
|
||||||
|
|
Loading…
Reference in New Issue