- Move the classes around
  - Split into Activity and Service
  - Add status bar notification
  - More config changes
This commit is contained in:
zzz
2011-06-06 13:47:47 +00:00
parent 7e84451ac3
commit 95189c8f53
8 changed files with 311 additions and 95 deletions

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="net.i2p.router"
package="net.i2p.android.router"
android.versionCode="0"
android.versionName="0.0.0"
android:installLocation="preferExternal"
@@ -11,8 +11,12 @@
<!-- 3 required for NDK -->
<uses-sdk android:minSdkVersion="3" />
<application android:label="@string/app_name">
<activity android:name="I2PAndroid"
<application android:label="@string/app_name"
android:icon="@drawable/ic_launcher_itoopie" >
<service android:name=".service.RouterService"
android:label="@string/app_name"
android:icon="@drawable/ic_launcher_itoopie" />
<activity android:name=".activity.MainActivity"
android:label="@string/app_name"
android:icon="@drawable/ic_launcher_itoopie"
android:launchMode="singleTask" >

View File

@@ -16,15 +16,30 @@ time.disabled=true
i2p.dummyClientFacade=true
i2cp.disableInterface=true
#
##### Tunnels
#
router.inboundPool.backupQuantity=0
router.inboundPool.length=2
router.inboundPool.lengthVariance=0
router.inboundPool.quantity=2
router.outboundPool.backupQuantity=0
router.outboundPool.length=2
router.outboundPool.lengthVariance=0
router.outboundPool.quantity=2
router.maxParticipatingTunnels=0
router.sharePercentage=10
#
##### Transport
#
i2np.bandwidth.inboundKBytesPerSecond=100
i2np.bandwidth.outboundKBytesPerSecond=30
#
# NTCP
#
#i2np.ntcp.enable=false
i2np.ntcp.maxConnections=8
i2np.ntcp.maxConnections=12
#
# UDP crashes the JVM, don't know why
# UDP disabled for now
#
i2np.udp.enable=false
i2np.udp.maxConnections=12

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">I2PAndroid</string>
<string name="app_name">I2P</string>
</resources>

View File

@@ -0,0 +1,65 @@
package net.i2p.android.router.activity;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.os.Bundle;
public abstract class I2PActivityBase extends Activity {
protected String _myDir;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
_myDir = getFilesDir().getAbsolutePath();
}
@Override
public void onRestart()
{
System.err.println(this + " onRestart called");
super.onRestart();
}
@Override
public void onStart()
{
System.err.println(this + " onStart called");
super.onStart();
Intent intent = new Intent();
intent.setClassName(this, "net.i2p.android.router.service.RouterService");
System.err.println(this + " calling startService");
ComponentName name = startService(intent);
System.err.println(this + " got from startService: " + name);
}
@Override
public void onResume()
{
System.err.println(this + " onResume called");
super.onResume();
}
@Override
public void onPause()
{
System.err.println(this + " onPause called");
super.onPause();
}
@Override
public void onStop()
{
System.err.println(this + " onStop called");
super.onStop();
}
@Override
public void onDestroy()
{
System.err.println(this + "onDestroy called");
super.onDestroy();
}
}

View File

@@ -0,0 +1,16 @@
package net.i2p.android.router.activity;
import android.os.Bundle;
import net.i2p.android.router.R;
public class MainActivity extends I2PActivityBase {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}

View File

@@ -1,13 +1,11 @@
package net.i2p.router;
package net.i2p.android.router.service;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.content.res.Resources.NotFoundException;
import android.os.Build;
import android.os.Bundle;
import java.io.File;
import java.io.FileOutputStream;
@@ -16,88 +14,25 @@ import java.io.IOException;
import java.util.List;
import java.util.Properties;
import net.i2p.android.router.R;
import net.i2p.data.DataHelper;
import net.i2p.router.Router;
import net.i2p.router.RouterContext;
import net.i2p.router.RouterLaunch;
import net.i2p.util.OrderedProperties;
import net.i2p.util.NativeBigInteger;
public class I2PAndroid extends Activity
{
static Context _context;
private String _myDir;
class Init {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
private final Context ctx;
private final String myDir;
_context = this; // Activity extends Context
_myDir = getFilesDir().getAbsolutePath();
debugStuff();
initialize();
// 300ms per run on emulator on eeepc
// 5x slower than java on my server and 50x slower than native on my server
// 33 ms native 29 ms java moto droid 2.2.2
NativeBigInteger.main(null);
public Init(Context c) {
ctx = c;
myDir = c.getFilesDir().getAbsolutePath();
}
public void onRestart()
{
System.err.println("onRestart called");
super.onRestart();
}
public void onStart()
{
System.err.println("onStart called");
super.onStart();
// net.i2p.crypto.DSAEngine.main(null);
RouterLaunch.main(null);
System.err.println("Router.main finished");
}
public void onResume()
{
System.err.println("onResume called");
super.onResume();
}
public void onPause()
{
System.err.println("onPause called");
super.onPause();
}
public void onStop()
{
System.err.println("onStop called");
super.onStop();
// from routerconsole ContextHelper
List contexts = RouterContext.listContexts();
if ( (contexts == null) || (contexts.isEmpty()) )
throw new IllegalStateException("No contexts. This is usually because the router is either starting up or shutting down.");
RouterContext ctx = (RouterContext)contexts.get(0);
// shutdown() doesn't return so use shutdownGracefully()
ctx.router().shutdownGracefully(Router.EXIT_HARD);
System.err.println("shutdown complete");
}
public void onDestroy()
{
System.err.println("onDestroy called");
super.onDestroy();
}
public static Context getContext() {
return _context;
}
private void debugStuff() {
void debugStuff() {
System.err.println("java.io.tmpdir" + ": " + System.getProperty("java.io.tmpdir"));
System.err.println("java.vendor" + ": " + System.getProperty("java.vendor"));
System.err.println("java.version" + ": " + System.getProperty("java.version"));
@@ -107,8 +42,8 @@ public class I2PAndroid extends Activity
System.err.println("user.dir" + ": " + System.getProperty("user.dir"));
System.err.println("user.home" + ": " + System.getProperty("user.home"));
System.err.println("user.name" + ": " + System.getProperty("user.name"));
System.err.println("getFilesDir()" + ": " + _myDir);
System.err.println("Package" + ": " + getPackageName());
System.err.println("getFilesDir()" + ": " + myDir);
System.err.println("Package" + ": " + ctx.getPackageName());
System.err.println("Version" + ": " + getOurVersion());
System.err.println("MODEL" + ": " + Build.MODEL);
System.err.println("DISPLAY" + ": " + Build.DISPLAY);
@@ -117,8 +52,8 @@ public class I2PAndroid extends Activity
}
private String getOurVersion() {
PackageManager pm = getPackageManager();
String us = getPackageName();
PackageManager pm = ctx.getPackageManager();
String us = ctx.getPackageName();
try {
PackageInfo pi = pm.getPackageInfo(us, 0);
System.err.println("VersionCode" + ": " + pi.versionCode);
@@ -128,15 +63,15 @@ public class I2PAndroid extends Activity
return "??";
}
private void initialize() {
void initialize() {
mergeResourceToFile(R.raw.router_config, "router.config");
mergeResourceToFile(R.raw.logger_config, "logger.config");
copyResourceToFile(R.raw.blocklist_txt, "blocklist.txt");
// Set up the locations so Router and WorkingDir can find them
System.setProperty("i2p.dir.base", _myDir);
System.setProperty("i2p.dir.config", _myDir);
System.setProperty("wrapper.logfile", _myDir + "/wrapper.log");
System.setProperty("i2p.dir.base", myDir);
System.setProperty("i2p.dir.config", myDir);
System.setProperty("wrapper.logfile", myDir + "/wrapper.log");
}
private void copyResourceToFile(int resID, String f) {
@@ -147,8 +82,8 @@ public class I2PAndroid extends Activity
byte buf[] = new byte[4096];
try {
// Context methods
in = getResources().openRawResource(resID);
out = openFileOutput(f, 0);
in = ctx.getResources().openRawResource(resID);
out = ctx.openFileOutput(f, 0);
int read = 0;
while ( (read = in.read(buf)) != -1)
@@ -174,12 +109,11 @@ public class I2PAndroid extends Activity
byte buf[] = new byte[4096];
try {
Properties props = new OrderedProperties();
// Context methods
in = getResources().openRawResource(resID);
in = ctx.getResources().openRawResource(resID);
DataHelper.loadProps(props, in);
try {
fin = openFileInput(f);
fin = ctx.openFileInput(f);
DataHelper.loadProps(props, fin);
System.err.println("Merging resource into file " + f);
} catch (IOException ioe) {
@@ -188,7 +122,7 @@ public class I2PAndroid extends Activity
if (fin != null) try { fin.close(); } catch (IOException ioe) {}
}
DataHelper.storeProps(props, getFileStreamPath(f));
DataHelper.storeProps(props, ctx.getFileStreamPath(f));
} catch (IOException ioe) {
} catch (Resources.NotFoundException nfe) {
} finally {

View File

@@ -0,0 +1,137 @@
package net.i2p.android.router.service;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
import java.util.List;
import net.i2p.android.router.R;
import net.i2p.router.Router;
import net.i2p.router.RouterContext;
import net.i2p.router.RouterLaunch;
import net.i2p.util.NativeBigInteger;
/**
* Runs the router
*/
public class RouterService extends Service {
private RouterContext _context;
private String _myDir;
private int _state;
private Thread _starterThread;
private StatusBar _statusBar;
private final Object _stateLock = new Object();
private static final int STATE_INIT = 0;
private static final int STATE_STARTING = 1;
private static final int STATE_RUNNING = 2;
private static final int STATE_STOPPING = 3;
private static final int STATE_STOPPED = 4;
private static final String MARKER = "************************************** ";
@Override
public void onCreate() {
System.err.println(this + " onCreate called" +
" Current state is: " + _state);
_myDir = getFilesDir().getAbsolutePath();
Init init = new Init(this);
init.debugStuff();
init.initialize();
_statusBar = new StatusBar(this);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
System.err.println(this + " onStart called" +
"Current state is: " + _state);
synchronized (_stateLock) {
if (_state != STATE_INIT)
return START_STICKY;
_statusBar.update("I2P is starting up");
_state = STATE_STARTING;
_starterThread = new Thread(new Starter());
_starterThread.start();
}
return START_STICKY;
}
private class Starter implements Runnable {
public void run() {
System.err.println(MARKER + this + " starter thread");
NativeBigInteger.main(null);
RouterLaunch.main(null);
synchronized (_stateLock) {
if (_state != STATE_STARTING)
return;
_state = STATE_RUNNING;
List contexts = RouterContext.listContexts();
if ( (contexts == null) || (contexts.isEmpty()) )
throw new IllegalStateException("No contexts. This is usually because the router is either starting up or shutting down.");
_statusBar.update("I2P is running");
_context = (RouterContext)contexts.get(0);
_context.router().setKillVMOnEnd(false);
_context.addShutdownTask(new ShutdownHook());
_starterThread = null;
}
System.err.println("Router.main finished");
}
}
@Override
public IBinder onBind(Intent intent)
{
System.err.println("onBind called" +
"Current state is: " + _state);
return null;
}
@Override
public void onDestroy() {
System.err.println("onDestroy called" +
"Current state is: " + _state);
synchronized (_stateLock) {
if (_state == STATE_STARTING)
_starterThread.interrupt();
if (_state == STATE_STARTING || _state == STATE_RUNNING) {
_state = STATE_STOPPING;
// should this be in a thread?
_statusBar.update("I2P is stopping");
Thread stopperThread = new Thread(new Stopper());
stopperThread.start();
} else if (_state != STATE_STOPPING) {
_statusBar.off(this);
}
}
}
private class Stopper implements Runnable {
public void run() {
System.err.println(MARKER + this + " stopper thread");
_context.router().shutdown(Router.EXIT_HARD);
_statusBar.off(RouterService.this);
System.err.println("shutdown complete");
synchronized (_stateLock) {
_state = STATE_STOPPED;
}
}
}
private class ShutdownHook implements Runnable {
public void run() {
System.err.println(this + " shutdown hook" +
"Current state is: " + _state);
synchronized (_stateLock) {
if (_state == STATE_STARTING || _state == STATE_RUNNING) {
_state = STATE_STOPPED;
_statusBar.off(RouterService.this);
stopSelf();
}
}
}
}
}

View File

@@ -0,0 +1,45 @@
package net.i2p.android.router.service;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import net.i2p.android.router.R;
import net.i2p.android.router.activity.MainActivity;
public class StatusBar {
private final Context ctx;
private final Intent intent;
private final Notification notif;
private final NotificationManager mgr;
private static final int ID = 1;
StatusBar(Context cx) {
ctx = cx;
String ns = Context.NOTIFICATION_SERVICE;
mgr = (NotificationManager)ctx.getSystemService(ns);
int icon = R.drawable.ic_launcher_itoopie;
String text = "Starting I2P";
long now = System.currentTimeMillis();
notif = new Notification(icon, text, now);
notif.flags |= Notification.FLAG_ONGOING_EVENT | Notification.FLAG_NO_CLEAR;
intent = new Intent(ctx, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
public void update(String details) {
String title = "I2P Status";
PendingIntent pi = PendingIntent.getActivity(ctx, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
notif.setLatestEventInfo(ctx, title, details, pi);
mgr.notify(ID, notif);
}
public void off(Context ctx) {
mgr.cancel(ID);
}
}