diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 3b57d4b1a41551e46ceaaa041a247ae5c3f57eae..a2f172f865a583c3840e9d100cc620e7fc1a8401 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -16,7 +16,7 @@
                   android:label="@string/app_name"
                   android:icon="@drawable/ic_launcher_itoopie" />
         <activity android:name=".activity.MainActivity"
-                  android:label="I2P Main Page"
+                  android:label="@string/app_name"
                   android:icon="@drawable/ic_launcher_itoopie"
                   android.theme="@android:style/Theme.NoTitleBar"
                   android:launchMode="singleTop" >
diff --git a/README.txt b/README.txt
index dec1669215f7237d7ab7c22ef5514553178a2674..2222eb47a518954ac958067fb8bc2d5a073c9068 100644
--- a/README.txt
+++ b/README.txt
@@ -2,7 +2,10 @@ These instructions are for a recent Android SDK (1.6 or later).
 These instructions were last updated for SDK Tools Version 11 with
 SDK Platform-tools Version 5, June 2011.
 
-The i2p source must be installed in ../i2p.i2p
+The i2p source must be installed in ../i2p.i2p,
+or else add i2psrc=/path/to/source in the local.properties file.
+Temporary - requires changes in the i2p.i2p.zzz.android branch,
+use it instead!
 
 =====================
 
@@ -35,6 +38,8 @@ The i2p source must be installed in ../i2p.i2p
 ../android-sdk-linux_86/tools/android create avd --name i2p --target 8
 
 #then run the emulator:
+#  This may take a LONG time the first time (half an hour or more)...
+#  Run the debugger to ensure it is making progress
 ../android-sdk-linux_86/tools/emulator -avd i2p &
 
 # or to talk to a real phone in debug mode:
diff --git a/build.xml b/build.xml
index 8826ca601413a9e53e4a02c13b7a4a1c09610394..160c840c2e7c27b81ff17ee8fb0e99a0c1d2ed03 100644
--- a/build.xml
+++ b/build.xml
@@ -102,6 +102,7 @@
         <ant dir="${i2pbase}" >
             <target name="buildRouter" />
             <target name="buildI2PTunnel" />
+            <target name="buildAddressbook" />
         </ant>
 
         <!-- router -->
@@ -144,6 +145,11 @@
             </zipfileset >
         </jar>
 
+        <!-- addressbook - make a jar, it's a war in the i2p distro -->
+        <jar destfile="${jar.libs.dir}/addressbook.jar"
+             basedir="${i2pbase}/apps/addressbook/build"
+             excludes="net/i2p/addressbook/Servlet.class" />
+
     </target>
 
     <!-- some resources -->
@@ -161,6 +167,7 @@
         <copy file="${i2pbase}/licenses/LICENSE-GPLv2.txt" tofile="res/raw/license_gplv2_txt" />
         <copy file="${i2pbase}/licenses/LICENSE-GPLv3.txt" tofile="res/raw/license_gplv3_txt" />
         <copy file="${i2pbase}/licenses/LICENSE-LGPLv3.txt" tofile="res/raw/license_lgplv3_txt" />
+        <copy file="${i2pbase}/licenses/LICENSE-Addressbook.txt" tofile="res/raw/license_addressbook_txt" />
     </target>
 
     <target name="hackcleanup">
diff --git a/res/layout/license.xml b/res/layout/license.xml
index c7436d3b9bb844cae169e35704f9dee561a5360b..ede2950ab7582b8efb822f81b13bb7646f797a65 100644
--- a/res/layout/license.xml
+++ b/res/layout/license.xml
@@ -99,6 +99,12 @@
     android:layout_height="wrap_content" 
     android:text="SNTP"
     />
+ <Button 
+    android:id="@+id/license_addressbook"
+    android:layout_width="wrap_content" 
+    android:layout_height="wrap_content" 
+    android:text="Addressbook"
+    />
 </LinearLayout>
 </LinearLayout>
 
diff --git a/res/layout/main.xml b/res/layout/main.xml
index d1a21b8761334877fd8780d7c4710116c3fe8d1e..d58bec4af8546614af1016b34ceb5c972bb89aff 100644
--- a/res/layout/main.xml
+++ b/res/layout/main.xml
@@ -4,12 +4,6 @@
     android:layout_width="fill_parent"
     android:layout_height="fill_parent"
     >
-<TextView  
-    android:id="@+id/main_title"
-    android:layout_width="fill_parent" 
-    android:layout_height="wrap_content" 
-    android:text="I2P Main Page"
-    />
 <ImageView  
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" 
diff --git a/res/raw/addressbook_config_txt b/res/raw/addressbook_config_txt
new file mode 100644
index 0000000000000000000000000000000000000000..60d9153c15568ad4156941dad0cb757a169f04a0
--- /dev/null
+++ b/res/raw/addressbook_config_txt
@@ -0,0 +1,11 @@
+etags=etags
+last_modified=last_modified
+log=../tmp/addressbook-log.txt
+proxy_host=127.0.0.1
+proxy_port=4444
+master_addressbook=../userhosts.txt
+published_addressbook=../tmp/published.txt
+router_addressbook=../hosts.txt
+should_publish=false
+subscriptions=subscriptions.txt
+update_delay=23
diff --git a/res/raw/subscriptions_txt b/res/raw/subscriptions_txt
new file mode 100644
index 0000000000000000000000000000000000000000..08f5608aa214d7f4f22577961b688237182d4c04
--- /dev/null
+++ b/res/raw/subscriptions_txt
@@ -0,0 +1,3 @@
+http://www.i2p2.i2p/hosts.txt
+http://i2host.i2p/cgi-bin/i2hostetag
+http://stats.i2p/cgi-bin/newhosts.txt
diff --git a/src/net/i2p/android/router/activity/LicenseActivity.java b/src/net/i2p/android/router/activity/LicenseActivity.java
index ac2dba2f78dcdcdbd0bcaf476cf77e266add85fe..6dbb48bdce4e7cc07a9ec4414536e7e24b6678f5 100644
--- a/src/net/i2p/android/router/activity/LicenseActivity.java
+++ b/src/net/i2p/android/router/activity/LicenseActivity.java
@@ -12,12 +12,12 @@ public class LicenseActivity extends I2PActivityBase {
     private static final int[] buttons = {
         R.id.license_main, R.id.license_bf, R.id.license_bsd, R.id.license_elg,
         R.id.license_gplv2, R.id.license_lgplv21, R.id.license_gplv3, R.id.license_lgplv3,
-        R.id.license_cert, R.id.license_sha256, R.id.license_sntp};
+        R.id.license_cert, R.id.license_sha256, R.id.license_sntp, R.id.license_addressbook};
 
     private static final int[] files = {
         R.raw.licenses_txt, R.raw.license_blockfile_txt, R.raw.license_bsd_txt, R.raw.license_elgamaldsa_txt,
         R.raw.license_gplv2_txt, R.raw.license_lgplv2_1_txt, R.raw.license_gplv3_txt, R.raw.license_lgplv3_txt,
-        R.raw.license_installcert_txt, R.raw.license_sha256_txt, R.raw.license_sntp_txt};
+        R.raw.license_installcert_txt, R.raw.license_sha256_txt, R.raw.license_sntp_txt, R.raw.license_addressbook_txt};
 
     /** Called when the activity is first created. */
     @Override
diff --git a/src/net/i2p/android/router/service/Init.java b/src/net/i2p/android/router/service/Init.java
index 9f0c4fac9a48a47c1da9f618188b4a71e59b21b4..48da3e9496eeb4db27c416dcddbbd1751d6ff502 100644
--- a/src/net/i2p/android/router/service/Init.java
+++ b/src/net/i2p/android/router/service/Init.java
@@ -8,6 +8,7 @@ import android.content.res.Resources.NotFoundException;
 import android.os.Build;
 
 import java.io.File;
+import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.InputStream;
 import java.io.IOException;
@@ -92,6 +93,10 @@ class Init {
             // FIXME this is a memory hog to merge this way
             mergeResourceToFile(R.raw.hosts_txt, "hosts.txt", null);
             copyResourceToFile(R.raw.blocklist_txt, "blocklist.txt");
+            File abDir = new File(myDir, "addressbook");
+            abDir.mkdir();
+            copyResourceToFile(R.raw.subscriptions_txt, "addressbook/subscriptions.txt");
+            mergeResourceToFile(R.raw.addressbook_config_txt, "addressbook/config.txt", null);
         }
 
         deleteOldFiles();
@@ -102,6 +107,9 @@ class Init {
         System.setProperty("wrapper.logfile", myDir + "/wrapper.log");
     }
 
+    /**
+     *  @param f relative to base dir
+     */
     private void copyResourceToFile(int resID, String f) {
         InputStream in = null;
         FileOutputStream out = null;
@@ -111,7 +119,7 @@ class Init {
         try {
             // Context methods
             in = ctx.getResources().openRawResource(resID);
-            out = ctx.openFileOutput(f, 0);
+            out = new FileOutputStream(new File(myDir, f));
             
             int read = 0;
             while ( (read = in.read(buf)) != -1)
@@ -131,6 +139,8 @@ class Init {
      *  and write back
      *  For now, do it backwards so we can override with new apks.
      *  When we have user configurable stuff, switch it back.
+     *
+     *  @param f relative to base dir
      *  @param props local overrides or null
      */
     private void mergeResourceToFile(int resID, String f, Properties overrides) {
@@ -145,7 +155,7 @@ class Init {
             //DataHelper.loadProps(props,  in);
             
             try {
-                fin = ctx.openFileInput(f);
+                fin = new FileInputStream(new File(myDir, f));
                 DataHelper.loadProps(props,  fin);
                 System.err.println("Merging resource into file " + f);
             } catch (IOException ioe) {
@@ -157,7 +167,8 @@ class Init {
 
             if (overrides != null)
                 props.putAll(overrides);
-            DataHelper.storeProps(props, ctx.getFileStreamPath(f));
+            File path = new File(myDir, f);
+            DataHelper.storeProps(props, path);
         } catch (IOException ioe) {
         } catch (Resources.NotFoundException nfe) {
         } finally {
diff --git a/src/net/i2p/android/router/service/LoadClientsJob.java b/src/net/i2p/android/router/service/LoadClientsJob.java
index 1a945032f0ec0447898ef19d777c513163026cf6..210e18e0101ae7d7514da2c6df86da969adff118 100644
--- a/src/net/i2p/android/router/service/LoadClientsJob.java
+++ b/src/net/i2p/android/router/service/LoadClientsJob.java
@@ -1,5 +1,6 @@
 package net.i2p.android.router.service;
 
+import net.i2p.addressbook.DaemonThread;
 import net.i2p.android.apps.NewsFetcher;
 import net.i2p.i2ptunnel.TunnelControllerGroup;
 import net.i2p.router.Job;
@@ -29,6 +30,7 @@ import net.i2p.util.I2PAppThread;
 class LoadClientsJob extends JobImpl {
     
     private Thread _fetcherThread;
+    private DaemonThread _addressbook;
 
     /** this is the delay to load (and start) the clients. */
     private static final long LOAD_DELAY = 90*1000;
@@ -49,7 +51,13 @@ class LoadClientsJob extends JobImpl {
         _fetcherThread = new I2PAppThread(fetcher, "NewsFetcher", true);
         _fetcherThread.start();
 
+        _addressbook = new DaemonThread(new String[] {"addressbook"});
+        _addressbook.start();
+
         // add other clients here
+
+
+        getContext().addShutdownTask(new ClientShutdownHook());
     }
 
     private class RunI2PTunnel extends JobImpl {
@@ -65,16 +73,18 @@ class LoadClientsJob extends JobImpl {
             TunnelControllerGroup tcg = TunnelControllerGroup.getInstance();
             int sz = tcg.getControllers().size();
             System.err.println("i2ptunnel started " + sz + " clients");
-            getContext().addShutdownTask(new I2PTunnelShutdownHook());
 
         }
     }
 
-    private class I2PTunnelShutdownHook implements Runnable {
+    private class ClientShutdownHook implements Runnable {
         public void run() {
-            System.err.println("i2ptunnel shutdown hook");
+            System.err.println("client shutdown hook");
+            // i2ptunnel registers its own hook
             if (_fetcherThread != null)
                 _fetcherThread.interrupt();
+            if (_addressbook != null)
+                _addressbook.halt();
         }
     }
 }