diff --git a/android/.gitignore b/android/.gitignore
index d9fa5a57..7e166aa6 100644
--- a/android/.gitignore
+++ b/android/.gitignore
@@ -5,4 +5,8 @@ ant.properties
 local.properties
 build.sh
 bin
-log*
\ No newline at end of file
+log*
+.gradle*
+build
+assets
+gradle-app.setting
diff --git a/android/build.gradle b/android/build.gradle
index a88403fd..46d0d057 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -11,23 +11,24 @@ buildscript {
 apply plugin: 'com.android.application'
 
 android {
-        compileSdkVersion 25
-        buildToolsVersion "25.0.2"
-        defaultConfig {
-                applicationId "org.purplei2p.i2pd"
-                targetSdkVersion 25
-                minSdkVersion 14
-                versionCode 1
-                versionName "2.17.1"
-        }
+    compileSdkVersion 25
+    buildToolsVersion "25.0.0"
+    defaultConfig {
+        applicationId "org.purplei2p.i2pd"
+        targetSdkVersion 25
+        minSdkVersion 14
+        versionCode 1
+        versionName "2.17.2e"
+    }
     sourceSets {
         main {
             manifest.srcFile 'AndroidManifest.xml'
             java.srcDirs = ['src']
-                        res.srcDirs = ['res']
-                        jniLibs.srcDirs = ['libs']
-        }
+            res.srcDirs = ['res']
+            jniLibs.srcDirs = ['libs']
+            assets.srcDirs = ['assets']
         }
+    }
     signingConfigs {
         orignal {
             storeFile file("i2pdapk.jks")
@@ -37,11 +38,30 @@ android {
         }
     }
     buildTypes {
-                release {
-                        minifyEnabled false
-                        signingConfig signingConfigs.orignal
-                        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt'
-                }
+        release {
+            minifyEnabled false
+            signingConfig signingConfigs.orignal
+            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt'
+        }
     }
 }
 
+tasks.withType(JavaCompile) {
+    options.compilerArgs << '-Xlint:unchecked' << '-Xlint:deprecation'
+    options.deprecation = true
+}
+
+task zipCerts(type:Zip) {
+    from (files('../contrib/'))
+    include 'certificates/**/*.crt'
+    destinationDir file('assets')
+    archiveName 'certificates.zip'
+    entryCompression ZipEntryCompression.STORED
+}
+preBuild.dependsOn zipCerts
+
+task clean(type: Delete,overwrite: true) {
+    delete 'build'
+    delete 'assets'
+}
+
diff --git a/android/jni/DaemonAndroid.cpp b/android/jni/DaemonAndroid.cpp
index 75584740..9865ac79 100644
--- a/android/jni/DaemonAndroid.cpp
+++ b/android/jni/DaemonAndroid.cpp
@@ -126,12 +126,11 @@ namespace android
 	}
 */
 	static DaemonAndroidImpl daemon;
-	static char* argv[1]={strdup("tmp")};
 	/**
 	 * returns error details if failed
 	 * returns "ok" if daemon initialized and started okay
 	 */
-	std::string start(/*int argc, char* argv[]*/)
+	std::string start(int argc, char* argv[])
 	{
 		try
 		{
@@ -139,7 +138,7 @@ namespace android
 
 			{
 				//Log.d(TAG"Initialising the daemon...");
-				bool daemonInitSuccess = daemon.init(1,argv);
+				bool daemonInitSuccess = daemon.init(argc,argv);
 				if(!daemonInitSuccess)
 				{
 					//QMessageBox::critical(0, "Error", "Daemon init failed");
diff --git a/android/jni/DaemonAndroid.h b/android/jni/DaemonAndroid.h
index 9cc8219b..81031936 100644
--- a/android/jni/DaemonAndroid.h
+++ b/android/jni/DaemonAndroid.h
@@ -37,7 +37,7 @@ namespace android
 	 * returns "ok" if daemon init failed
 	 * returns errinfo if daemon initialized and started okay
 	 */
-    std::string start();
+    std::string start(int argc, char* argv[]);
 
     // stops the daemon
     void stop();
diff --git a/android/jni/i2pd_android.cpp b/android/jni/i2pd_android.cpp
index 8791c90b..1079a252 100755
--- a/android/jni/i2pd_android.cpp
+++ b/android/jni/i2pd_android.cpp
@@ -44,8 +44,24 @@ JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getABICompiledWith
 }
 
 JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startDaemon
-  (JNIEnv * env, jclass clazz) {
-	return env->NewStringUTF(i2p::android::start().c_str());
+  (JNIEnv * env, jclass clazz, jobjectArray args) {
+    int argc = env->GetArrayLength(args);
+    typedef char *pchar;
+    pchar* argv = new pchar[argc];
+    for (int i = 0; i < argc; i++) {
+        jstring arg = (jstring) env->GetObjectArrayElement(args, i);
+        const char *argStr = env->GetStringUTFChars(arg, 0);
+        size_t len = strlen(argStr);
+        argv[i] = new char[len + 1];
+        strcpy(argv[i], argStr);
+        env->ReleaseStringUTFChars(arg, argStr);
+    }
+    const char* result = i2p::android::start(argc,argv).c_str();
+    for (int i = 0; i < argc; i++) {
+        delete [] argv[i];
+    }
+    delete [] argv;
+    return env->NewStringUTF(result);
 }
 
 JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopDaemon
diff --git a/android/jni/org_purplei2p_i2pd_I2PD_JNI.h b/android/jni/org_purplei2p_i2pd_I2PD_JNI.h
index 04923d22..484b3230 100644
--- a/android/jni/org_purplei2p_i2pd_I2PD_JNI.h
+++ b/android/jni/org_purplei2p_i2pd_I2PD_JNI.h
@@ -16,7 +16,7 @@ JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getABICompiledWith
   (JNIEnv *, jclass);
 
 JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startDaemon
-  (JNIEnv *, jclass);
+  (JNIEnv *, jclass, jobjectArray args);
 
 JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopDaemon
   (JNIEnv *, jclass);
diff --git a/android/src/org/purplei2p/i2pd/DaemonSingleton.java b/android/src/org/purplei2p/i2pd/DaemonSingleton.java
index 65afd0f5..beff0c39 100644
--- a/android/src/org/purplei2p/i2pd/DaemonSingleton.java
+++ b/android/src/org/purplei2p/i2pd/DaemonSingleton.java
@@ -14,10 +14,10 @@ public class DaemonSingleton {
 	public static DaemonSingleton getInstance() {
 		return instance;
 	}
-
+	
 	public synchronized void addStateChangeListener(StateUpdateListener listener) { stateUpdateListeners.add(listener); }
 	public synchronized void removeStateChangeListener(StateUpdateListener listener) { stateUpdateListeners.remove(listener); }
-
+	
 	public synchronized void stopAcceptingTunnels() {
 		if(isStartedOkay()){
 			state=State.gracefulShutdownInProgress;
@@ -25,20 +25,21 @@ public class DaemonSingleton {
 			I2PD_JNI.stopAcceptingTunnels();
 		}
 	}
-
+	
 	public void onNetworkStateChange(boolean isConnected) {
 		I2PD_JNI.onNetworkStateChanged(isConnected);
 	}
-
+	
 	private boolean startedOkay;
 
 	public static enum State {uninitialized,starting,jniLibraryLoaded,startedOkay,startFailed,gracefulShutdownInProgress};
-
+	
 	private State state = State.uninitialized;
-
+	
 	public State getState() { return state; }
+	
+    public synchronized void start(final String confDir, final String dataDir) {
 
-	public synchronized void start() {
 		if(state != State.uninitialized)return;
 		state = State.starting;
 		fireStateUpdate();
@@ -62,7 +63,15 @@ public class DaemonSingleton {
 				}
 				try {
 					synchronized (DaemonSingleton.this) {
-						daemonStartResult = I2PD_JNI.startDaemon();
+
+						String args[] = new String[] {
+							"i2pd", "--service", "--daemon", 
+								"--datadir=" + dataDir,
+								"--conf=" + confDir + "/i2pd.conf",
+								"--tunconf=" + confDir + "/tunnels.conf"
+						};
+
+						daemonStartResult = I2PD_JNI.startDaemon(args);
 						if("ok".equals(daemonStartResult)){
 							state=State.startedOkay;
 							setStartedOkay(true);
@@ -76,9 +85,9 @@ public class DaemonSingleton {
 						fireStateUpdate();
 					}
 					return;
-				}
+				}				
 			}
-
+			
 		}, "i2pdDaemonStart").start();
 	}
 	private Throwable lastThrowable;
@@ -87,10 +96,10 @@ public class DaemonSingleton {
 	private synchronized void fireStateUpdate() {
 		Log.i(TAG, "daemon state change: "+state);
 		for(StateUpdateListener listener : stateUpdateListeners) {
-			try {
-				listener.daemonStateUpdate();
-			} catch (Throwable tr) {
-				Log.e(TAG, "exception in listener ignored", tr);
+			try { 
+				listener.daemonStateUpdate(); 
+			} catch (Throwable tr) { 
+				Log.e(TAG, "exception in listener ignored", tr); 
 			}
 		}
 	}
@@ -102,7 +111,7 @@ public class DaemonSingleton {
 	public String getDaemonStartResult() {
 		return daemonStartResult;
 	}
-
+	
 	private final Object startedOkayLock = new Object();
 
 	public boolean isStartedOkay() {
diff --git a/android/src/org/purplei2p/i2pd/Decompress.java b/android/src/org/purplei2p/i2pd/Decompress.java
new file mode 100644
index 00000000..917abc7c
--- /dev/null
+++ b/android/src/org/purplei2p/i2pd/Decompress.java
@@ -0,0 +1,83 @@
+package org.purplei2p.i2pd;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+import android.content.Context;
+import android.util.Log;
+
+public class Decompress {
+    private static final int BUFFER_SIZE = 1024 * 10;
+    private static final String TAG = "Decompress";
+
+    public static void unzipFromAssets(Context context, String zipFile, String destination) {
+        try {
+            if (destination == null || destination.length() == 0)
+                destination = context.getFilesDir().getAbsolutePath();
+            InputStream stream = context.getAssets().open(zipFile);
+            unzip(stream, destination);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public static void unzip(String zipFile, String location) {
+        try {
+            FileInputStream fin = new FileInputStream(zipFile);
+            unzip(fin, location);
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        }
+
+    }
+
+    public static void unzip(InputStream stream, String destination) {
+        dirChecker(destination, "");
+        byte[] buffer = new byte[BUFFER_SIZE];
+        try {
+            ZipInputStream zin = new ZipInputStream(stream);
+            ZipEntry ze = null;
+
+            while ((ze = zin.getNextEntry()) != null) {
+                Log.v(TAG, "Unzipping " + ze.getName());
+
+                if (ze.isDirectory()) {
+                    dirChecker(destination, ze.getName());
+                } else {
+                    File f = new File(destination + ze.getName());
+                    if (!f.exists()) {
+                        FileOutputStream fout = new FileOutputStream(destination + ze.getName());
+                        int count;
+                        while ((count = zin.read(buffer)) != -1) {
+                            fout.write(buffer, 0, count);
+                        }
+                        zin.closeEntry();
+                        fout.close();
+                    }
+                }
+
+            }
+            zin.close();
+        } catch (Exception e) {
+            Log.e(TAG, "unzip", e);
+        }
+
+    }
+
+    private static void dirChecker(String destination, String dir) {
+        File f = new File(destination + dir);
+
+        if (!f.isDirectory()) {
+            boolean success = f.mkdirs();
+            if (!success) {
+                Log.w(TAG, "Failed to create folder " + f.getName());
+            }
+        }
+    }
+}
diff --git a/android/src/org/purplei2p/i2pd/ForegroundService.java b/android/src/org/purplei2p/i2pd/ForegroundService.java
index bfd650c8..645d0dca 100644
--- a/android/src/org/purplei2p/i2pd/ForegroundService.java
+++ b/android/src/org/purplei2p/i2pd/ForegroundService.java
@@ -5,6 +5,8 @@ import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.app.Service;
 import android.content.Intent;
+import android.content.Context;
+import android.os.Environment;
 import android.os.Binder;
 import android.os.IBinder;
 import android.util.Log;
@@ -28,13 +30,20 @@ public class ForegroundService extends Service {
         }
     }
 
+    private String dataDir;
+    private String confDir;
+
     @Override
     public void onCreate() {
         notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
+        dataDir = this.getDir("data", Context.MODE_PRIVATE).toString();
+        confDir = Environment.getExternalStoragePublicDirectory("i2pd").toString();
 
         // Display a notification about us starting.  We put an icon in the status bar.
         showNotification();
-        daemon.start();
+
+        Log.i("ForegroundService", "About to start daemon with dataDir: " + dataDir + ", confDir: " + confDir);
+        daemon.start(confDir, dataDir);
         // Tell the user we started.
         Toast.makeText(this, R.string.i2pd_service_started, Toast.LENGTH_SHORT).show();
     }
@@ -42,7 +51,7 @@ public class ForegroundService extends Service {
     @Override
     public int onStartCommand(Intent intent, int flags, int startId) {
         Log.i("ForegroundService", "Received start id " + startId + ": " + intent);
-        daemon.start();
+        daemon.start(confDir, dataDir);
         return START_STICKY;
     }
 
@@ -50,7 +59,7 @@ public class ForegroundService extends Service {
     public void onDestroy() {
         // Cancel the persistent notification.
         notificationManager.cancel(NOTIFICATION);
-
+        
         stopForeground(true);
 
         // Tell the user we stopped.
@@ -91,7 +100,7 @@ public class ForegroundService extends Service {
         //mNM.notify(NOTIFICATION, notification);
         startForeground(NOTIFICATION, notification);
     }
-
+    
 	private final DaemonSingleton daemon = DaemonSingleton.getInstance();
 }
 
diff --git a/android/src/org/purplei2p/i2pd/I2PD.java b/android/src/org/purplei2p/i2pd/I2PD.java
index a2494b2b..d66a0174 100755
--- a/android/src/org/purplei2p/i2pd/I2PD.java
+++ b/android/src/org/purplei2p/i2pd/I2PD.java
@@ -2,6 +2,13 @@ package org.purplei2p.i2pd;
 
 import java.io.PrintWriter;
 import java.io.StringWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
 import java.util.Timer;
 import java.util.TimerTask;
 
@@ -24,12 +31,12 @@ public class I2PD extends Activity {
 	private static final String TAG = "i2pd";
 
 	private TextView textView;
-
+	
 	private final DaemonSingleton daemon = DaemonSingleton.getInstance();
 
 	private DaemonSingleton.StateUpdateListener daemonStateUpdatedListener =
 			new DaemonSingleton.StateUpdateListener() {
-
+		
 		@Override
 		public void daemonStateUpdate() {
 			runOnUiThread(new Runnable(){
@@ -53,11 +60,14 @@ public class I2PD extends Activity {
 			});
 		}
 	};
-
+	
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
+		//install certs every time
+		Decompress.unzipFromAssets(this, "certificates.zip", this.getDir("data", Context.MODE_PRIVATE).toString() + "/" );
+
         textView = new TextView(this);
         setContentView(textView);
         DaemonSingleton.getInstance().addStateChangeListener(daemonStateUpdatedListener);
@@ -123,7 +133,7 @@ public class I2PD extends Activity {
         }
     };
 
-
+	
     private boolean mIsBound;
 
     private void doBindService() {
@@ -147,7 +157,7 @@ public class I2PD extends Activity {
 	@Override
 	public boolean onCreateOptionsMenu(Menu menu) {
 		// Inflate the menu; this adds items to the action bar if it is present.
-		getMenuInflater().inflate(R.menu.options_main, menu);
+		getMenuInflater().inflate(R.menu.options_main, menu); 
 		return true;
 	}
 
@@ -216,9 +226,9 @@ public class I2PD extends Activity {
 
 			    			@Override
 			    			public void run() {
-			    				quit();
+			    				quit();	
 			    			}
-
+			            	
 			            }, 10*60*1000/*milliseconds*/);
 			        }else{
 			        	quit();
@@ -227,7 +237,7 @@ public class I2PD extends Activity {
 					Log.e(TAG,"",tr);
 				}
 			}
-
+        	
         },"gracQuitInit").start();
     }
 
diff --git a/android/src/org/purplei2p/i2pd/I2PD_JNI.java b/android/src/org/purplei2p/i2pd/I2PD_JNI.java
index f965d471..bfdf8967 100644
--- a/android/src/org/purplei2p/i2pd/I2PD_JNI.java
+++ b/android/src/org/purplei2p/i2pd/I2PD_JNI.java
@@ -6,12 +6,12 @@ public class I2PD_JNI {
 	 * returns error info if failed
 	 * returns "ok" if daemon initialized and started okay
 	 */
-    public static native String startDaemon();
+    public static native String startDaemon(String args[]);
     //should only be called after startDaemon() success
     public static native void stopDaemon();
-
+    
     public static native void stopAcceptingTunnels();
-
+    
 	public static native void onNetworkStateChanged(boolean isConnected);
 
 	public static void loadLibraries() {