forked from I2P_Developers/i2p.i2p
Android:
- Move the classes around - Split into Activity and Service - Add status bar notification - More config changes
This commit is contained in:
@@ -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" >
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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 {
|
||||
137
android/src/net/i2p/android/router/service/RouterService.java
Normal file
137
android/src/net/i2p/android/router/service/RouterService.java
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
45
android/src/net/i2p/android/router/service/StatusBar.java
Normal file
45
android/src/net/i2p/android/router/service/StatusBar.java
Normal 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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user