mirror of
https://github.com/PurpleI2P/i2pd
synced 2024-11-10 08:00:38 +03:00
android ported all + isConnected notif
This commit is contained in:
parent
5967ab75b1
commit
4d3a01a5fe
@ -3,14 +3,23 @@
|
|||||||
package="org.purplei2p.i2pd"
|
package="org.purplei2p.i2pd"
|
||||||
android:versionCode="1"
|
android:versionCode="1"
|
||||||
android:versionName="1.0">
|
android:versionName="1.0">
|
||||||
<uses-sdk android:minSdkVersion="9" />
|
<uses-sdk android:minSdkVersion="9" android:targetSdkVersion="24"/>
|
||||||
<application android:label="@string/app_name" android:allowBackup="true" android:icon="@drawable/icon">
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||||
<activity android:name=".I2PD"
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||||
|
<application android:label="@string/app_name" android:allowBackup="true" android:icon="@drawable/icon">
|
||||||
|
<receiver android:name=".NetworkStateChangeReceiver">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
|
<activity android:name=".I2PD"
|
||||||
android:label="@string/app_name">
|
android:label="@string/app_name">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
<service android:enabled="true" android:name=".ForegroundService"/>
|
||||||
</application>
|
</application>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
@ -12,7 +12,6 @@ LOCAL_STATIC_LIBRARIES := \
|
|||||||
miniupnpc
|
miniupnpc
|
||||||
LOCAL_LDLIBS := -lz
|
LOCAL_LDLIBS := -lz
|
||||||
|
|
||||||
#LOCAL_CFLAGS :=
|
|
||||||
LOCAL_SRC_FILES := DaemonAndroid.cpp i2pd_android.cpp \
|
LOCAL_SRC_FILES := DaemonAndroid.cpp i2pd_android.cpp \
|
||||||
$(IFADDRS_PATH)/ifaddrs.c \
|
$(IFADDRS_PATH)/ifaddrs.c \
|
||||||
../../HTTPServer.cpp ../../I2PControl.cpp ../../Daemon.cpp ../../Config.cpp \
|
../../HTTPServer.cpp ../../I2PControl.cpp ../../Daemon.cpp ../../Config.cpp \
|
||||||
@ -58,9 +57,8 @@ LOCAL_SRC_FILES := DaemonAndroid.cpp i2pd_android.cpp \
|
|||||||
../../TunnelEndpoint.cpp \
|
../../TunnelEndpoint.cpp \
|
||||||
../../TunnelGateway.cpp \
|
../../TunnelGateway.cpp \
|
||||||
../../TunnelPool.cpp \
|
../../TunnelPool.cpp \
|
||||||
../../UPnP.cpp \
|
|
||||||
../../util.cpp \
|
../../util.cpp \
|
||||||
../../i2pd.cpp
|
../../i2pd.cpp ../../UPnP.cpp
|
||||||
|
|
||||||
include $(BUILD_SHARED_LIBRARY)
|
include $(BUILD_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#APP_ABI := all
|
#APP_ABI := all
|
||||||
APP_ABI := armeabi-v7a x86
|
#APP_ABI := armeabi-v7a x86
|
||||||
|
#APP_ABI := x86
|
||||||
|
APP_ABI := armeabi-v7a
|
||||||
#can be android-3 but will fail for x86 since arch-x86 is not present at ndkroot/platforms/android-3/ . libz is taken from there.
|
#can be android-3 but will fail for x86 since arch-x86 is not present at ndkroot/platforms/android-3/ . libz is taken from there.
|
||||||
APP_PLATFORM := android-9
|
APP_PLATFORM := android-9
|
||||||
|
|
||||||
@ -11,7 +13,7 @@ APP_STL := gnustl_shared
|
|||||||
# Enable c++11 extentions in source code
|
# Enable c++11 extentions in source code
|
||||||
APP_CPPFLAGS += -std=c++11
|
APP_CPPFLAGS += -std=c++11
|
||||||
|
|
||||||
APP_CPPFLAGS += -DUSE_UPNP -DANDROID -D__ANDROID__
|
APP_CPPFLAGS += -DANDROID -D__ANDROID__ -DUSE_UPNP
|
||||||
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
|
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
|
||||||
APP_CPPFLAGS += -DANDROID_ARM7A
|
APP_CPPFLAGS += -DANDROID_ARM7A
|
||||||
endif
|
endif
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
#include "DaemonAndroid.h"
|
#include "DaemonAndroid.h"
|
||||||
#include "../../Daemon.h"
|
#include "../../Daemon.h"
|
||||||
|
#include <iostream>
|
||||||
|
#include <boost/exception/diagnostic_information.hpp>
|
||||||
|
#include <boost/exception_ptr.hpp>
|
||||||
|
#include <exception>
|
||||||
//#include "mainwindow.h"
|
//#include "mainwindow.h"
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
@ -58,10 +62,11 @@ namespace android
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
DaemonAndroidImpl::DaemonAndroidImpl ():
|
DaemonAndroidImpl::DaemonAndroidImpl ()
|
||||||
|
//:
|
||||||
/*mutex(nullptr), */
|
/*mutex(nullptr), */
|
||||||
m_IsRunning(false),
|
//m_IsRunning(false),
|
||||||
m_RunningChangedCallback(nullptr)
|
//m_RunningChangedCallback(nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,15 +78,15 @@ namespace android
|
|||||||
bool DaemonAndroidImpl::init(int argc, char* argv[])
|
bool DaemonAndroidImpl::init(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
//mutex=new QMutex(QMutex::Recursive);
|
//mutex=new QMutex(QMutex::Recursive);
|
||||||
setRunningCallback(0);
|
//setRunningCallback(0);
|
||||||
m_IsRunning=false;
|
//m_IsRunning=false;
|
||||||
return Daemon.init(argc,argv);
|
return Daemon.init(argc,argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DaemonAndroidImpl::start()
|
void DaemonAndroidImpl::start()
|
||||||
{
|
{
|
||||||
//QMutexLocker locker(mutex);
|
//QMutexLocker locker(mutex);
|
||||||
setRunning(true);
|
//setRunning(true);
|
||||||
Daemon.start();
|
Daemon.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,7 +94,7 @@ namespace android
|
|||||||
{
|
{
|
||||||
//QMutexLocker locker(mutex);
|
//QMutexLocker locker(mutex);
|
||||||
Daemon.stop();
|
Daemon.stop();
|
||||||
setRunning(false);
|
//setRunning(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DaemonAndroidImpl::restart()
|
void DaemonAndroidImpl::restart()
|
||||||
@ -98,7 +103,7 @@ namespace android
|
|||||||
stop();
|
stop();
|
||||||
start();
|
start();
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
void DaemonAndroidImpl::setRunningCallback(runningChangedCallback cb)
|
void DaemonAndroidImpl::setRunningCallback(runningChangedCallback cb)
|
||||||
{
|
{
|
||||||
m_RunningChangedCallback = cb;
|
m_RunningChangedCallback = cb;
|
||||||
@ -119,46 +124,65 @@ namespace android
|
|||||||
m_RunningChangedCallback();
|
m_RunningChangedCallback();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
static DaemonAndroidImpl daemon;
|
static DaemonAndroidImpl daemon;
|
||||||
|
static char* argv[1]={strdup("tmp")};
|
||||||
/**
|
/**
|
||||||
* returns 1 if daemon init failed
|
* returns error details if failed
|
||||||
* returns 0 if daemon initialized and started okay
|
* returns "ok" if daemon initialized and started okay
|
||||||
*/
|
*/
|
||||||
int start(/*int argc, char* argv[]*/)
|
std::string start(/*int argc, char* argv[]*/)
|
||||||
{
|
{
|
||||||
int result;
|
try
|
||||||
|
|
||||||
{
|
{
|
||||||
//Log.d(TAG"Initialising the daemon...");
|
//int result;
|
||||||
bool daemonInitSuccess = daemon.init(0,0/*argc, argv*/);
|
|
||||||
if(!daemonInitSuccess)
|
|
||||||
{
|
|
||||||
//QMessageBox::critical(0, "Error", "Daemon init failed");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
//Log.d(TAG"Initialised, creating the main window...");
|
|
||||||
//MainWindow w;
|
|
||||||
//Log.d(TAG"Before main window.show()...");
|
|
||||||
//w.show ();
|
|
||||||
|
|
||||||
{
|
{
|
||||||
//i2p::qt::Controller daemonQtController(daemon);
|
//Log.d(TAG"Initialising the daemon...");
|
||||||
//Log.d(TAG"Starting the daemon...");
|
bool daemonInitSuccess = daemon.init(1,argv);
|
||||||
//emit daemonQtController.startDaemon();
|
if(!daemonInitSuccess)
|
||||||
//daemon.start ();
|
{
|
||||||
//Log.d(TAG"Starting GUI event loop...");
|
//QMessageBox::critical(0, "Error", "Daemon init failed");
|
||||||
//result = app.exec();
|
return "Daemon init failed";
|
||||||
//daemon.stop ();
|
}
|
||||||
daemon.start();
|
//Log.d(TAG"Initialised, creating the main window...");
|
||||||
return 0;
|
//MainWindow w;
|
||||||
|
//Log.d(TAG"Before main window.show()...");
|
||||||
|
//w.show ();
|
||||||
|
|
||||||
|
{
|
||||||
|
//i2p::qt::Controller daemonQtController(daemon);
|
||||||
|
//Log.d(TAG"Starting the daemon...");
|
||||||
|
//emit daemonQtController.startDaemon();
|
||||||
|
//daemon.start ();
|
||||||
|
//Log.d(TAG"Starting GUI event loop...");
|
||||||
|
//result = app.exec();
|
||||||
|
//daemon.stop ();
|
||||||
|
daemon.start();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//QMessageBox::information(&w, "Debug", "demon stopped");
|
||||||
|
//Log.d(TAG"Exiting the application");
|
||||||
|
//return result;
|
||||||
}
|
}
|
||||||
|
catch (boost::exception& ex)
|
||||||
//QMessageBox::information(&w, "Debug", "demon stopped");
|
{
|
||||||
//Log.d(TAG"Exiting the application");
|
std::stringstream ss;
|
||||||
//return result;
|
ss << boost::diagnostic_information(ex);
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
catch (std::exception& ex)
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << ex.what();
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
return "unknown exception";
|
||||||
|
}
|
||||||
|
return "ok";
|
||||||
}
|
}
|
||||||
|
|
||||||
void stop()
|
void stop()
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
#ifndef DAEMON_ANDROID_H
|
#ifndef DAEMON_ANDROID_H
|
||||||
#define DAEMON_ANDROID_H
|
#define DAEMON_ANDROID_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
namespace android
|
namespace android
|
||||||
{
|
{
|
||||||
//FIXME currently NOT threadsafe
|
|
||||||
class DaemonAndroidImpl
|
class DaemonAndroidImpl
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -13,7 +14,7 @@ namespace android
|
|||||||
DaemonAndroidImpl ();
|
DaemonAndroidImpl ();
|
||||||
~DaemonAndroidImpl ();
|
~DaemonAndroidImpl ();
|
||||||
|
|
||||||
typedef void (*runningChangedCallback)();
|
//typedef void (*runningChangedCallback)();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return success
|
* @return success
|
||||||
@ -22,21 +23,21 @@ namespace android
|
|||||||
void start();
|
void start();
|
||||||
void stop();
|
void stop();
|
||||||
void restart();
|
void restart();
|
||||||
void setRunningCallback(runningChangedCallback cb);
|
//void setRunningCallback(runningChangedCallback cb);
|
||||||
bool isRunning();
|
//bool isRunning();
|
||||||
private:
|
private:
|
||||||
void setRunning(bool running);
|
//void setRunning(bool running);
|
||||||
private:
|
private:
|
||||||
//QMutex* mutex;
|
//QMutex* mutex;
|
||||||
bool m_IsRunning;
|
//bool m_IsRunning;
|
||||||
runningChangedCallback m_RunningChangedCallback;
|
//runningChangedCallback m_RunningChangedCallback;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns 1 if daemon init failed
|
* returns "ok" if daemon init failed
|
||||||
* returns 0 if daemon initialized and started okay
|
* returns errinfo if daemon initialized and started okay
|
||||||
*/
|
*/
|
||||||
int start();
|
std::string start();
|
||||||
|
|
||||||
// stops the daemon
|
// stops the daemon
|
||||||
void stop();
|
void stop();
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
#include "org_purplei2p_i2pd_I2PD_JNI.h"
|
#include "org_purplei2p_i2pd_I2PD_JNI.h"
|
||||||
#include "DaemonAndroid.h"
|
#include "DaemonAndroid.h"
|
||||||
|
#include "../../RouterContext.h"
|
||||||
|
|
||||||
JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getABICompiledWith
|
JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getABICompiledWith
|
||||||
(JNIEnv * env, jclass clazz) {
|
(JNIEnv * env, jclass clazz) {
|
||||||
@ -41,9 +42,9 @@ JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getABICompiledWith
|
|||||||
return env->NewStringUTF(ABI);
|
return env->NewStringUTF(ABI);
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jint JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startDaemon
|
JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startDaemon
|
||||||
(JNIEnv * env, jclass clazz) {
|
(JNIEnv * env, jclass clazz) {
|
||||||
return (jint)i2p::android::start();
|
return env->NewStringUTF(i2p::android::start().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopDaemon
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopDaemon
|
||||||
@ -51,3 +52,12 @@ JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopDaemon
|
|||||||
i2p::android::stop();
|
i2p::android::stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopAcceptingTunnels
|
||||||
|
(JNIEnv * env, jclass clazz) {
|
||||||
|
i2p::context.SetAcceptsTunnels (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_onNetworkStateChanged
|
||||||
|
(JNIEnv * env, jclass clazz, jboolean isConnected) {
|
||||||
|
bool isConnectedBool = (bool) isConnected;
|
||||||
|
}
|
||||||
|
@ -15,6 +15,18 @@ extern "C" {
|
|||||||
JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getABICompiledWith
|
JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getABICompiledWith
|
||||||
(JNIEnv *, jclass);
|
(JNIEnv *, jclass);
|
||||||
|
|
||||||
|
JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startDaemon
|
||||||
|
(JNIEnv *, jclass);
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopDaemon
|
||||||
|
(JNIEnv *, jclass);
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopAcceptingTunnels
|
||||||
|
(JNIEnv *, jclass);
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_onNetworkStateChanged
|
||||||
|
(JNIEnv * env, jclass clazz, jboolean isConnected);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -11,4 +11,4 @@
|
|||||||
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
||||||
|
|
||||||
# Project target.
|
# Project target.
|
||||||
target=android-9
|
target=android-24
|
||||||
|
16
android/res/menu/options_main.xml
Normal file
16
android/res/menu/options_main.xml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<menu
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
tools:context=".I2PD">
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_graceful_quit"
|
||||||
|
android:title="@string/action_graceful_quit"
|
||||||
|
android:orderInCategory="98"
|
||||||
|
/>
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_quit"
|
||||||
|
android:title="@string/action_quit"
|
||||||
|
android:orderInCategory="99"
|
||||||
|
/>
|
||||||
|
</menu>
|
@ -1,4 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">i2pd</string>
|
<string name="app_name">i2pd</string>
|
||||||
|
<string name="i2pd_started">i2pd started</string>
|
||||||
|
<string name="action_quit">Quit</string>
|
||||||
|
<string name="action_graceful_quit">Graceful Quit</string>
|
||||||
|
<string name="graceful_quit_is_already_in_progress">Graceful quit is already in progress</string>
|
||||||
|
<string name="graceful_quit_is_in_progress">Graceful quit is in progress</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
88
android/src/org/purplei2p/i2pd/ForegroundService.java
Normal file
88
android/src/org/purplei2p/i2pd/ForegroundService.java
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
package org.purplei2p.i2pd;
|
||||||
|
|
||||||
|
import android.app.Notification;
|
||||||
|
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;
|
||||||
|
|
||||||
|
public class ForegroundService 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.i2pd_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 {
|
||||||
|
ForegroundService getService() {
|
||||||
|
return ForegroundService.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("ForegroundService", "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.i2pd_started);
|
||||||
|
|
||||||
|
// The PendingIntent to launch our activity if the user selects this notification
|
||||||
|
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
|
||||||
|
new Intent(this, I2PD.class), 0);
|
||||||
|
|
||||||
|
// Set the info for the views that show in the notification panel.
|
||||||
|
Notification notification = new NotificationCompat.Builder(this)
|
||||||
|
.setSmallIcon(R.drawable.itoopie_notification_icon) // the status icon
|
||||||
|
.setTicker(text) // the status text
|
||||||
|
.setWhen(System.currentTimeMillis()) // the time stamp
|
||||||
|
.setContentTitle(getText(R.string.app_name)) // 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);
|
||||||
|
}
|
||||||
|
}
|
@ -1,20 +1,272 @@
|
|||||||
package org.purplei2p.i2pd;
|
package org.purplei2p.i2pd;
|
||||||
|
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.util.Timer;
|
||||||
|
import java.util.TimerTask;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.widget.TextView;
|
import android.content.ComponentName;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.ServiceConnection;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
public class I2PD extends Activity {
|
public class I2PD extends Activity {
|
||||||
|
private static final String TAG = "i2pd";
|
||||||
|
|
||||||
|
private static Throwable loadLibsThrowable;
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
I2PD_JNI.loadLibraries();
|
||||||
|
} catch (Throwable tr) {
|
||||||
|
loadLibsThrowable = tr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private String daemonStartResult="N/A";
|
||||||
|
private boolean destroyed=false;
|
||||||
|
private TextView textView;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
destroyed=false;
|
||||||
|
|
||||||
TextView tv = new TextView(this);
|
//set the app be foreground (do not unload when RAM needed)
|
||||||
tv.setText( "libi2pd.so was compiled with ABI " + getABICompiledWith());
|
doBindService();
|
||||||
setContentView(tv);
|
|
||||||
|
textView = new TextView(this);
|
||||||
|
setContentView(textView);
|
||||||
|
if (loadLibsThrowable != null) {
|
||||||
|
textView.setText(throwableToString(loadLibsThrowable)+"\r\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
textView.setText(
|
||||||
|
"libi2pd.so was compiled with ABI " + getABICompiledWith() + "\r\n"+
|
||||||
|
"Starting daemon... ");
|
||||||
|
new Thread(new Runnable(){
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
doStartDaemon();
|
||||||
|
} catch (final Throwable tr) {
|
||||||
|
appendThrowable(tr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
},"i2pdDaemonStarting").start();
|
||||||
|
} catch (Throwable tr) {
|
||||||
|
textView.setText(textView.getText().toString()+throwableToString(tr));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getABICompiledWith() {
|
@Override
|
||||||
|
protected void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
localDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized void localDestroy() {
|
||||||
|
if(destroyed)return;
|
||||||
|
destroyed=true;
|
||||||
|
if(gracefulQuitTimer!=null) {
|
||||||
|
gracefulQuitTimer.cancel();
|
||||||
|
gracefulQuitTimer = null;
|
||||||
|
}
|
||||||
|
try{
|
||||||
|
doUnbindService();
|
||||||
|
}catch(Throwable tr){
|
||||||
|
Log.e(TAG, "", tr);
|
||||||
|
}
|
||||||
|
if("ok".equals(daemonStartResult)) {
|
||||||
|
try {
|
||||||
|
I2PD_JNI.stopDaemon();
|
||||||
|
} catch (Throwable tr) {
|
||||||
|
Log.e(TAG, "error", tr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private CharSequence throwableToString(Throwable tr) {
|
||||||
|
StringWriter sw = new StringWriter(8192);
|
||||||
|
PrintWriter pw = new PrintWriter(sw);
|
||||||
|
tr.printStackTrace(pw);
|
||||||
|
pw.close();
|
||||||
|
return sw.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getABICompiledWith() {
|
||||||
return I2PD_JNI.getABICompiledWith();
|
return I2PD_JNI.getABICompiledWith();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private synchronized void doStartDaemon() {
|
||||||
|
if(destroyed)return;
|
||||||
|
daemonStartResult = I2PD_JNI.startDaemon();
|
||||||
|
runOnUiThread(new Runnable(){
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
synchronized (I2PD.this) {
|
||||||
|
if(destroyed)return;
|
||||||
|
textView.setText(
|
||||||
|
textView.getText().toString()+
|
||||||
|
"start result: "+daemonStartResult+"\r\n"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void appendThrowable(final Throwable tr) {
|
||||||
|
runOnUiThread(new Runnable(){
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
synchronized (I2PD.this) {
|
||||||
|
if(destroyed)return;
|
||||||
|
textView.setText(textView.getText().toString()+throwableToString(tr)+"\r\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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,
|
||||||
|
ForegroundService.class), mConnection, Context.BIND_AUTO_CREATE);
|
||||||
|
mIsBound = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doUnbindService() {
|
||||||
|
if (mIsBound) {
|
||||||
|
// Detach our existing connection.
|
||||||
|
unbindService(mConnection);
|
||||||
|
mIsBound = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@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);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
// Handle action bar item clicks here. The action bar will
|
||||||
|
// automatically handle clicks on the Home/Up button, so long
|
||||||
|
// as you specify a parent activity in AndroidManifest.xml.
|
||||||
|
int id = item.getItemId();
|
||||||
|
|
||||||
|
switch(id){
|
||||||
|
case R.id.action_quit:
|
||||||
|
quit();
|
||||||
|
return true;
|
||||||
|
case R.id.action_graceful_quit:
|
||||||
|
gracefulQuit();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("NewApi")
|
||||||
|
private void quit() {
|
||||||
|
try {
|
||||||
|
localDestroy();
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
|
finishAndRemoveTask();
|
||||||
|
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
||||||
|
finishAffinity();
|
||||||
|
} else {
|
||||||
|
//moveTaskToBack(true);
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
}catch (Throwable tr) {
|
||||||
|
Log.e(TAG, "", tr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Timer gracefulQuitTimer;
|
||||||
|
private synchronized void gracefulQuit() {
|
||||||
|
if(gracefulQuitTimer!=null){
|
||||||
|
Toast.makeText(this, R.string.graceful_quit_is_already_in_progress,
|
||||||
|
Toast.LENGTH_SHORT).show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Toast.makeText(this, R.string.graceful_quit_is_in_progress,
|
||||||
|
Toast.LENGTH_SHORT).show();
|
||||||
|
new Thread(new Runnable(){
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try{
|
||||||
|
synchronized (I2PD.this) {
|
||||||
|
if("ok".equals(daemonStartResult)) {
|
||||||
|
I2PD_JNI.stopAcceptingTunnels();
|
||||||
|
gracefulQuitTimer = new Timer(true);
|
||||||
|
gracefulQuitTimer.schedule(new TimerTask(){
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
quit();
|
||||||
|
}
|
||||||
|
|
||||||
|
}, 10*60*1000/*millis*/);
|
||||||
|
}else{
|
||||||
|
quit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch(Throwable tr) {
|
||||||
|
Log.e(TAG,"",tr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
},"gracQuitInit").start();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,14 +3,19 @@ package org.purplei2p.i2pd;
|
|||||||
public class I2PD_JNI {
|
public class I2PD_JNI {
|
||||||
public static native String getABICompiledWith();
|
public static native String getABICompiledWith();
|
||||||
/**
|
/**
|
||||||
* returns 1 if daemon init failed
|
* returns error info if failed
|
||||||
* returns 0 if daemon initialized and started okay
|
* returns "ok" if daemon initialized and started okay
|
||||||
*/
|
*/
|
||||||
public static native int startDaemon();
|
public static native String startDaemon();
|
||||||
//should only be called after startDaemon() success
|
//should only be called after startDaemon() success
|
||||||
public static native void stopDaemon();
|
public static native void stopDaemon();
|
||||||
|
|
||||||
|
public static native void stopAcceptingTunnels();
|
||||||
|
|
||||||
|
public static native void onNetworkStateChanged(boolean isConnected);
|
||||||
|
|
||||||
static {
|
public static void loadLibraries() {
|
||||||
|
//System.loadLibrary("gnustl_shared");
|
||||||
System.loadLibrary("i2pd");
|
System.loadLibrary("i2pd");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,30 @@
|
|||||||
|
package org.purplei2p.i2pd;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.net.ConnectivityManager;
|
||||||
|
import android.net.NetworkInfo;
|
||||||
|
|
||||||
|
public class NetworkStateChangeReceiver extends BroadcastReceiver {
|
||||||
|
|
||||||
|
private static final String TAG = "i2pd";
|
||||||
|
|
||||||
|
//api level 1
|
||||||
|
@Override
|
||||||
|
public void onReceive(final Context context, final Intent intent) {
|
||||||
|
Log.d(TAG,"Network state change");
|
||||||
|
try {
|
||||||
|
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||||
|
NetworkInfo activeNetworkInfo = cm.getActiveNetworkInfo();
|
||||||
|
boolean isConnected = activeNetworkInfo!=null && activeNetworkInfo.isConnected();
|
||||||
|
// https://developer.android.com/training/monitoring-device-state/connectivity-monitoring.html?hl=ru
|
||||||
|
// boolean isWiFi = activeNetworkInfo!=null && (activeNetworkInfo.getType() == ConnectivityManager.TYPE_WIFI);
|
||||||
|
|
||||||
|
I2PD_JNI.onNetworkStateChanged(isConnected);
|
||||||
|
} catch (Throwable tr) {
|
||||||
|
Log.d(TAG,"",tr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user