diff --git a/qt/i2pd_qt/android/AndroidManifest.xml b/qt/i2pd_qt/android/AndroidManifest.xml index 73f6eb6d..cf426bf2 100644 --- a/qt/i2pd_qt/android/AndroidManifest.xml +++ b/qt/i2pd_qt/android/AndroidManifest.xml @@ -1,7 +1,22 @@ - - - + + + + + + + @@ -45,9 +60,8 @@ + - - diff --git a/qt/i2pd_qt/android/build.gradle b/qt/i2pd_qt/android/build.gradle new file mode 100644 index 00000000..ef416b0b --- /dev/null +++ b/qt/i2pd_qt/android/build.gradle @@ -0,0 +1,57 @@ +buildscript { + repositories { + jcenter() + } + + dependencies { + classpath 'com.android.tools.build:gradle:1.1.0' + } +} + +allprojects { + repositories { + jcenter() + } +} + +apply plugin: 'com.android.application' + +dependencies { + compile fileTree(dir: 'libs', include: ['*.jar']) +} + +android { + /******************************************************* + * The following variables: + * - androidBuildToolsVersion, + * - androidCompileSdkVersion + * - qt5AndroidDir - holds the path to qt android files + * needed to build any Qt application + * on Android. + * + * are defined in gradle.properties file. This file is + * updated by QtCreator and androiddeployqt tools. + * Changing them manually might break the compilation! + *******************************************************/ + + compileSdkVersion androidCompileSdkVersion.toInteger() + + buildToolsVersion androidBuildToolsVersion + + sourceSets { + main { + manifest.srcFile 'AndroidManifest.xml' + java.srcDirs = [qt5AndroidDir + '/src', 'src', 'java'] + aidl.srcDirs = [qt5AndroidDir + '/src', 'src', 'aidl'] + res.srcDirs = [qt5AndroidDir + '/res', 'res'] + resources.srcDirs = ['src'] + renderscript.srcDirs = ['src'] + assets.srcDirs = ['assets'] + jniLibs.srcDirs = ['libs'] + } + } + + lintOptions { + abortOnError false + } +} diff --git a/qt/i2pd_qt/android/libs/android-support-v4.jar b/qt/i2pd_qt/android/libs/android-support-v4.jar new file mode 100644 index 00000000..2ff47f4f Binary files /dev/null and b/qt/i2pd_qt/android/libs/android-support-v4.jar differ diff --git a/qt/i2pd_qt/android/project.properties b/qt/i2pd_qt/android/project.properties index c6998b3d..4d07452b 100644 --- a/qt/i2pd_qt/android/project.properties +++ b/qt/i2pd_qt/android/project.properties @@ -11,4 +11,4 @@ #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt # Project target. -target=android-9 +target=android-11 diff --git a/qt/i2pd_qt/android/res/drawable/itoopie.png b/qt/i2pd_qt/android/res/drawable/itoopie.png new file mode 100644 index 00000000..a5dc7b68 Binary files /dev/null and b/qt/i2pd_qt/android/res/drawable/itoopie.png differ diff --git a/qt/i2pd_qt/android/res/values/strings.xml b/qt/i2pd_qt/android/res/values/strings.xml index fcc3eb09..713c7aa0 100644 --- a/qt/i2pd_qt/android/res/values/strings.xml +++ b/qt/i2pd_qt/android/res/values/strings.xml @@ -4,4 +4,7 @@ Can\'t find Ministro service.\nThe application can\'t start. This application requires Ministro service. Would you like to install it? Your application encountered a fatal error and cannot continue. + i2pd started + i2pd stopped + i2pd diff --git a/qt/i2pd_qt/android/src/org/purplei2p/i2pd/I2PDMainActivity.java b/qt/i2pd_qt/android/src/org/purplei2p/i2pd/I2PDMainActivity.java new file mode 100644 index 00000000..23b32312 --- /dev/null +++ b/qt/i2pd_qt/android/src/org/purplei2p/i2pd/I2PDMainActivity.java @@ -0,0 +1,97 @@ +package org.purplei2p.i2pd; + +import org.qtproject.qt5.android.bindings.QtActivity; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.Bundle; +import android.os.IBinder; + +public class I2PDMainActivity extends QtActivity +{ + + private static I2PDMainActivity instance; + + public I2PDMainActivity() {} + + /* (non-Javadoc) + * @see org.qtproject.qt5.android.bindings.QtActivity#onCreate(android.os.Bundle) + */ + @Override + public void onCreate(Bundle savedInstanceState) { + I2PDMainActivity.setInstance(this); + super.onCreate(savedInstanceState); + + //set the app be foreground (do not unload when RAM needed) + doBindService(); + } + + /* (non-Javadoc) + * @see org.qtproject.qt5.android.bindings.QtActivity#onDestroy() + */ + @Override + protected void onDestroy() { + I2PDMainActivity.setInstance(null); + doUnbindService(); + super.onDestroy(); + } + + public static I2PDMainActivity getInstance() { + return instance; + } + + private static void setInstance(I2PDMainActivity instance) { + I2PDMainActivity.instance = instance; + } + + + +// private LocalService mBoundService; + + private ServiceConnection mConnection = new ServiceConnection() { + public void onServiceConnected(ComponentName className, IBinder service) { + // This is called when the connection with the service has been + // established, giving us the service object we can use to + // interact with the service. Because we have bound to a explicit + // service that we know is running in our own process, we can + // cast its IBinder to a concrete class and directly access it. +// mBoundService = ((LocalService.LocalBinder)service).getService(); + + // Tell the user about this for our demo. +// Toast.makeText(Binding.this, R.string.local_service_connected, +// Toast.LENGTH_SHORT).show(); + } + + public void onServiceDisconnected(ComponentName className) { + // This is called when the connection with the service has been + // unexpectedly disconnected -- that is, its process crashed. + // Because it is running in our same process, we should never + // see this happen. +// mBoundService = null; +// Toast.makeText(Binding.this, R.string.local_service_disconnected, +// Toast.LENGTH_SHORT).show(); + } + }; + + private boolean mIsBound; + + private void doBindService() { + // Establish a connection with the service. We use an explicit + // class name because we want a specific service implementation that + // we know will be running in our own process (and thus won't be + // supporting component replacement by other applications). + bindService(new Intent(this, + LocalService.class), mConnection, Context.BIND_AUTO_CREATE); + mIsBound = true; + } + + void doUnbindService() { + if (mIsBound) { + // Detach our existing connection. + unbindService(mConnection); + mIsBound = false; + } + } +} diff --git a/qt/i2pd_qt/android/src/org/purplei2p/i2pd/LocalService.java b/qt/i2pd_qt/android/src/org/purplei2p/i2pd/LocalService.java new file mode 100644 index 00000000..0cbdb7d2 --- /dev/null +++ b/qt/i2pd_qt/android/src/org/purplei2p/i2pd/LocalService.java @@ -0,0 +1,92 @@ +package org.purplei2p.i2pd; + +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.app.Service; +import android.content.Intent; +import android.os.Binder; +import android.os.IBinder; +import android.support.v4.app.NotificationCompat; +import android.util.Log; +import android.widget.Toast; + +public class LocalService extends Service { +// private NotificationManager mNM; + + // Unique Identification Number for the Notification. + // We use it on Notification start, and to cancel it. + private int NOTIFICATION = R.string.local_service_started; + + /** + * Class for clients to access. Because we know this service always + * runs in the same process as its clients, we don't need to deal with + * IPC. + */ + public class LocalBinder extends Binder { + LocalService getService() { + return LocalService.this; + } + } + + @Override + public void onCreate() { +// mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); + + // Display a notification about us starting. We put an icon in the status bar. + showNotification(); + + + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + Log.i("LocalService", "Received start id " + startId + ": " + intent); + return START_NOT_STICKY; + } + + @Override + public void onDestroy() { + // Cancel the persistent notification. + //mNM.cancel(NOTIFICATION); + stopForeground(true); + + // Tell the user we stopped. + Toast.makeText(this, R.string.local_service_stopped, Toast.LENGTH_SHORT).show(); + } + + @Override + public IBinder onBind(Intent intent) { + return mBinder; + } + + // This is the object that receives interactions from clients. See + // RemoteService for a more complete example. + private final IBinder mBinder = new LocalBinder(); + + /** + * Show a notification while this service is running. + */ + private void showNotification() { + // In this sample, we'll use the same text for the ticker and the expanded notification + CharSequence text = getText(R.string.local_service_started); + + // The PendingIntent to launch our activity if the user selects this notification + PendingIntent contentIntent = PendingIntent.getActivity(this, 0, + new Intent(this, I2PDMainActivity.class), 0); + + // Set the info for the views that show in the notification panel. + Notification notification = new NotificationCompat.Builder(this) + .setSmallIcon(R.drawable.itoopie) // the status icon + .setTicker(text) // the status text + .setWhen(System.currentTimeMillis()) // the time stamp + .setContentTitle(getText(R.string.local_service_label)) // the label of the entry + .setContentText(text) // the contents of the entry + .setContentIntent(contentIntent) // The intent to send when the entry is clicked + .build(); + + // Send the notification. + //mNM.notify(NOTIFICATION, notification); + startForeground(NOTIFICATION, notification); + } +} \ No newline at end of file diff --git a/qt/i2pd_qt/android/src/org/qtproject/qt5/android/bindings/QtActivity.java b/qt/i2pd_qt/android/src/org/qtproject/qt5/android/bindings/QtActivity.java index f370b4f6..677e8f46 100644 --- a/qt/i2pd_qt/android/src/org/qtproject/qt5/android/bindings/QtActivity.java +++ b/qt/i2pd_qt/android/src/org/qtproject/qt5/android/bindings/QtActivity.java @@ -62,7 +62,6 @@ import android.content.Intent; import android.content.ServiceConnection; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageInfo; import android.content.res.Configuration; import android.content.res.Resources.Theme; @@ -1589,34 +1588,34 @@ public class QtActivity extends Activity //@ANDROID-11 //////////////// Activity API 12 ///////////// -//@ANDROID-12 - @Override - public boolean dispatchGenericMotionEvent(MotionEvent ev) - { - if (QtApplication.m_delegateObject != null && QtApplication.dispatchGenericMotionEvent != null) - return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.dispatchGenericMotionEvent, ev); - else - return super.dispatchGenericMotionEvent(ev); - } - public boolean super_dispatchGenericMotionEvent(MotionEvent event) - { - return super.dispatchGenericMotionEvent(event); - } - //--------------------------------------------------------------------------- - - @Override - public boolean onGenericMotionEvent(MotionEvent event) - { - if (QtApplication.m_delegateObject != null && QtApplication.onGenericMotionEvent != null) - return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.onGenericMotionEvent, event); - else - return super.onGenericMotionEvent(event); - } - public boolean super_onGenericMotionEvent(MotionEvent event) - { - return super.onGenericMotionEvent(event); - } - //--------------------------------------------------------------------------- -//@ANDROID-12 +////@ANDROID-12 +// @Override +// public boolean dispatchGenericMotionEvent(MotionEvent ev) +// { +// if (QtApplication.m_delegateObject != null && QtApplication.dispatchGenericMotionEvent != null) +// return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.dispatchGenericMotionEvent, ev); +// else +// return super.dispatchGenericMotionEvent(ev); +// } +// public boolean super_dispatchGenericMotionEvent(MotionEvent event) +// { +// return super.dispatchGenericMotionEvent(event); +// } +// //--------------------------------------------------------------------------- +// +// @Override +// public boolean onGenericMotionEvent(MotionEvent event) +// { +// if (QtApplication.m_delegateObject != null && QtApplication.onGenericMotionEvent != null) +// return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.onGenericMotionEvent, event); +// else +// return super.onGenericMotionEvent(event); +// } +// public boolean super_onGenericMotionEvent(MotionEvent event) +// { +// return super.onGenericMotionEvent(event); +// } +// //--------------------------------------------------------------------------- +////@ANDROID-12 } diff --git a/qt/i2pd_qt/i2pd_qt.pro b/qt/i2pd_qt/i2pd_qt.pro index 6f02385a..7cf27b1d 100644 --- a/qt/i2pd_qt/i2pd_qt.pro +++ b/qt/i2pd_qt/i2pd_qt.pro @@ -20,6 +20,11 @@ BOOST_PATH = /mnt/media/android/Boost-for-Android-Prebuilt OPENSSL_PATH = /mnt/media/android/OpenSSL-for-Android-Prebuilt IFADDRS_PATH = /mnt/media/android/android-ifaddrs +# Steps in Android SDK manager: +# 1) Check Extras/Google Support Library https://developer.android.com/topic/libraries/support-library/setup.html +# 2) Check API 11 +# Finally, click Install. + SOURCES += DaemonQT.cpp\ mainwindow.cpp \ ../../HTTPServer.cpp ../../I2PControl.cpp ../../UPnP.cpp ../../Daemon.cpp ../../Config.cpp \