From 961fb203df59803327ca4d95dba017fe9d88ede0 Mon Sep 17 00:00:00 2001 From: Adrian Tiberius Date: Fri, 26 Jun 2015 12:21:17 +0200 Subject: [PATCH] Implemented remote service using Messenger. --- app/src/main/AndroidManifest.xml | 15 +- .../android_app/ActivityInterface.java | 2 - ...ainActivity.java => AidlMainActivity.java} | 29 +- .../android_app/EthereumApplication.java | 16 +- .../android_app/EthereumRemoteService.java | 10 + .../ethereum/android_app/EthereumService.java | 2 +- .../android_app/RemoteMainActivity.java | 69 +++ .../ethereum/android_app/TestActivity.java | 3 + .../ethereum/android_app/TestsFragment.java | 114 +++- .../main/res/layout/activity_remote_main.xml | 12 + app/src/main/res/layout/fragment_tests.xml | 159 ++++- app/src/main/res/menu/menu_main.xml | 3 +- app/src/main/res/values/strings.xml | 1 + .../src/main/AndroidManifest.xml | 6 +- .../src/main/assets/logback.xml | 2 +- .../org/ethereum/android/EthereumManager.java | 2 - .../android/EthereumRemoteService.java | 16 - .../org/ethereum/android/EthereumService.java | 16 - .../ethereum/android/interop/AdminInfo.java | 82 +++ .../ethereum/android/interop/PeerInfo.java | 61 ++ .../ethereum/android/interop/Transaction.java | 44 ++ .../android/service/ConnectorHandler.java | 10 + .../android/service/EthereumAidlService.java | 101 ++++ .../service/EthereumClientMessage.java | 39 ++ .../android/service/EthereumConnector.java | 391 +++++++++++++ .../service/EthereumRemoteService.java | 542 ++++++++++++++++++ .../EthereumService.java} | 85 +-- .../service/EthereumServiceMessage.java | 76 +++ .../android/service/ServiceConnector.java | 140 +++++ .../java/org/ethereum/manager/AdminInfo.java | 6 +- .../ethereum/net/peerdiscovery/PeerInfo.java | 6 +- 31 files changed, 1915 insertions(+), 145 deletions(-) rename app/src/main/java/org/ethereum/android_app/{MainActivity.java => AidlMainActivity.java} (81%) create mode 100644 app/src/main/java/org/ethereum/android_app/EthereumRemoteService.java create mode 100644 app/src/main/java/org/ethereum/android_app/RemoteMainActivity.java create mode 100644 app/src/main/res/layout/activity_remote_main.xml delete mode 100644 ethereumj-core-android/src/main/java/org/ethereum/android/EthereumRemoteService.java delete mode 100644 ethereumj-core-android/src/main/java/org/ethereum/android/EthereumService.java create mode 100644 ethereumj-core-android/src/main/java/org/ethereum/android/interop/AdminInfo.java create mode 100644 ethereumj-core-android/src/main/java/org/ethereum/android/interop/PeerInfo.java create mode 100644 ethereumj-core-android/src/main/java/org/ethereum/android/interop/Transaction.java create mode 100644 ethereumj-core-android/src/main/java/org/ethereum/android/service/ConnectorHandler.java create mode 100644 ethereumj-core-android/src/main/java/org/ethereum/android/service/EthereumAidlService.java create mode 100644 ethereumj-core-android/src/main/java/org/ethereum/android/service/EthereumClientMessage.java create mode 100644 ethereumj-core-android/src/main/java/org/ethereum/android/service/EthereumConnector.java create mode 100644 ethereumj-core-android/src/main/java/org/ethereum/android/service/EthereumRemoteService.java rename ethereumj-core-android/src/main/java/org/ethereum/android/{EthereumAidlService.java => service/EthereumService.java} (60%) create mode 100644 ethereumj-core-android/src/main/java/org/ethereum/android/service/EthereumServiceMessage.java create mode 100644 ethereumj-core-android/src/main/java/org/ethereum/android/service/ServiceConnector.java diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 6aa61eeb..d16041f6 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -14,7 +14,7 @@ android:largeHeap="true" android:theme="@style/AppTheme" > @@ -28,11 +28,22 @@ + + + + + diff --git a/app/src/main/java/org/ethereum/android_app/ActivityInterface.java b/app/src/main/java/org/ethereum/android_app/ActivityInterface.java index 8dcee763..8bdc6411 100644 --- a/app/src/main/java/org/ethereum/android_app/ActivityInterface.java +++ b/app/src/main/java/org/ethereum/android_app/ActivityInterface.java @@ -1,8 +1,6 @@ package org.ethereum.android_app; -import android.support.v4.app.Fragment; - public interface ActivityInterface { void registerFragment(FragmentInterface fragment); diff --git a/app/src/main/java/org/ethereum/android_app/MainActivity.java b/app/src/main/java/org/ethereum/android_app/AidlMainActivity.java similarity index 81% rename from app/src/main/java/org/ethereum/android_app/MainActivity.java rename to app/src/main/java/org/ethereum/android_app/AidlMainActivity.java index fa6a5add..d2641201 100644 --- a/app/src/main/java/org/ethereum/android_app/MainActivity.java +++ b/app/src/main/java/org/ethereum/android_app/AidlMainActivity.java @@ -4,11 +4,9 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; -import android.os.AsyncTask; 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.os.Bundle; import android.support.v7.app.ActionBarActivity; @@ -16,10 +14,8 @@ import android.support.v7.widget.Toolbar; import android.util.Log; import android.view.Menu; import android.view.MenuItem; -import android.os.Build; import android.widget.Toast; -import org.ethereum.android.EthereumManager; import org.ethereum.android.interop.IEthereumService; import org.ethereum.android.interop.IListener; import org.ethereum.config.SystemProperties; @@ -28,7 +24,7 @@ import java.io.File; import java.util.ArrayList; -public class MainActivity extends ActionBarActivity implements ActivityInterface { +public class AidlMainActivity extends ActionBarActivity implements ActivityInterface { 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 // representation of that from the raw service object. 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 { @@ -93,7 +89,7 @@ public class MainActivity extends ActionBarActivity implements ActivityInterface SystemProperties.CONFIG.activePeerPort(), 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) { 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 // unexpectedly disconnected -- that is, its process crashed. 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.setViewPager(viewPager); - ComponentName myService = startService(new Intent(MainActivity.this, EthereumService.class)); + ComponentName myService = startService(new Intent(AidlMainActivity.this, EthereumService.class)); doBindService(); //StrictMode.enableDefaults(); @@ -133,13 +129,13 @@ public class MainActivity extends ActionBarActivity implements ActivityInterface protected void logMessage(String message) { - MainActivity.consoleLog += message + "\n"; - int consoleLength = MainActivity.consoleLog.length(); + AidlMainActivity.consoleLog += message + "\n"; + int consoleLength = AidlMainActivity.consoleLog.length(); 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 // class name because there is no reason to be able to let other // 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; - Toast.makeText(MainActivity.this, "binding to service", Toast.LENGTH_SHORT).show(); + Toast.makeText(AidlMainActivity.this, "binding to service", Toast.LENGTH_SHORT).show(); } void doUnbindService() { @@ -177,7 +173,7 @@ public class MainActivity extends ActionBarActivity implements ActivityInterface // Detach our existing connection. unbindService(serviceConnection); 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 public boolean onCreateOptionsMenu(Menu menu) { - //return super.onCreateOptionsMenu(menu); getMenuInflater().inflate(R.menu.menu_main, menu); return true; } diff --git a/app/src/main/java/org/ethereum/android_app/EthereumApplication.java b/app/src/main/java/org/ethereum/android_app/EthereumApplication.java index acbc416c..e6931d8f 100644 --- a/app/src/main/java/org/ethereum/android_app/EthereumApplication.java +++ b/app/src/main/java/org/ethereum/android_app/EthereumApplication.java @@ -3,11 +3,23 @@ package org.ethereum.android_app; import android.support.multidex.MultiDexApplication; +import org.ethereum.android.service.EthereumConnector; + public class EthereumApplication extends MultiDexApplication { - @Override public void onCreate() { - super.onCreate(); + EthereumConnector ethereum = null; + @Override public void onCreate() { + + super.onCreate(); + ethereum = new EthereumConnector(this, EthereumRemoteService.class); + ethereum.bindService(); } + @Override + public void onTerminate() { + + super.onTerminate(); + ethereum.unbindService(); + } } \ No newline at end of file diff --git a/app/src/main/java/org/ethereum/android_app/EthereumRemoteService.java b/app/src/main/java/org/ethereum/android_app/EthereumRemoteService.java new file mode 100644 index 00000000..fd91c19e --- /dev/null +++ b/app/src/main/java/org/ethereum/android_app/EthereumRemoteService.java @@ -0,0 +1,10 @@ +package org.ethereum.android_app; + + +public class EthereumRemoteService extends org.ethereum.android.service.EthereumRemoteService { + + public EthereumRemoteService() { + + super(); + } +} diff --git a/app/src/main/java/org/ethereum/android_app/EthereumService.java b/app/src/main/java/org/ethereum/android_app/EthereumService.java index 65d78e92..7ea9d376 100644 --- a/app/src/main/java/org/ethereum/android_app/EthereumService.java +++ b/app/src/main/java/org/ethereum/android_app/EthereumService.java @@ -1,6 +1,6 @@ package org.ethereum.android_app; -import org.ethereum.android.EthereumAidlService; +import org.ethereum.android.service.EthereumAidlService; import org.ethereum.android.interop.IListener; public class EthereumService extends EthereumAidlService { diff --git a/app/src/main/java/org/ethereum/android_app/RemoteMainActivity.java b/app/src/main/java/org/ethereum/android_app/RemoteMainActivity.java new file mode 100644 index 00000000..ef19056b --- /dev/null +++ b/app/src/main/java/org/ethereum/android_app/RemoteMainActivity.java @@ -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 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); + } + } +} diff --git a/app/src/main/java/org/ethereum/android_app/TestActivity.java b/app/src/main/java/org/ethereum/android_app/TestActivity.java index 05cba35a..d7a84cc0 100644 --- a/app/src/main/java/org/ethereum/android_app/TestActivity.java +++ b/app/src/main/java/org/ethereum/android_app/TestActivity.java @@ -10,12 +10,14 @@ public class TestActivity extends ActionBarActivity { @Override protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); setContentView(R.layout.activity_test); } @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_test, menu); return true; @@ -23,6 +25,7 @@ public class TestActivity extends ActionBarActivity { @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. diff --git a/app/src/main/java/org/ethereum/android_app/TestsFragment.java b/app/src/main/java/org/ethereum/android_app/TestsFragment.java index 47d6b825..5db25424 100644 --- a/app/src/main/java/org/ethereum/android_app/TestsFragment.java +++ b/app/src/main/java/org/ethereum/android_app/TestsFragment.java @@ -1,22 +1,132 @@ package org.ethereum.android_app; import android.os.Bundle; +import android.os.Message; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.Button; +import android.widget.TextView; 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 public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 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; } + + 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; + } + } \ No newline at end of file diff --git a/app/src/main/res/layout/activity_remote_main.xml b/app/src/main/res/layout/activity_remote_main.xml new file mode 100644 index 00000000..78df55dc --- /dev/null +++ b/app/src/main/res/layout/activity_remote_main.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/app/src/main/res/layout/fragment_tests.xml b/app/src/main/res/layout/fragment_tests.xml index 43783032..5fb17cf0 100644 --- a/app/src/main/res/layout/fragment_tests.xml +++ b/app/src/main/res/layout/fragment_tests.xml @@ -7,5 +7,162 @@ android:gravity="center" android:text="@string/ethereumj_tests" android:textSize="20sp" - android:layout_centerInParent="true"/> + android:id="@+id/textView2" + android:layout_alignParentTop="true" + android:layout_alignParentLeft="true" + android:layout_alignParentStart="true" /> + + + + + +