From 664985461a49c26d4dec20d8712bb33511c88c48 Mon Sep 17 00:00:00 2001
From: str4d <str4d@mail.i2p>
Date: Fri, 9 Aug 2013 11:11:37 +0000
Subject: [PATCH] Initial migration to navigation drawer and Fragment

- Migrated I2PActivityBase and subclasses to Fragment
- Added new MainActivity with navigation drawer to handle Fragments
- Added MainFragment to navigation drawer

Code compiles, installs and runs. Known bugs created:
- Some buttons now fail (can't use an Intent with a Fragment)
  -> Migrate usage of Intents to Fragment transactions
- New install/upgrade dialogs are commented out
  -> Migrate old Dialogs to DialogFragments
---
 res/drawable-hdpi/drawer_shadow.9.png         | Bin 0 -> 171 bytes
 res/drawable-hdpi/ic_drawer.png               | Bin 0 -> 2842 bytes
 res/drawable-mdpi/drawer_shadow.9.png         | Bin 0 -> 158 bytes
 res/drawable-mdpi/ic_drawer.png               | Bin 0 -> 2837 bytes
 res/drawable-xhdpi/drawer_shadow.9.png        | Bin 0 -> 182 bytes
 res/drawable-xhdpi/ic_drawer.png              | Bin 0 -> 1056 bytes
 res/layout/activity_main.xml                  |  27 +
 res/layout/{main.xml => fragment_main.xml}    |   0
 res/values/arrays.xml                         |   6 +
 res/values/strings.xml                        |   2 +
 .../router/activity/AddressbookActivity.java  |   2 +-
 ...ActivityBase.java => I2PFragmentBase.java} |  56 +-
 .../router/activity/I2PWebViewClient.java     |   4 -
 .../router/activity/LicenseActivity.java      |   4 +-
 .../android/router/activity/MainActivity.java | 581 ++++--------------
 .../android/router/activity/MainFragment.java | 507 +++++++++++++++
 .../{NewsActivity.java => NewsFragment.java}  |  38 +-
 ...{PeersActivity.java => PeersFragment.java} |  44 +-
 ...ctivity.java => TextResourceFragment.java} |  18 +-
 .../{WebActivity.java => WebFragment.java}    |  44 +-
 20 files changed, 766 insertions(+), 567 deletions(-)
 create mode 100644 res/drawable-hdpi/drawer_shadow.9.png
 create mode 100644 res/drawable-hdpi/ic_drawer.png
 create mode 100644 res/drawable-mdpi/drawer_shadow.9.png
 create mode 100644 res/drawable-mdpi/ic_drawer.png
 create mode 100644 res/drawable-xhdpi/drawer_shadow.9.png
 create mode 100644 res/drawable-xhdpi/ic_drawer.png
 create mode 100644 res/layout/activity_main.xml
 rename res/layout/{main.xml => fragment_main.xml} (100%)
 rename src/net/i2p/android/router/activity/{I2PActivityBase.java => I2PFragmentBase.java} (86%)
 create mode 100644 src/net/i2p/android/router/activity/MainFragment.java
 rename src/net/i2p/android/router/activity/{NewsActivity.java => NewsFragment.java} (76%)
 rename src/net/i2p/android/router/activity/{PeersActivity.java => PeersFragment.java} (71%)
 rename src/net/i2p/android/router/activity/{TextResourceActivity.java => TextResourceFragment.java} (77%)
 rename src/net/i2p/android/router/activity/{WebActivity.java => WebFragment.java} (75%)

diff --git a/res/drawable-hdpi/drawer_shadow.9.png b/res/drawable-hdpi/drawer_shadow.9.png
new file mode 100644
index 0000000000000000000000000000000000000000..224cc4ff43a29c546ae50c654c20c58c2f4cdb75
GIT binary patch
literal 171
zcmeAS@N?(olHy`uVBq!ia0vp^JV0#3!3HEVSgovp6icy_X9x!n)NrJ90QsB+9+AZi
z4BVX{%xHe{^je^xucwP+h)3t!Yl?gg4m>OeUfNFiFU`@U5Xr+-Y2h+^&Fz!7ypldm
za#4)fkaYOplLMWvd)czen2t>^YG&h=GRe5G;NW`))xgl;_^?U481>l1!)FR53IYvg
N@O1TaS?83{1OO&fGZ_E?

literal 0
HcmV?d00001

diff --git a/res/drawable-hdpi/ic_drawer.png b/res/drawable-hdpi/ic_drawer.png
new file mode 100644
index 0000000000000000000000000000000000000000..ff7b1def9ac3f86488a855f502b965ac75b633fb
GIT binary patch
literal 2842
zcmV+#3+42QP)<h;3K|Lk000e1NJLTq000;O000;W1^@s6;CDUv00009a7bBm000XU
z000XU0RWnu7ytkYPiaF#P*7-ZbZ>KLZ*U+<Lqi~Na&Km7Y-Iodc-oy)XH-+^7Crag
z^g>IBfRsybQWXdwQbLP>6p<z>Aqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uh<iVD~V
z<RPMtgQJLw%KPDaqifc@_vX$1wbwr9tn;0-&j-K=43<bUQ8j=JsX`tR;Dg7+#^K~H
zK!FM*Z~zbpvt%K2{UZSY_<lS*D<Z%Lz5oGu(+dayz)hRLFdT>f59&ghTmgWD0l;*T
zI7<kC6aYYajzXpYKt=(8otP$50H6c_V9R4-;{Z@C0AMG7=F<Rxo%or10RUT+Ar%3j
zkpLhQWr#!oXgdI`&sK^>09Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p
z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-<?i
z0%4j!F2Z@488U%158(66005wo6%pWr^Zj_v4zAA5HjcIqUoGmt2LB>rV&neh&#Q1i
z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_<lS*MWK+n+1cgf
z<k(8YLR(?VSAG6x!e78w{cQPuJpA|d;J)G{fihizM+Erb!p!tcr5w+a34~(Y=8s4G
zw+sLL9n&JjNn*KJDiq^U5^;`1nvC-@r6P$!k}1U{(*I=Q-z@tBKHoI}uxdU5dyy@u
zU1J0GOD7Ombim^G008p4Z^6_k2m^p<gW=D2|L;HjN1!DDfM!XOaR2~bL?kX$%CkSm
z2mk;?pn)o|K^yeJ7%adB9Ki+L!3+FgHiSYX#KJ-lLJDMn9CBbOtb#%)hRv`YDqt_v
zKpix|QD}yfa1JiQRk#j4a1Z)n2%f<xynzV>LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW
zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_Ifq<Ex{*7`05XF7hP+2Hl!3BQJ=6@fL%FCo
z8iYoo3(#bAF`ADSpqtQgv>H8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X
zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ<AYmRsNLWl*PS{AOARHt#5!wki2?K;t
z!Y3k=s7tgax)J%r7-BLphge7~Bi0g+6E6^Zh(p9TBoc{3GAFr^0!gu?RMHaCM$&Fl
zBk3%un>0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4
z<uv66WtcKSRim0x-Ke2d5jBrmLam{;Qm;{ms1r1GnmNsb7D-E`t)i9F8fX`2_i3-_
zbh;7Ul^#x)&{xvS=|||7=mYe33=M`AgU5(xC>fg=2N-7=cNnjjOr{yriy6mMFgG#l
znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U
zt5vF<Q0r40Q)j6=sE4X&sBct1q<&fbi3VB2Ov6t@q*0);U*o*SAPZv|vv@2aYYnT0
zb%8a+Cb7-ge0D0knEf5Qi#@8Tp*ce{N;6lpQuCB%KL_KOarm5cP6_8Ir<e17iry6O
zDdH&`rZh~sF=bq9s+O0QSgS~@QL9Jmy*94xr=6y~MY~!1fet~(N+(<=M`w@D1)b+p
z*;C!83a1uLJv#NSE~;y#8=<>IcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya?
z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y
zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB
zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt
z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a<fJbF^|4I#xQ~n$Dc=
zKYhjYmgz5NSkDm8*fZm{6U!;YX`NG>(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C
z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB
zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe
zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0
z?2xS?_ve_-k<Mujg;0Lz*3buG=3$G&ehepthlN*$KaOySSQ^nWmo<0M+(UEUMEXRQ
zMBbZcF;6+KElM>iKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$
z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4
z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu
zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu
z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E
ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw
zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX
z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i&
z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01
z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R
z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw
zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD
zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3|
zawq-H%e&ckC+@AhPrP6BK<z=<L*0kfKU@CX*zeqbYQT4(^U>T#_XdT7&;F71j}Joy
zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z
zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot<a{81DF0~rvGr5Xr~8u`lav1h
z1DNytV>2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F}
z0000*Nkl<Zc-mt8|NlP&Eddh)jR8wja~s)SsH?4F9B>~DeG6C^7#J9bv=11Ed_EY>
sXrmczG^34Xw9$-44FCWD0RR6306G;FG3hs#*#H0l07*qoM6N<$f)^G)DF6Tf

literal 0
HcmV?d00001

diff --git a/res/drawable-mdpi/drawer_shadow.9.png b/res/drawable-mdpi/drawer_shadow.9.png
new file mode 100644
index 0000000000000000000000000000000000000000..3797f99c0ef9f657c2b0a1f84a4d0f16cc8ee5f4
GIT binary patch
literal 158
zcmeAS@N?(olHy`uVBq!ia0vp^96+qZ!3HFgEN0vWQY^(zo*^7SP{WbZ0pxQQctjR6
zFmQK*Fr)d&(`$i(4xTQKAr`%FuWaOOaA06QaQd;(yN7D;?7i2paNm#nvBfgTEqd~o
zcU{8lWjX#P6K=BftS@S075ic65$zclza&>r_mjZQ`zwzw1DeI)>FVdQ&MBb@0Ae69
AivR!s

literal 0
HcmV?d00001

diff --git a/res/drawable-mdpi/ic_drawer.png b/res/drawable-mdpi/ic_drawer.png
new file mode 100644
index 0000000000000000000000000000000000000000..fb681ba2639897cc4646d3784b97bbe16f5d4e91
GIT binary patch
literal 2837
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

literal 0
HcmV?d00001

diff --git a/res/drawable-xhdpi/drawer_shadow.9.png b/res/drawable-xhdpi/drawer_shadow.9.png
new file mode 100644
index 0000000000000000000000000000000000000000..fa3d853e902401d850f09b1cc50a58cda9bd3bb5
GIT binary patch
literal 182
zcmeAS@N?(olHy`uVBq!ia0vp^{6Or)!3HEd1bTh|DVAa<&kznEsNqQI0P;BtJR*x3
z7`Qt@n9=;?>9s(?2u~Ns5RcBc*A@8=2k<aom@ZfHU481R#!RUh-d)GOIZkwDS|k40
zBPnsx5rv8et+M$t*Xte?r{2HMES<JgYFlVT3^J&(o~M%b>^;BD$vKZ(B+Ju<=2igh
OVDNPHb6Mw<&;$UPn>!5v

literal 0
HcmV?d00001

diff --git a/res/drawable-xhdpi/ic_drawer.png b/res/drawable-xhdpi/ic_drawer.png
new file mode 100644
index 0000000000000000000000000000000000000000..b9bc3d70f1d29fec2e4530e5d1809edc8e15ad35
GIT binary patch
literal 1056
zcmbVLy>HV%6u%0oKud=rkbnW5+yx|J`<&Q`t(wY-lQsgURT^lJI@GnVjg{JG>??6I
zp$-TJMs}p`%!m$vm_Q6HNWh<fkWfX%0z=RFC=6ARux#JEcklOmANSs)h1%@I*rhQ5
zz(jS<tg{uS->FgdkGtJ{wp^s;CS4?Jv|~pY7%o}Gu<G0ExQ=ai>+V}T4Zw+(*J#qF
zbyIVQ&)caDpZFm|128?4gtpVh6t3cRFVMN~yDvHDxjMHbTcQ<~aLb$PMtHGXYdGDu
zqq^M8bvT`9jKIg#hKaus#9E?rJzkB;saoJ*&xE#ht{+s>T7V@IVJP$2j3Xih6@^DR
zSy9k6D2YfCMD{8fl+$EIlk#xzaLileu4#3%GVsNAI@h8!)C8f^>F}K_Poi}Jsj8ZC
zNK%GbWa6!W+DRser-lqBj-AL0sYe2sGTN(Tlj<Ccw4Z_>TGk<P5DyB)N+u+BC?H-G
zd_T>rXC2cz{u9QL)^TGi#6lg%WHWNueXLCl!K`-2J4y{%G}?URu}iTxOyX?%IG|Ni
z=hzAFdahPhWYd&UB`ZouDIio33t8338aX7(id>P097kc5Tt2T#qN-LD1EI21DCNpU
z)l>>nF>e%+ImA|jnA(AZhkiZgcYrM%i`7aIwke4kglr5uV4+1QiCZLur9}l^v24c+
zQpMHug8KQIIP&gcw-ON__A0D-M?~=N%==jPf2t<1V1%?i{%V(@iuGVB9yUMQ9F7kT
z*vv$1ICdVt{>%oeRyB=A^5xqTV+_DEZ*K2>+`fG7_s{+D?GHCbcTc|H-@OlOr+<7J
z`MUh8J-U;h90BvQ$x;pMJp@l5JO^O;{&-)=znWYD7w()l&fdzcq%&JB*UV?dmF)v&
C(MM<i

literal 0
HcmV?d00001

diff --git a/res/layout/activity_main.xml b/res/layout/activity_main.xml
new file mode 100644
index 000000000..6f2591c94
--- /dev/null
+++ b/res/layout/activity_main.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<android.support.v4.widget.DrawerLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/drawer_layout"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context=".MainActivity" >
+
+    <!-- The main content view -->
+    <FrameLayout
+        android:id="@+id/main_content"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+
+    <!-- The navigation drawer -->
+    <ListView
+        android:id="@+id/drawer"
+        android:layout_width="240dp"
+        android:layout_height="match_parent"
+        android:layout_gravity="start"
+        android:choiceMode="singleChoice"
+        android:divider="@android:color/transparent"
+        android:dividerHeight="0dp"
+        android:background="#111"/>
+
+</android.support.v4.widget.DrawerLayout>
\ No newline at end of file
diff --git a/res/layout/main.xml b/res/layout/fragment_main.xml
similarity index 100%
rename from res/layout/main.xml
rename to res/layout/fragment_main.xml
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index ed6cc84d1..cb3ecd8c3 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -1,5 +1,11 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources>
+    <string-array name="main_fragments">
+        <item>net.i2p.android.router.activity.MainFragment</item>
+    </string-array>
+    <string-array name="main_fragment_titles">
+        <item>I2P</item>
+    </string-array>
     <string-array name="setting0to3">
         <item>0</item>
         <item>1</item>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 280690a2f..484455be9 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -23,6 +23,8 @@
     <string name="label_website_nonanon">Web Site (non-anon)</string>
     <string name="label_faq_nonanon">FAQ (non-anon)</string>
 
+    <string name="drawer_open">Open nav</string>
+    <string name="drawer_close">Close nav</string>
     <string name="action_add">Add</string>
     <string name="action_router_start">Start Router</string>
     <string name="action_router_stop">Stop Router</string>
diff --git a/src/net/i2p/android/router/activity/AddressbookActivity.java b/src/net/i2p/android/router/activity/AddressbookActivity.java
index 6d3068acb..6c533583f 100644
--- a/src/net/i2p/android/router/activity/AddressbookActivity.java
+++ b/src/net/i2p/android/router/activity/AddressbookActivity.java
@@ -66,7 +66,7 @@ public class AddressbookActivity extends ActionBarActivity {
         lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
             public void onItemClick(AdapterView parent, View view, int pos, long id) {
                 CharSequence host = ((TextView) view).getText();
-                Intent intent = new Intent(view.getContext(), WebActivity.class);
+                Intent intent = new Intent(view.getContext(), WebFragment.class);
                 intent.setData(Uri.parse("http://" + host + '/'));
                 startActivity(intent);
             }
diff --git a/src/net/i2p/android/router/activity/I2PActivityBase.java b/src/net/i2p/android/router/activity/I2PFragmentBase.java
similarity index 86%
rename from src/net/i2p/android/router/activity/I2PActivityBase.java
rename to src/net/i2p/android/router/activity/I2PFragmentBase.java
index 5b04f77bf..15d467bea 100644
--- a/src/net/i2p/android/router/activity/I2PActivityBase.java
+++ b/src/net/i2p/android/router/activity/I2PFragmentBase.java
@@ -6,6 +6,7 @@ import android.content.ServiceConnection;
 import android.content.SharedPreferences;
 import android.os.Bundle;
 import android.os.IBinder;
+import android.support.v4.app.Fragment;
 import android.support.v7.app.ActionBarActivity;
 import android.view.Menu;
 import android.view.MenuInflater;
@@ -23,7 +24,7 @@ import net.i2p.router.peermanager.ProfileOrganizer;
 import net.i2p.router.transport.FIFOBandwidthLimiter;
 import net.i2p.stat.StatManager;
 
-public abstract class I2PActivityBase extends ActionBarActivity {
+public abstract class I2PFragmentBase extends Fragment {
     protected String _myDir;
     protected boolean _isBound;
     protected boolean _triedBind;
@@ -43,14 +44,9 @@ public abstract class I2PActivityBase extends ActionBarActivity {
     {
         Util.i(this + " onCreate called");
         super.onCreate(savedInstanceState);
-        _myDir = getFilesDir().getAbsolutePath();
-    }
-
-    @Override
-    public void onRestart()
-    {
-        Util.i(this + " onRestart called");
-        super.onRestart();
+        _myDir = getActivity().getFilesDir().getAbsolutePath();
+        // Set this so onCreateOptionsMenu() is called
+        setHasOptionsMenu(true);
     }
 
     @Override
@@ -58,7 +54,7 @@ public abstract class I2PActivityBase extends ActionBarActivity {
     {
         Util.i(this + " onStart called");
         super.onStart();
-        _sharedPrefs = getSharedPreferences(SHARED_PREFS, 0);
+        _sharedPrefs = getActivity().getSharedPreferences(SHARED_PREFS, 0);
         if (_sharedPrefs.getBoolean(PREF_AUTO_START, DEFAULT_AUTO_START))
             startRouter();
         else
@@ -113,6 +109,14 @@ public abstract class I2PActivityBase extends ActionBarActivity {
         super.onStop();
     }
 
+    /**
+     * Called by MainActivity.onBackPressed()
+     * @return true if the fragment should stay, false otherwise.
+     */
+    public boolean onBackPressed() {
+        return false;
+    }
+
     @Override
     public void onDestroy()
     {
@@ -121,18 +125,16 @@ public abstract class I2PActivityBase extends ActionBarActivity {
     }
 
     @Override
-    public boolean onCreateOptionsMenu(Menu menu) {
-        MenuInflater inflater = getMenuInflater();
+    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
         inflater.inflate(R.menu.menu1, menu);
-        return true;
     }
 
     @Override
-    public boolean onPrepareOptionsMenu(Menu menu) {
+    public void onPrepareOptionsMenu(Menu menu) {
         // add/hide items here
         RouterService svc = _routerService;
         boolean showStart = ((svc == null) || (!_isBound) || svc.canManualStart()) &&
-                            Util.isConnected(this);
+                            Util.isConnected(getActivity());
         MenuItem start = menu.findItem(R.id.menu_start);
         start.setVisible(showStart);
         start.setEnabled(showStart);
@@ -142,39 +144,37 @@ public abstract class I2PActivityBase extends ActionBarActivity {
         stop.setVisible(showStop);
         stop.setEnabled(showStop);
 
-        boolean showHome = ! (this instanceof MainActivity);
+        boolean showHome = ! (this instanceof MainFragment);
         MenuItem home = menu.findItem(R.id.menu_home);
         home.setVisible(showHome);
         home.setEnabled(showHome);
 
-        boolean showAddressbook = (this instanceof WebActivity);
+        boolean showAddressbook = (this instanceof WebFragment);
         MenuItem addressbook = menu.findItem(R.id.menu_addressbook);
         addressbook.setVisible(showAddressbook);
         addressbook.setEnabled(showAddressbook);
 
-        boolean showReload = showAddressbook || (this instanceof PeersActivity);
+        boolean showReload = showAddressbook || (this instanceof PeersFragment);
         MenuItem reload = menu.findItem(R.id.menu_reload);
         reload.setVisible(showReload);
         reload.setEnabled(showReload);
-
-        return super.onPrepareOptionsMenu(menu);
     }
 
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
         switch (item.getItemId()) {
         case R.id.menu_settings:
-            Intent intent = new Intent(I2PActivityBase.this, SettingsActivity.class);
+            Intent intent = new Intent(getActivity(), SettingsActivity.class);
             startActivity(intent);
             return true;
 
         case R.id.menu_home:
-            Intent i2 = new Intent(I2PActivityBase.this, MainActivity.class);
+            Intent i2 = new Intent(getActivity(), MainActivity.class);
             startActivity(i2);
             return true;
 
         case R.id.menu_addressbook:
-            Intent i3 = new Intent(I2PActivityBase.this, AddressbookActivity.class);
+            Intent i3 = new Intent(getActivity(), AddressbookActivity.class);
             startActivity(i3);
             return true;
 
@@ -209,9 +209,9 @@ public abstract class I2PActivityBase extends ActionBarActivity {
      */
     protected boolean startRouter() {
         Intent intent = new Intent();
-        intent.setClassName(this, "net.i2p.android.router.service.RouterService");
+        intent.setClassName(getActivity(), "net.i2p.android.router.service.RouterService");
         Util.i(this + " calling startService");
-        ComponentName name = startService(intent);
+        ComponentName name = getActivity().startService(intent);
         if (name == null)
             Util.i(this + " XXXXXXXXXXXXXXXXXXXX got from startService: " + name);
         Util.i(this + " got from startService: " + name);
@@ -226,10 +226,10 @@ public abstract class I2PActivityBase extends ActionBarActivity {
      */
     protected boolean bindRouter(boolean autoCreate) {
         Intent intent = new Intent();
-        intent.setClassName(this, "net.i2p.android.router.service.RouterService");
+        intent.setClassName(getActivity(), "net.i2p.android.router.service.RouterService");
         Util.i(this + " calling bindService");
         _connection = new RouterConnection();
-        _triedBind = bindService(intent, _connection, autoCreate ? BIND_AUTO_CREATE : 0);
+        _triedBind = getActivity().bindService(intent, _connection, autoCreate ? getActivity().BIND_AUTO_CREATE : 0);
         Util.i(this + " bindService: auto create? " + autoCreate + " success? " + _triedBind);
         return _triedBind;
     }
@@ -237,7 +237,7 @@ public abstract class I2PActivityBase extends ActionBarActivity {
     protected void unbindRouter() {
         Util.i(this + " unbindRouter called with _isBound:" + _isBound + " _connection:" + _connection + " _triedBind:" + _triedBind);
         if (_triedBind && _connection != null)
-                unbindService(_connection);
+            getActivity().unbindService(_connection);
 
         _triedBind = false;
         _connection = null;
diff --git a/src/net/i2p/android/router/activity/I2PWebViewClient.java b/src/net/i2p/android/router/activity/I2PWebViewClient.java
index 375bb1478..f5be46f4f 100644
--- a/src/net/i2p/android/router/activity/I2PWebViewClient.java
+++ b/src/net/i2p/android/router/activity/I2PWebViewClient.java
@@ -38,10 +38,6 @@ class I2PWebViewClient extends WebViewClient {
     private static final String ERROR_URL = "<p>Unable to load URL: ";
     private static final String ERROR_ROUTER = "<p>Your router (or the HTTP proxy) does not appear to be running.</p>";
 
-    public I2PWebViewClient(Context ctx) {
-        super();
-    }
-
     @Override
     public boolean shouldOverrideUrlLoading(WebView view, String url) {
         Util.d("Should override? " + url);
diff --git a/src/net/i2p/android/router/activity/LicenseActivity.java b/src/net/i2p/android/router/activity/LicenseActivity.java
index c124559c0..a0e455cdc 100644
--- a/src/net/i2p/android/router/activity/LicenseActivity.java
+++ b/src/net/i2p/android/router/activity/LicenseActivity.java
@@ -36,8 +36,8 @@ public class LicenseActivity extends ListActivity {
         // set the callback
         lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
             public void onItemClick(AdapterView parent, View view, int pos, long id) {
-                Intent intent = new Intent(view.getContext(), TextResourceActivity.class);
-                intent.putExtra(TextResourceActivity.TEXT_RESOURCE_ID, files[pos]);
+                Intent intent = new Intent(view.getContext(), TextResourceFragment.class);
+                intent.putExtra(TextResourceFragment.TEXT_RESOURCE_ID, files[pos]);
                 startActivity(intent);
             }
         });
diff --git a/src/net/i2p/android/router/activity/MainActivity.java b/src/net/i2p/android/router/activity/MainActivity.java
index c0af403a9..3e5032029 100644
--- a/src/net/i2p/android/router/activity/MainActivity.java
+++ b/src/net/i2p/android/router/activity/MainActivity.java
@@ -1,508 +1,159 @@
 package net.i2p.android.router.activity;
 
+import net.i2p.android.router.R;
+import net.i2p.android.router.util.Util;
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.content.DialogInterface;
 import android.content.Intent;
-import android.net.Uri;
+import android.content.res.Configuration;
 import android.os.Bundle;
-import android.os.Handler;
+import android.support.v4.app.ActionBarDrawerToggle;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.view.GravityCompat;
+import android.support.v4.widget.DrawerLayout;
+import android.support.v7.app.ActionBarActivity;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
 import android.view.View;
-import android.widget.Button;
-import android.widget.TextView;
-import java.io.File;
-import java.text.DecimalFormat;
-import net.i2p.android.router.R;
-import net.i2p.android.router.service.RouterService;
-import net.i2p.android.router.util.Util;
-import net.i2p.data.DataHelper;
-import net.i2p.router.RouterContext;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
 
-public class MainActivity extends I2PActivityBase {
+public class MainActivity extends ActionBarActivity {
+    private DrawerLayout mDrawerLayout;
+    private ListView mDrawerList;
+    private ActionBarDrawerToggle mDrawerToggle;
 
-    private Handler _handler;
-    private Runnable _updater;
-    private Runnable _oneShotUpdate;
-    private String _savedStatus;
-    private String _ourVersion;
-    private boolean _keep = true;
-    private boolean _startPressed = false;
-    protected static final String PROP_NEW_INSTALL = "i2p.newInstall";
-    protected static final String PROP_NEW_VERSION = "i2p.newVersion";
-    protected static final int DIALOG_NEW_INSTALL = 0;
-    protected static final int DIALOG_NEW_VERSION = 1;
-
-    @Override
-    public void onPostCreate(Bundle savedInstanceState) {
-        Util.i("Initializing...");
-        InitActivities init = new InitActivities(this);
-        init.debugStuff();
-        init.initialize();
-        super.onPostCreate(savedInstanceState);
-        _ourVersion = Util.getOurVersion(this);
-    }
+    private CharSequence mDrawerTitle;
+    private CharSequence mTitle;
+    private String[] mFragments;
+    private String[] mFragmentTitles;
 
-    /**
-     * Called when the activity is first created.
-     */
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        // Init stuff here so settings work.
-        _myDir = getFilesDir().getAbsolutePath();
-        if(savedInstanceState != null) {
-            String saved = savedInstanceState.getString("status");
-            if(saved != null) {
-                _savedStatus = saved;
-            }
-        }
-
-        _keep = true;
-        setContentView(R.layout.main);
-
-        Button b = (Button) findViewById(R.id.news_button);
-        b.setOnClickListener(new View.OnClickListener() {
-
-            public void onClick(View view) {
-                Intent intent = new Intent(view.getContext(), NewsActivity.class);
-                startActivity(intent);
-            }
-        });
-
-        b = (Button) findViewById(R.id.releasenotes_button);
-        b.setOnClickListener(new View.OnClickListener() {
-
-            public void onClick(View view) {
-                Intent intent = new Intent(view.getContext(), TextResourceActivity.class);
-                intent.putExtra(TextResourceActivity.TEXT_RESOURCE_ID, R.raw.releasenotes_txt);
-                startActivity(intent);
-            }
-        });
-
-        b = (Button) findViewById(R.id.licenses_button);
-        b.setOnClickListener(new View.OnClickListener() {
-
-            public void onClick(View view) {
-                Intent intent = new Intent(view.getContext(), LicenseActivity.class);
-                //Intent intent = new Intent(view.getContext(), TextResourceActivity.class);
-                //intent.putExtra(TextResourceActivity.TEXT_RESOURCE_ID, R.raw.licenses_txt);
-                startActivity(intent);
-            }
-        });
-
-        b = (Button) findViewById(R.id.website_button);
-        b.setOnClickListener(new View.OnClickListener() {
-
-            public void onClick(View view) {
-                Intent intent = new Intent(view.getContext(), WebActivity.class);
-                //intent.setData((new Uri.Builder()).scheme("http").authority("www.i2p2.de").path("/").build());
-                intent.setData(Uri.parse("http://www.i2p2.de/"));
-                startActivity(intent);
-            }
-        });
-
-        b = (Button) findViewById(R.id.faq_button);
-        b.setOnClickListener(new View.OnClickListener() {
-
-            public void onClick(View view) {
-                Intent intent = new Intent(view.getContext(), WebActivity.class);
-                //intent.setData((new Uri.Builder()).scheme("http").authority("www.i2p2.de").path("/faq").build());
-                intent.setData(Uri.parse("http://www.i2p2.de/faq"));
-                startActivity(intent);
-            }
-        });
-
-        b = (Button) findViewById(R.id.welcome_button);
-        b.setOnClickListener(new View.OnClickListener() {
-
-            public void onClick(View view) {
-                Intent intent = new Intent(view.getContext(), WebActivity.class);
-                intent.putExtra(WebActivity.HTML_RESOURCE_ID, R.raw.welcome_html);
-                startActivity(intent);
-            }
-        });
-
-        b = (Button) findViewById(R.id.addressbook_button);
-        b.setOnClickListener(new View.OnClickListener() {
-
-            public void onClick(View view) {
-                Intent intent = new Intent(view.getContext(), AddressbookActivity.class);
-                startActivity(intent);
-            }
-        });
-
-        b = (Button) findViewById(R.id.logs_button);
-        b.setOnClickListener(new View.OnClickListener() {
-
-            public void onClick(View view) {
-                Intent intent = new Intent(view.getContext(), LogActivity.class);
-                startActivity(intent);
-            }
-        });
-
-        b = (Button) findViewById(R.id.error_button);
-        b.setOnClickListener(new View.OnClickListener() {
-
-            public void onClick(View view) {
-                Intent intent = new Intent(view.getContext(), LogActivity.class);
-                intent.putExtra(LogActivity.ERRORS_ONLY, true);
-                startActivity(intent);
-            }
-        });
-
-        b = (Button) findViewById(R.id.peers_button);
-        b.setOnClickListener(new View.OnClickListener() {
-
-            public void onClick(View view) {
-                Intent intent = new Intent(view.getContext(), PeersActivity.class);
-                startActivity(intent);
-            }
-        });
-
-        /*
-         * hidden, unused b = (Button) findViewById(R.id.router_stop_button);
-         * b.setOnClickListener(new View.OnClickListener() { public void
-         * onClick(View view) { RouterService svc = _routerService; if (svc !=
-         * null && _isBound) { setPref(PREF_AUTO_START, false);
-         * svc.manualStop(); updateOneShot(); } } });
-         */
-
-        b = (Button) findViewById(R.id.router_start_button);
-        b.setOnClickListener(new View.OnClickListener() {
-
-            public void onClick(View view) {
-                _startPressed = true;
-                RouterService svc = _routerService;
-                if(svc != null && _isBound) {
-                    setPref(PREF_AUTO_START, true);
-                    svc.manualStart();
-                } else {
-                    (new File(_myDir, "wrapper.log")).delete();
-                    startRouter();
-                }
-                updateOneShot();
-            }
-        });
-
-        b = (Button) findViewById(R.id.router_quit_button);
-        b.setOnClickListener(new View.OnClickListener() {
-
-            public void onClick(View view) {
-                RouterService svc = _routerService;
-                if(svc != null && _isBound) {
-                    setPref(PREF_AUTO_START, false);
-                    svc.manualQuit();
-                    updateOneShot();
-                }
-            }
-        });
-
-        _handler = new Handler();
-        _updater = new Updater();
-        _oneShotUpdate = new OneShotUpdate();
-    }
-
-    @Override
-    public void onStart() {
-        super.onStart();
-        _handler.removeCallbacks(_updater);
-        _handler.removeCallbacks(_oneShotUpdate);
-        if(_savedStatus != null) {
-            TextView tv = (TextView) findViewById(R.id.main_status_text);
-            tv.setText(_savedStatus);
+        setContentView(R.layout.activity_main);
+
+        mTitle = mDrawerTitle = getTitle();
+        mFragments = getResources().getStringArray(R.array.main_fragments);
+        mFragmentTitles = getResources().getStringArray(R.array.main_fragment_titles);
+        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
+        mDrawerList = (ListView) findViewById(R.id.drawer);
+
+        // Set a custom shadow that overlays the main content when the drawer opens
+        mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
+        // Set the adapter for the list view
+        mDrawerList.setAdapter(new ArrayAdapter<String>(this,
+                android.R.layout.simple_list_item_1, mFragments));
+        // Set the list's click listener
+        mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
+
+        // Enable ActionBar app icon to behave as action to toggle nav drawer
+        //getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+        //getSupportActionBar().setHomeButtonEnabled(true);
+
+        mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
+                R.drawable.ic_drawer, R.string.drawer_open, R.string.drawer_close) {
+
+            /** Called when a drawer has settled in a completely closed state. */
+            public void onDrawerClosed(View view) {
+                getSupportActionBar().setTitle(mTitle);
+                supportInvalidateOptionsMenu();
+            }
+
+            /** Called when a drawer has settled in a completely open state. */
+            public void onDrawerOpened(View view) {
+                getSupportActionBar().setTitle(mDrawerTitle);
+                supportInvalidateOptionsMenu();
+            }
+        };
+
+        // Set the drawer toggle as the DrawerListener
+        mDrawerLayout.setDrawerListener(mDrawerToggle);
+
+        // Start with the home view
+        if (savedInstanceState == null) {
+            MainFragment mainFragment = new MainFragment();
+            mainFragment.setArguments(getIntent().getExtras());
+            getSupportFragmentManager().beginTransaction()
+                    .add(R.id.main_content, mainFragment).commit();
         }
-        checkDialog();
-        _handler.postDelayed(_updater, 100);
-    }
-
-    @Override
-    public void onStop() {
-        super.onStop();
-        _handler.removeCallbacks(_updater);
-        _handler.removeCallbacks(_oneShotUpdate);
     }
 
+    /* Called whenever we call invalidateOptionsMenu() */
     @Override
-    public void onResume() {
-        super.onResume();
-        updateOneShot();
+    public boolean onPrepareOptionsMenu(Menu menu) {
+        // If the nav drawer is open, hide action items related to the content view
+        boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);
+        //menu.findItem(R.id.action_add_to_addressbook).setVisible(!drawerOpen);
+        return super.onPrepareOptionsMenu(menu);
     }
 
     @Override
-    public void onSaveInstanceState(Bundle outState) {
-        if(_savedStatus != null) {
-            outState.putString("status", _savedStatus);
-        }
-        super.onSaveInstanceState(outState);
-    }
-
-    private void updateOneShot() {
-        _handler.postDelayed(_oneShotUpdate, 100);
-    }
-
-    private class OneShotUpdate implements Runnable {
-
-        public void run() {
-            updateVisibility();
-            updateStatus();
+    public boolean onOptionsItemSelected(MenuItem item) {
+        // The action bar home/up action should open or close the drawer.
+        // ActionBarDrawerToggle will take care of this.
+        if(mDrawerToggle.onOptionsItemSelected(item)) {
+            return true;
         }
+        // Handle action buttons
+        return super.onOptionsItemSelected(item);
     }
 
-    private class Updater implements Runnable {
-
-        private int counter;
-        private final int delay = 1000;
-        private final int toloop = delay / 500;
-        public void run() {
-            updateVisibility();
-            if(counter++ % toloop == 0) {
-                updateStatus();
-            }
-            //_handler.postDelayed(this, 2500);
-            _handler.postDelayed(this, delay);
+    private class DrawerItemClickListener implements ListView.OnItemClickListener {
+        public void onItemClick(AdapterView<?> parent, View view, int pos, long id) {
+            selectItem(pos);
         }
     }
 
-    private void updateVisibility() {
-        RouterService svc = _routerService;
-        boolean showStart = ((svc == null) || (!_isBound) || svc.canManualStart())
-                && Util.isConnected(this);
-        Button start = (Button) findViewById(R.id.router_start_button);
-        start.setVisibility(showStart ? View.VISIBLE : View.INVISIBLE);
+    private void selectItem(int pos) {
+        Fragment fragment = Fragment.instantiate(MainActivity.this, mFragments[pos]);
 
-        boolean showStop = svc != null && _isBound && svc.canManualStop();
-        // Old stop but leave in memory. Always hide for now.
-        // Button stop = (Button) findViewById(R.id.router_stop_button);
-        // stop.setVisibility( /* showStop ? View.VISIBLE : */ View.INVISIBLE);
+        // Insert the fragment by replacing any existing fragment
+        FragmentManager fragmentManager = getSupportFragmentManager();
+        fragmentManager.beginTransaction()
+                       .replace(R.id.main_content, fragment)
+                       .commit();
 
-        Button quit = (Button) findViewById(R.id.router_quit_button);
-        quit.setVisibility(showStop ? View.VISIBLE : View.INVISIBLE);
+        // Highlight the selected item, update the title, and close the drawer
+        mDrawerList.setItemChecked(pos, true);
+        setTitle(mFragmentTitles[pos]);
+        mDrawerLayout.closeDrawer(mDrawerList);
     }
 
     @Override
-    public void onBackPressed() {
-        RouterContext ctx = getRouterContext();
-        // RouterService svc = _routerService; Which is better to use?!
-        _keep = Util.isConnected(this) && (ctx != null || _startPressed);
-        Util.d("*********************************************************");
-        Util.d("Back pressed, Keep? " + _keep);
-        Util.d("*********************************************************");
-        super.onBackPressed();
+    public void setTitle(CharSequence title) {
+        mTitle = title;
+        getSupportActionBar().setTitle(mTitle);
     }
 
     @Override
-    public void onDestroy() {
-        super.onDestroy();
-        if(!_keep) {
-            Thread t = new Thread(new KillMe());
-            t.start();
-        }
-    }
-
-    private class KillMe implements Runnable {
-
-        public void run() {
-            Util.d("*********************************************************");
-            Util.d("KillMe started!");
-            Util.d("*********************************************************");
-            try {
-                Thread.sleep(500); // is 500ms long enough?
-            } catch(InterruptedException ex) {
-            }
-            System.exit(0);
-        }
-    }
-
-    private void updateStatus() {
-        RouterContext ctx = getRouterContext();
-        TextView tv = (TextView) findViewById(R.id.main_status_text);
-
-        if(!Util.isConnected(this)) {
-            tv.setText("Router version: " + _ourVersion + "\nNo Internet connection is available");
-            tv.setVisibility(View.VISIBLE);
-        } else if(ctx != null) {
-            if(_startPressed) {
-                _startPressed = false;
-            }
-            short reach = ctx.commSystem().getReachabilityStatus();
-            int active = ctx.commSystem().countActivePeers();
-            int known = Math.max(ctx.netDb().getKnownRouters() - 1, 0);
-            int inEx = ctx.tunnelManager().getFreeTunnelCount();
-            int outEx = ctx.tunnelManager().getOutboundTunnelCount();
-            int inCl = ctx.tunnelManager().getInboundClientTunnelCount();
-            int outCl = ctx.tunnelManager().getOutboundClientTunnelCount();
-            int part = ctx.tunnelManager().getParticipatingCount();
-            double dLag = ctx.statManager().getRate("jobQueue.jobLag").getRate(60000).getAverageValue();
-            String jobLag = DataHelper.formatDuration((long) dLag);
-            String msgDelay = DataHelper.formatDuration(ctx.throttle().getMessageDelay());
-            String uptime = DataHelper.formatDuration(ctx.router().getUptime());
-
-            String netstatus = "Unknown";
-            if(reach == net.i2p.router.CommSystemFacade.STATUS_DIFFERENT) {
-                netstatus = "Different";
-            }
-            if(reach == net.i2p.router.CommSystemFacade.STATUS_HOSED) {
-                netstatus = "Hosed";
-            }
-            if(reach == net.i2p.router.CommSystemFacade.STATUS_OK) {
-                netstatus = "OK";
-            }
-            if(reach == net.i2p.router.CommSystemFacade.STATUS_REJECT_UNSOLICITED) {
-                netstatus = "Reject Unsolicited";
-            }
-            String tunnelStatus = ctx.throttle().getTunnelStatus();
-            //ctx.commSystem().getReachabilityStatus();
-            double inBW = ctx.bandwidthLimiter().getReceiveBps() / 1024;
-            double outBW = ctx.bandwidthLimiter().getSendBps() / 1024;
-
-            // control total width
-            DecimalFormat fmt;
-            if(inBW >= 1000 || outBW >= 1000) {
-                fmt = new DecimalFormat("#0");
-            } else if(inBW >= 100 || outBW >= 100) {
-                fmt = new DecimalFormat("#0.0");
-            } else {
-                fmt = new DecimalFormat("#0.00");
-            }
-
-            double kBytesIn = ctx.bandwidthLimiter().getTotalAllocatedInboundBytes() / 1024;
-            double kBytesOut = ctx.bandwidthLimiter().getTotalAllocatedOutboundBytes() / 1024;
-
-            // control total width
-            DecimalFormat kBfmt;
-            if(kBytesIn >= 1000 || kBytesOut >= 1000) {
-                kBfmt = new DecimalFormat("#0");
-            } else if(kBytesIn >= 100 || kBytesOut >= 100) {
-                kBfmt = new DecimalFormat("#0.0");
-            } else {
-                kBfmt = new DecimalFormat("#0.00");
-            }
-
-            String status =
-                    "ROUTER STATUS"
-                    + "\nNetwork: " + netstatus
-                    + "\nPeers active/known: " + active + " / " + known
-                    + "\nExploratory Tunnels in/out: " + inEx + " / " + outEx
-                    + "\nClient Tunnels in/out: " + inCl + " / " + outCl;
-
-
-            // Need to see if we have the participation option set to on.
-            // I thought there was a router method for that? I guess not! WHY NOT?
-            // It would be easier if we had a number to test status.
-            String participate = "\nParticipation: " + tunnelStatus +" (" + part + ")";
-
-            String details =
-                    "\nBandwidth in/out: " + fmt.format(inBW) + " / " + fmt.format(outBW) + " KBps"
-                    + "\nData usage in/out: " + kBfmt.format(kBytesIn) + " / " + kBfmt.format(kBytesOut) + " KB"
-                    + "\nMemory: " + DataHelper.formatSize(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory())
-                    + "B / " + DataHelper.formatSize(Runtime.getRuntime().maxMemory()) + 'B'
-                    + "\nJob Lag: " + jobLag
-                    + "\nMsg Delay: " + msgDelay
-                    + "\nUptime: " + uptime;
-
-            _savedStatus = "Router version: " + _ourVersion + "\n" + status + participate + details;
-            tv.setText(_savedStatus);
-            tv.setVisibility(View.VISIBLE);
-        } else {
-            // network but no router context
-            tv.setText("Router version: " + _ourVersion + "\n");
-            //tv.setVisibility(View.INVISIBLE);
-            /**
-             * **
-             * RouterService svc = _routerService; String status = "connected? "
-             * + Util.isConnected(this) + "\nMemory: " +
-             * DataHelper.formatSize(Runtime.getRuntime().totalMemory() -
-             * Runtime.getRuntime().freeMemory()) + "B / " +
-             * DataHelper.formatSize(Runtime.getRuntime().maxMemory()) + 'B' +
-             * "\nhave ctx? " + (ctx != null) + "\nhave svc? " + (svc != null) +
-             * "\nis bound? " + _isBound + "\nsvc state: " + (svc == null ?
-             * "null" : svc.getState()) + "\ncan start? " + (svc == null ?
-             * "null" : svc.canManualStart()) + "\ncan stop? " + (svc == null ?
-             * "null" : svc.canManualStop()); tv.setText(status);
-             * tv.setVisibility(View.VISIBLE);
-          ***
-             */
-        }
+    protected void onPostCreate(Bundle savedInstanceState) {
+        Util.i("Initializing...");
+        InitActivities init = new InitActivities(this);
+        init.debugStuff();
+        init.initialize();
+        super.onPostCreate(savedInstanceState);
+        // Sync the toggle state after onRestoreInstanceState has occurred.
+        mDrawerToggle.syncState();
     }
 
-    private void checkDialog() {
-        String oldVersion = getPref(PREF_INSTALLED_VERSION, "??");
-        if(oldVersion.equals("??")) {
-            showDialog(DIALOG_NEW_INSTALL);
-        } else {
-            String currentVersion = Util.getOurVersion(this);
-            if(!oldVersion.equals(currentVersion)) {
-                showDialog(DIALOG_NEW_VERSION);
-            }
-        }
+    @Override
+    public void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        // Pass any configuration change to the drawer toggle
+        mDrawerToggle.onConfigurationChanged(newConfig);
     }
 
     @Override
-    protected Dialog onCreateDialog(int id) {
-        final String currentVersion = Util.getOurVersion(this);
-        Dialog rv = null;
-        AlertDialog.Builder b = new AlertDialog.Builder(this);
-        switch(id) {
-            case DIALOG_NEW_INSTALL:
-                b.setMessage(getResources().getText(R.string.welcome_new_install)).setCancelable(false).setPositiveButton("OK", new DialogInterface.OnClickListener() {
-
-                    public void onClick(DialogInterface dialog, int id) {
-                        setPref(PREF_INSTALLED_VERSION, currentVersion);
-                        dialog.cancel();
-                        MainActivity.this.removeDialog(id);
-                    }
-                }).setNeutralButton("Release Notes", new DialogInterface.OnClickListener() {
-
-                    public void onClick(DialogInterface dialog, int id) {
-                        setPref(PREF_INSTALLED_VERSION, currentVersion);
-                        dialog.cancel();
-                        MainActivity.this.removeDialog(id);
-                        Intent intent = new Intent(MainActivity.this, TextResourceActivity.class);
-                        intent.putExtra(TextResourceActivity.TEXT_RESOURCE_ID, R.raw.releasenotes_txt);
-                        startActivity(intent);
-                    }
-                }).setNegativeButton("Licenses", new DialogInterface.OnClickListener() {
-
-                    public void onClick(DialogInterface dialog, int id) {
-                        setPref(PREF_INSTALLED_VERSION, currentVersion);
-                        dialog.cancel();
-                        MainActivity.this.removeDialog(id);
-                        Intent intent = new Intent(MainActivity.this, LicenseActivity.class);
-                        startActivity(intent);
-                    }
-                });
-                rv = b.create();
-                break;
-
-            case DIALOG_NEW_VERSION:
-                b.setMessage(getResources().getText(R.string.welcome_new_version) + " " + currentVersion).setCancelable(true).setPositiveButton("OK", new DialogInterface.OnClickListener() {
-
-                    public void onClick(DialogInterface dialog, int id) {
-                        setPref(PREF_INSTALLED_VERSION, currentVersion);
-                        try {
-                            dialog.dismiss();
-                        } catch(Exception e) {
-                        }
-                        MainActivity.this.removeDialog(id);
-                    }
-                }).setNegativeButton("Release Notes", new DialogInterface.OnClickListener() {
-
-                    public void onClick(DialogInterface dialog, int id) {
-                        setPref(PREF_INSTALLED_VERSION, currentVersion);
-                        try {
-                            dialog.dismiss();
-                        } catch(Exception e) {
-                        }
-                        MainActivity.this.removeDialog(id);
-                        Intent intent = new Intent(MainActivity.this, TextResourceActivity.class);
-                        intent.putExtra(TextResourceActivity.TEXT_RESOURCE_ID, R.raw.releasenotes_txt);
-                        startActivity(intent);
-                    }
-                });
-
-                rv = b.create();
-                break;
+    public void onBackPressed() {
+        I2PFragmentBase fragment = (I2PFragmentBase) getSupportFragmentManager().findFragmentById(R.id.main_content);
+        // If we shouldn't stay on this fragment, go back.
+        if (!fragment.onBackPressed()) {
+            super.onBackPressed();
         }
-        return rv;
     }
 }
diff --git a/src/net/i2p/android/router/activity/MainFragment.java b/src/net/i2p/android/router/activity/MainFragment.java
new file mode 100644
index 000000000..40b1b979e
--- /dev/null
+++ b/src/net/i2p/android/router/activity/MainFragment.java
@@ -0,0 +1,507 @@
+package net.i2p.android.router.activity;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.TextView;
+import java.io.File;
+import java.text.DecimalFormat;
+import net.i2p.android.router.R;
+import net.i2p.android.router.service.RouterService;
+import net.i2p.android.router.util.Util;
+import net.i2p.data.DataHelper;
+import net.i2p.router.RouterContext;
+
+public class MainFragment extends I2PFragmentBase {
+
+    private Handler _handler;
+    private Runnable _updater;
+    private Runnable _oneShotUpdate;
+    private String _savedStatus;
+    private String _ourVersion;
+    private boolean _keep = true;
+    private boolean _startPressed = false;
+    protected static final String PROP_NEW_INSTALL = "i2p.newInstall";
+    protected static final String PROP_NEW_VERSION = "i2p.newVersion";
+    protected static final int DIALOG_NEW_INSTALL = 0;
+    protected static final int DIALOG_NEW_VERSION = 1;
+
+    /**
+     * Called when the fragment is first created.
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        // Init stuff here so settings work.
+        _myDir = getActivity().getFilesDir().getAbsolutePath();
+        if(savedInstanceState != null) {
+            String saved = savedInstanceState.getString("status");
+            if(saved != null) {
+                _savedStatus = saved;
+            }
+        }
+        _ourVersion = Util.getOurVersion(getActivity());
+
+        _keep = true;
+
+        _handler = new Handler();
+        _updater = new Updater();
+        _oneShotUpdate = new OneShotUpdate();
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+                             Bundle savedInstanceState) {
+        View v = inflater.inflate(R.layout.fragment_main, container, false);
+
+        Button b = (Button) v.findViewById(R.id.news_button);
+        b.setOnClickListener(new View.OnClickListener() {
+
+            public void onClick(View view) {
+                Intent intent = new Intent(view.getContext(), NewsFragment.class);
+                startActivity(intent);
+            }
+        });
+
+        b = (Button) v.findViewById(R.id.releasenotes_button);
+        b.setOnClickListener(new View.OnClickListener() {
+
+            public void onClick(View view) {
+                Intent intent = new Intent(view.getContext(), TextResourceFragment.class);
+                intent.putExtra(TextResourceFragment.TEXT_RESOURCE_ID, R.raw.releasenotes_txt);
+                startActivity(intent);
+            }
+        });
+
+        b = (Button) v.findViewById(R.id.licenses_button);
+        b.setOnClickListener(new View.OnClickListener() {
+
+            public void onClick(View view) {
+                Intent intent = new Intent(view.getContext(), LicenseActivity.class);
+                //Intent intent = new Intent(view.getContext(), TextResourceActivity.class);
+                //intent.putExtra(TextResourceActivity.TEXT_RESOURCE_ID, R.raw.licenses_txt);
+                startActivity(intent);
+            }
+        });
+
+        b = (Button) v.findViewById(R.id.website_button);
+        b.setOnClickListener(new View.OnClickListener() {
+
+            public void onClick(View view) {
+                Intent intent = new Intent(view.getContext(), WebFragment.class);
+                //intent.setData((new Uri.Builder()).scheme("http").authority("www.i2p2.de").path("/").build());
+                intent.setData(Uri.parse("http://www.i2p2.de/"));
+                startActivity(intent);
+            }
+        });
+
+        b = (Button) v.findViewById(R.id.faq_button);
+        b.setOnClickListener(new View.OnClickListener() {
+
+            public void onClick(View view) {
+                Intent intent = new Intent(view.getContext(), WebFragment.class);
+                //intent.setData((new Uri.Builder()).scheme("http").authority("www.i2p2.de").path("/faq").build());
+                intent.setData(Uri.parse("http://www.i2p2.de/faq"));
+                startActivity(intent);
+            }
+        });
+
+        b = (Button) v.findViewById(R.id.welcome_button);
+        b.setOnClickListener(new View.OnClickListener() {
+
+            public void onClick(View view) {
+                Intent intent = new Intent(view.getContext(), WebFragment.class);
+                intent.putExtra(WebFragment.HTML_RESOURCE_ID, R.raw.welcome_html);
+                startActivity(intent);
+            }
+        });
+
+        b = (Button) v.findViewById(R.id.addressbook_button);
+        b.setOnClickListener(new View.OnClickListener() {
+
+            public void onClick(View view) {
+                Intent intent = new Intent(view.getContext(), AddressbookActivity.class);
+                startActivity(intent);
+            }
+        });
+
+        b = (Button) v.findViewById(R.id.logs_button);
+        b.setOnClickListener(new View.OnClickListener() {
+
+            public void onClick(View view) {
+                Intent intent = new Intent(view.getContext(), LogActivity.class);
+                startActivity(intent);
+            }
+        });
+
+        b = (Button) v.findViewById(R.id.error_button);
+        b.setOnClickListener(new View.OnClickListener() {
+
+            public void onClick(View view) {
+                Intent intent = new Intent(view.getContext(), LogActivity.class);
+                intent.putExtra(LogActivity.ERRORS_ONLY, true);
+                startActivity(intent);
+            }
+        });
+
+        b = (Button) v.findViewById(R.id.peers_button);
+        b.setOnClickListener(new View.OnClickListener() {
+
+            public void onClick(View view) {
+                Intent intent = new Intent(view.getContext(), PeersFragment.class);
+                startActivity(intent);
+            }
+        });
+
+        /*
+         * hidden, unused b = (Button) v.findViewById(R.id.router_stop_button);
+         * b.setOnClickListener(new View.OnClickListener() { public void
+         * onClick(View view) { RouterService svc = _routerService; if (svc !=
+         * null && _isBound) { setPref(PREF_AUTO_START, false);
+         * svc.manualStop(); updateOneShot(); } } });
+         */
+
+        b = (Button) v.findViewById(R.id.router_start_button);
+        b.setOnClickListener(new View.OnClickListener() {
+
+            public void onClick(View view) {
+                _startPressed = true;
+                RouterService svc = _routerService;
+                if(svc != null && _isBound) {
+                    setPref(PREF_AUTO_START, true);
+                    svc.manualStart();
+                } else {
+                    (new File(_myDir, "wrapper.log")).delete();
+                    startRouter();
+                }
+                updateOneShot();
+            }
+        });
+
+        b = (Button) v.findViewById(R.id.router_quit_button);
+        b.setOnClickListener(new View.OnClickListener() {
+
+            public void onClick(View view) {
+                RouterService svc = _routerService;
+                if(svc != null && _isBound) {
+                    setPref(PREF_AUTO_START, false);
+                    svc.manualQuit();
+                    updateOneShot();
+                }
+            }
+        });
+
+        return v;
+    }
+
+    @Override
+    public void onStart() {
+        super.onStart();
+        _handler.removeCallbacks(_updater);
+        _handler.removeCallbacks(_oneShotUpdate);
+        if(_savedStatus != null) {
+            TextView tv = (TextView) getActivity().findViewById(R.id.main_status_text);
+            tv.setText(_savedStatus);
+        }
+        checkDialog();
+        _handler.postDelayed(_updater, 100);
+    }
+
+    @Override
+    public void onStop() {
+        super.onStop();
+        _handler.removeCallbacks(_updater);
+        _handler.removeCallbacks(_oneShotUpdate);
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        updateOneShot();
+    }
+
+    @Override
+    public void onSaveInstanceState(Bundle outState) {
+        if(_savedStatus != null) {
+            outState.putString("status", _savedStatus);
+        }
+        super.onSaveInstanceState(outState);
+    }
+
+    private void updateOneShot() {
+        _handler.postDelayed(_oneShotUpdate, 100);
+    }
+
+    private class OneShotUpdate implements Runnable {
+
+        public void run() {
+            updateVisibility();
+            updateStatus();
+        }
+    }
+
+    private class Updater implements Runnable {
+
+        private int counter;
+        private final int delay = 1000;
+        private final int toloop = delay / 500;
+        public void run() {
+            updateVisibility();
+            if(counter++ % toloop == 0) {
+                updateStatus();
+            }
+            //_handler.postDelayed(this, 2500);
+            _handler.postDelayed(this, delay);
+        }
+    }
+
+    private void updateVisibility() {
+        RouterService svc = _routerService;
+        boolean showStart = ((svc == null) || (!_isBound) || svc.canManualStart())
+                && Util.isConnected(getActivity());
+        Button start = (Button) getActivity().findViewById(R.id.router_start_button);
+        start.setVisibility(showStart ? View.VISIBLE : View.INVISIBLE);
+
+        boolean showStop = svc != null && _isBound && svc.canManualStop();
+        // Old stop but leave in memory. Always hide for now.
+        // Button stop = (Button) findViewById(R.id.router_stop_button);
+        // stop.setVisibility( /* showStop ? View.VISIBLE : */ View.INVISIBLE);
+
+        Button quit = (Button) getActivity().findViewById(R.id.router_quit_button);
+        quit.setVisibility(showStop ? View.VISIBLE : View.INVISIBLE);
+    }
+
+    public boolean onBackPressed() {
+        RouterContext ctx = getRouterContext();
+        // RouterService svc = _routerService; Which is better to use?!
+        _keep = Util.isConnected(getActivity()) && (ctx != null || _startPressed);
+        Util.d("*********************************************************");
+        Util.d("Back pressed, Keep? " + _keep);
+        Util.d("*********************************************************");
+        return false;
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        if(!_keep) {
+            Thread t = new Thread(new KillMe());
+            t.start();
+        }
+    }
+
+    private class KillMe implements Runnable {
+
+        public void run() {
+            Util.d("*********************************************************");
+            Util.d("KillMe started!");
+            Util.d("*********************************************************");
+            try {
+                Thread.sleep(500); // is 500ms long enough?
+            } catch(InterruptedException ex) {
+            }
+            System.exit(0);
+        }
+    }
+
+    private void updateStatus() {
+        RouterContext ctx = getRouterContext();
+        TextView tv = (TextView) getActivity().findViewById(R.id.main_status_text);
+
+        if(!Util.isConnected(getActivity())) {
+            tv.setText("Router version: " + _ourVersion + "\nNo Internet connection is available");
+            tv.setVisibility(View.VISIBLE);
+        } else if(ctx != null) {
+            if(_startPressed) {
+                _startPressed = false;
+            }
+            short reach = ctx.commSystem().getReachabilityStatus();
+            int active = ctx.commSystem().countActivePeers();
+            int known = Math.max(ctx.netDb().getKnownRouters() - 1, 0);
+            int inEx = ctx.tunnelManager().getFreeTunnelCount();
+            int outEx = ctx.tunnelManager().getOutboundTunnelCount();
+            int inCl = ctx.tunnelManager().getInboundClientTunnelCount();
+            int outCl = ctx.tunnelManager().getOutboundClientTunnelCount();
+            int part = ctx.tunnelManager().getParticipatingCount();
+            double dLag = ctx.statManager().getRate("jobQueue.jobLag").getRate(60000).getAverageValue();
+            String jobLag = DataHelper.formatDuration((long) dLag);
+            String msgDelay = DataHelper.formatDuration(ctx.throttle().getMessageDelay());
+            String uptime = DataHelper.formatDuration(ctx.router().getUptime());
+
+            String netstatus = "Unknown";
+            if(reach == net.i2p.router.CommSystemFacade.STATUS_DIFFERENT) {
+                netstatus = "Different";
+            }
+            if(reach == net.i2p.router.CommSystemFacade.STATUS_HOSED) {
+                netstatus = "Hosed";
+            }
+            if(reach == net.i2p.router.CommSystemFacade.STATUS_OK) {
+                netstatus = "OK";
+            }
+            if(reach == net.i2p.router.CommSystemFacade.STATUS_REJECT_UNSOLICITED) {
+                netstatus = "Reject Unsolicited";
+            }
+            String tunnelStatus = ctx.throttle().getTunnelStatus();
+            //ctx.commSystem().getReachabilityStatus();
+            double inBW = ctx.bandwidthLimiter().getReceiveBps() / 1024;
+            double outBW = ctx.bandwidthLimiter().getSendBps() / 1024;
+
+            // control total width
+            DecimalFormat fmt;
+            if(inBW >= 1000 || outBW >= 1000) {
+                fmt = new DecimalFormat("#0");
+            } else if(inBW >= 100 || outBW >= 100) {
+                fmt = new DecimalFormat("#0.0");
+            } else {
+                fmt = new DecimalFormat("#0.00");
+            }
+
+            double kBytesIn = ctx.bandwidthLimiter().getTotalAllocatedInboundBytes() / 1024;
+            double kBytesOut = ctx.bandwidthLimiter().getTotalAllocatedOutboundBytes() / 1024;
+
+            // control total width
+            DecimalFormat kBfmt;
+            if(kBytesIn >= 1000 || kBytesOut >= 1000) {
+                kBfmt = new DecimalFormat("#0");
+            } else if(kBytesIn >= 100 || kBytesOut >= 100) {
+                kBfmt = new DecimalFormat("#0.0");
+            } else {
+                kBfmt = new DecimalFormat("#0.00");
+            }
+
+            String status =
+                    "ROUTER STATUS"
+                    + "\nNetwork: " + netstatus
+                    + "\nPeers active/known: " + active + " / " + known
+                    + "\nExploratory Tunnels in/out: " + inEx + " / " + outEx
+                    + "\nClient Tunnels in/out: " + inCl + " / " + outCl;
+
+
+            // Need to see if we have the participation option set to on.
+            // I thought there was a router method for that? I guess not! WHY NOT?
+            // It would be easier if we had a number to test status.
+            String participate = "\nParticipation: " + tunnelStatus +" (" + part + ")";
+
+            String details =
+                    "\nBandwidth in/out: " + fmt.format(inBW) + " / " + fmt.format(outBW) + " KBps"
+                    + "\nData usage in/out: " + kBfmt.format(kBytesIn) + " / " + kBfmt.format(kBytesOut) + " KB"
+                    + "\nMemory: " + DataHelper.formatSize(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory())
+                    + "B / " + DataHelper.formatSize(Runtime.getRuntime().maxMemory()) + 'B'
+                    + "\nJob Lag: " + jobLag
+                    + "\nMsg Delay: " + msgDelay
+                    + "\nUptime: " + uptime;
+
+            _savedStatus = "Router version: " + _ourVersion + "\n" + status + participate + details;
+            tv.setText(_savedStatus);
+            tv.setVisibility(View.VISIBLE);
+        } else {
+            // network but no router context
+            tv.setText("Router version: " + _ourVersion + "\n");
+            //tv.setVisibility(View.INVISIBLE);
+            /**
+             * **
+             * RouterService svc = _routerService; String status = "connected? "
+             * + Util.isConnected(this) + "\nMemory: " +
+             * DataHelper.formatSize(Runtime.getRuntime().totalMemory() -
+             * Runtime.getRuntime().freeMemory()) + "B / " +
+             * DataHelper.formatSize(Runtime.getRuntime().maxMemory()) + 'B' +
+             * "\nhave ctx? " + (ctx != null) + "\nhave svc? " + (svc != null) +
+             * "\nis bound? " + _isBound + "\nsvc state: " + (svc == null ?
+             * "null" : svc.getState()) + "\ncan start? " + (svc == null ?
+             * "null" : svc.canManualStart()) + "\ncan stop? " + (svc == null ?
+             * "null" : svc.canManualStop()); tv.setText(status);
+             * tv.setVisibility(View.VISIBLE);
+          ***
+             */
+        }
+    }
+
+    private void checkDialog() {
+        String oldVersion = getPref(PREF_INSTALLED_VERSION, "??");
+        /*if(oldVersion.equals("??")) {
+            getActivity().showDialog(DIALOG_NEW_INSTALL);
+        } else {
+            String currentVersion = Util.getOurVersion(getActivity());
+            if(!oldVersion.equals(currentVersion)) {
+                getActivity().showDialog(DIALOG_NEW_VERSION);
+            }
+        }*/
+    }
+
+    /*@Override
+    protected Dialog onCreateDialog(int id) {
+        final String currentVersion = Util.getOurVersion(this);
+        Dialog rv = null;
+        AlertDialog.Builder b = new AlertDialog.Builder(this);
+        switch(id) {
+            case DIALOG_NEW_INSTALL:
+                b.setMessage(getResources().getText(R.string.welcome_new_install)).setCancelable(false).setPositiveButton("OK", new DialogInterface.OnClickListener() {
+
+                    public void onClick(DialogInterface dialog, int id) {
+                        setPref(PREF_INSTALLED_VERSION, currentVersion);
+                        dialog.cancel();
+                        MainActivity.this.removeDialog(id);
+                    }
+                }).setNeutralButton("Release Notes", new DialogInterface.OnClickListener() {
+
+                    public void onClick(DialogInterface dialog, int id) {
+                        setPref(PREF_INSTALLED_VERSION, currentVersion);
+                        dialog.cancel();
+                        MainActivity.this.removeDialog(id);
+                        Intent intent = new Intent(MainActivity.this, TextResourceActivity.class);
+                        intent.putExtra(TextResourceActivity.TEXT_RESOURCE_ID, R.raw.releasenotes_txt);
+                        startActivity(intent);
+                    }
+                }).setNegativeButton("Licenses", new DialogInterface.OnClickListener() {
+
+                    public void onClick(DialogInterface dialog, int id) {
+                        setPref(PREF_INSTALLED_VERSION, currentVersion);
+                        dialog.cancel();
+                        MainActivity.this.removeDialog(id);
+                        Intent intent = new Intent(MainActivity.this, LicenseActivity.class);
+                        startActivity(intent);
+                    }
+                });
+                rv = b.create();
+                break;
+
+            case DIALOG_NEW_VERSION:
+                b.setMessage(getResources().getText(R.string.welcome_new_version) + " " + currentVersion).setCancelable(true).setPositiveButton("OK", new DialogInterface.OnClickListener() {
+
+                    public void onClick(DialogInterface dialog, int id) {
+                        setPref(PREF_INSTALLED_VERSION, currentVersion);
+                        try {
+                            dialog.dismiss();
+                        } catch(Exception e) {
+                        }
+                        MainActivity.this.removeDialog(id);
+                    }
+                }).setNegativeButton("Release Notes", new DialogInterface.OnClickListener() {
+
+                    public void onClick(DialogInterface dialog, int id) {
+                        setPref(PREF_INSTALLED_VERSION, currentVersion);
+                        try {
+                            dialog.dismiss();
+                        } catch(Exception e) {
+                        }
+                        MainActivity.this.removeDialog(id);
+                        Intent intent = new Intent(MainActivity.this, TextResourceActivity.class);
+                        intent.putExtra(TextResourceActivity.TEXT_RESOURCE_ID, R.raw.releasenotes_txt);
+                        startActivity(intent);
+                    }
+                });
+
+                rv = b.create();
+                break;
+        }
+        return rv;
+    }*/
+}
diff --git a/src/net/i2p/android/router/activity/NewsActivity.java b/src/net/i2p/android/router/activity/NewsFragment.java
similarity index 76%
rename from src/net/i2p/android/router/activity/NewsActivity.java
rename to src/net/i2p/android/router/activity/NewsFragment.java
index efe1ffdd5..a744c350d 100644
--- a/src/net/i2p/android/router/activity/NewsActivity.java
+++ b/src/net/i2p/android/router/activity/NewsFragment.java
@@ -3,6 +3,9 @@ package net.i2p.android.router.activity;
 import android.content.res.Resources;
 import android.os.Bundle;
 import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
 import android.webkit.WebView;
 import android.widget.TextView;
 import java.io.ByteArrayOutputStream;
@@ -14,7 +17,7 @@ import java.io.UnsupportedEncodingException;
 import net.i2p.android.apps.NewsFetcher;
 import net.i2p.android.router.R;
 
-public class NewsActivity extends I2PActivityBase {
+public class NewsFragment extends I2PFragmentBase {
 
     private I2PWebViewClient _wvClient;
     private long _lastChanged;
@@ -29,17 +32,18 @@ public class NewsActivity extends I2PActivityBase {
     private static final String FOOTER = "</body></html>";
 
     @Override
-    public void onCreate(Bundle savedInstanceState)
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+                             Bundle savedInstanceState)
     {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.news);
-        WebView wv = (WebView) findViewById(R.id.news_webview);
+        View v = inflater.inflate(R.layout.news, container, false);
+        WebView wv = (WebView) v.findViewById(R.id.news_webview);
         wv.getSettings().setLoadsImagesAutomatically(false);
         // http://stackoverflow.com/questions/2369310/webview-double-tap-zoom-not-working-on-a-motorola-droid-a855
         wv.getSettings().setUseWideViewPort(true);
-        _wvClient = new I2PWebViewClient(this);
+        _wvClient = new I2PWebViewClient();
         wv.setWebViewClient(_wvClient);
         wv.getSettings().setBuiltInZoomControls(true);
+        return v;
     }
 
     @Override
@@ -49,7 +53,7 @@ public class NewsActivity extends I2PActivityBase {
         NewsFetcher nf = NewsFetcher.getInstance();
         if (nf != null) {
             // always update the text
-            TextView tv = (TextView) findViewById(R.id.news_status);
+            TextView tv = (TextView) getActivity().findViewById(R.id.news_status);
             tv.setText(WARNING + nf.status().replace("&nbsp;", " "));
         }
 
@@ -60,7 +64,7 @@ public class NewsActivity extends I2PActivityBase {
             return;
         _lastChanged = System.currentTimeMillis();
 
-        WebView wv = (WebView) findViewById(R.id.news_webview);
+        WebView wv = (WebView) getActivity().findViewById(R.id.news_webview);
 
         InputStream in = null;
         ByteArrayOutputStream out = new ByteArrayOutputStream(2048);
@@ -94,16 +98,14 @@ public class NewsActivity extends I2PActivityBase {
     }
 
     @Override
-    public boolean onKeyDown(int keyCode, KeyEvent event) {
-        WebView wv = (WebView) findViewById(R.id.news_webview);
-        if ((keyCode == KeyEvent.KEYCODE_BACK)) {
-            _wvClient.cancelAll();
-            wv.stopLoading();
-            if (wv.canGoBack()) {
-                wv.goBack();
-                return true;
-            }
+    public boolean onBackPressed() {
+        WebView wv = (WebView) getActivity().findViewById(R.id.news_webview);
+        _wvClient.cancelAll();
+        wv.stopLoading();
+        if (wv.canGoBack()) {
+            wv.goBack();
+            return true;
         }
-        return super.onKeyDown(keyCode, event);
+        return false;
     }
 }
diff --git a/src/net/i2p/android/router/activity/PeersActivity.java b/src/net/i2p/android/router/activity/PeersFragment.java
similarity index 71%
rename from src/net/i2p/android/router/activity/PeersActivity.java
rename to src/net/i2p/android/router/activity/PeersFragment.java
index 395ec0280..83be6bbaa 100644
--- a/src/net/i2p/android/router/activity/PeersActivity.java
+++ b/src/net/i2p/android/router/activity/PeersFragment.java
@@ -2,7 +2,10 @@ package net.i2p.android.router.activity;
 
 import android.os.Bundle;
 import android.view.KeyEvent;
+import android.view.LayoutInflater;
 import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
 import android.webkit.WebView;
 import java.io.IOException;
 import java.io.StringWriter;
@@ -11,7 +14,7 @@ import net.i2p.android.router.service.RouterService;
 import net.i2p.android.router.util.Util;
 import net.i2p.router.CommSystemFacade;
 
-public class PeersActivity extends I2PActivityBase {
+public class PeersFragment extends I2PFragmentBase {
 
     private I2PWebViewClient _wvClient;
 
@@ -20,17 +23,18 @@ public class PeersActivity extends I2PActivityBase {
     private static final String FOOTER = "</body></html>";
 
     @Override
-    public void onCreate(Bundle savedInstanceState)
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+                             Bundle savedInstanceState)
     {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.peers);
-        WebView wv = (WebView) findViewById(R.id.peers_webview);
+        View v = inflater.inflate(R.layout.peers, container, false);
+        WebView wv = (WebView) v.findViewById(R.id.peers_webview);
         wv.getSettings().setLoadsImagesAutomatically(true); // was false
         // http://stackoverflow.com/questions/2369310/webview-double-tap-zoom-not-working-on-a-motorola-droid-a855
         wv.getSettings().setUseWideViewPort(true);
-        _wvClient = new I2PWebViewClient(this);
+        _wvClient = new I2PWebViewClient();
         wv.setWebViewClient(_wvClient);
         wv.getSettings().setBuiltInZoomControls(true);
+        return v;
     }
 
     @Override
@@ -49,7 +53,7 @@ public class PeersActivity extends I2PActivityBase {
     }
 
     private void update() {
-        WebView wv = (WebView) findViewById(R.id.peers_webview);
+        WebView wv = (WebView) getActivity().findViewById(R.id.peers_webview);
         wv.clearHistory(); // fixes having to hit back.
         CommSystemFacade comm = getCommSystem();
         String data;
@@ -77,25 +81,23 @@ public class PeersActivity extends I2PActivityBase {
     }
 
     @Override
-    public boolean onKeyDown(int keyCode, KeyEvent event) {
-        WebView wv = (WebView) findViewById(R.id.peers_webview);
-        if ((keyCode == KeyEvent.KEYCODE_BACK)) {
-            _wvClient.cancelAll();
-            wv.stopLoading();
+    public boolean onBackPressed() {
+        WebView wv = (WebView) getActivity().findViewById(R.id.peers_webview);
+        _wvClient.cancelAll();
+        wv.stopLoading();
 
-            // We do not want to go back, or keep history... Theere is no need to.
-            // What we DO want to do is exit!
-            //if (wv.canGoBack()) {
-            //    wv.goBack();
-            //    return true;
-            //}
-        }
-        return super.onKeyDown(keyCode, event);
+        // We do not want to go back, or keep history... There is no need to.
+        // What we DO want to do is exit!
+        //if (wv.canGoBack()) {
+        //    wv.goBack();
+        //    return true;
+        //}
+        return false;
     }
 
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
-        WebView wv = (WebView) findViewById(R.id.peers_webview);
+        WebView wv = (WebView) getActivity().findViewById(R.id.peers_webview);
         switch (item.getItemId()) {
         case R.id.menu_reload:
             update();
diff --git a/src/net/i2p/android/router/activity/TextResourceActivity.java b/src/net/i2p/android/router/activity/TextResourceFragment.java
similarity index 77%
rename from src/net/i2p/android/router/activity/TextResourceActivity.java
rename to src/net/i2p/android/router/activity/TextResourceFragment.java
index b9c2ed33d..6bd00c217 100644
--- a/src/net/i2p/android/router/activity/TextResourceActivity.java
+++ b/src/net/i2p/android/router/activity/TextResourceFragment.java
@@ -4,6 +4,9 @@ import android.content.Intent;
 import android.content.res.Resources;
 import android.os.Bundle;
 import android.text.method.ScrollingMovementMethod;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
 import android.widget.TextView;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
@@ -16,24 +19,25 @@ import net.i2p.android.router.util.Util;
  *  Display a raw text resource.
  *  The resource ID must be passed as an extra in the intent.
  */
-public class TextResourceActivity extends I2PActivityBase {
+public class TextResourceFragment extends I2PFragmentBase {
 
     final static String TEXT_RESOURCE_ID = "text_resource_id";
 
     @Override
-    public void onCreate(Bundle savedInstanceState)
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+                             Bundle savedInstanceState)
     {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.text_resource);
-        TextView tv = (TextView) findViewById(R.id.text_resource_text);
+        View v = inflater.inflate(R.layout.text_resource, container, false);
+        TextView tv = (TextView) v.findViewById(R.id.text_resource_text);
         tv.setMovementMethod(ScrollingMovementMethod.getInstance());
-        Intent intent = getIntent();
+        Intent intent = getActivity().getIntent();
         int id = intent.getIntExtra(TEXT_RESOURCE_ID, R.raw.releasenotes_txt);
         if (id == R.raw.releasenotes_txt)
-            tv.setText("Release Notes for Release " + Util.getOurVersion(this) + "\n\n" +
+            tv.setText("Release Notes for Release " + Util.getOurVersion(getActivity()) + "\n\n" +
                        getResourceAsString(id));
         else
             tv.setText(getResourceAsString(id));
+        return v;
     }
 
     private String getResourceAsString(int id) {
diff --git a/src/net/i2p/android/router/activity/WebActivity.java b/src/net/i2p/android/router/activity/WebFragment.java
similarity index 75%
rename from src/net/i2p/android/router/activity/WebActivity.java
rename to src/net/i2p/android/router/activity/WebFragment.java
index b1953ff1f..0b6f04b2a 100644
--- a/src/net/i2p/android/router/activity/WebActivity.java
+++ b/src/net/i2p/android/router/activity/WebFragment.java
@@ -5,7 +5,10 @@ import android.content.res.Resources;
 import android.net.Uri;
 import android.os.Bundle;
 import android.view.KeyEvent;
+import android.view.LayoutInflater;
 import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
 import android.webkit.WebView;
 import android.widget.TextView;
 import java.io.ByteArrayOutputStream;
@@ -14,7 +17,7 @@ import java.io.InputStream;
 import java.io.UnsupportedEncodingException;
 import net.i2p.android.router.R;
 
-public class WebActivity extends I2PActivityBase {
+public class WebFragment extends I2PFragmentBase {
 
     private I2PWebViewClient _wvClient;
 
@@ -24,19 +27,19 @@ public class WebActivity extends I2PActivityBase {
                "not anonymous. I2P pages may not load images or CSS.";
 
     @Override
-    public void onCreate(Bundle savedInstanceState)
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+                             Bundle savedInstanceState)
     {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.web);
-        TextView tv = (TextView) findViewById(R.id.browser_status);
+        View v = inflater.inflate(R.layout.web, container, false);
+        TextView tv = (TextView) v.findViewById(R.id.browser_status);
         tv.setText(WARNING);
-        WebView wv = (WebView) findViewById(R.id.browser_webview);
-        _wvClient = new I2PWebViewClient(this);
+        WebView wv = (WebView) v.findViewById(R.id.browser_webview);
+        _wvClient = new I2PWebViewClient();
         wv.setWebViewClient(_wvClient);
         wv.getSettings().setBuiltInZoomControls(true);
         // http://stackoverflow.com/questions/2369310/webview-double-tap-zoom-not-working-on-a-motorola-droid-a855
         wv.getSettings().setUseWideViewPort(true);
-        Intent intent = getIntent();
+        Intent intent = getActivity().getIntent();
         Uri uri = intent.getData();
         if (uri != null) {
             //wv.getSettings().setLoadsImagesAutomatically(true);
@@ -50,6 +53,7 @@ public class WebActivity extends I2PActivityBase {
             if (id != 0)
                 loadResource(wv, id);
         }
+        return v;
     }
 
     private void loadResource(WebView wv, int id) {
@@ -77,24 +81,22 @@ public class WebActivity extends I2PActivityBase {
     }
 
     @Override
-    public boolean onKeyDown(int keyCode, KeyEvent event) {
-        WebView wv = (WebView) findViewById(R.id.browser_webview);
-        if ((keyCode == KeyEvent.KEYCODE_BACK)) {
-            _wvClient.cancelAll();
-            wv.stopLoading();
-            if (wv.canGoBack()) {
-                // TODO go into history, get url and call shouldOverrideUrlLoading()
-                // so we have control ??? But then back won't work right
-                wv.goBack();
-                return true;
-            }
+    public boolean onBackPressed() {
+        WebView wv = (WebView) getActivity().findViewById(R.id.browser_webview);
+        _wvClient.cancelAll();
+        wv.stopLoading();
+        if (wv.canGoBack()) {
+            // TODO go into history, get url and call shouldOverrideUrlLoading()
+            // so we have control ??? But then back won't work right
+            wv.goBack();
+            return true;
         }
-        return super.onKeyDown(keyCode, event);
+        return false;
     }
 
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
-        WebView wv = (WebView) findViewById(R.id.browser_webview);
+        WebView wv = (WebView) getActivity().findViewById(R.id.browser_webview);
         switch (item.getItemId()) {
         case R.id.menu_reload:
             _wvClient.cancelAll();
-- 
GitLab