mirror of https://github.com/PurpleI2P/i2pd.git
orignal
8 years ago
committed by
GitHub
58 changed files with 2062 additions and 705 deletions
@ -0,0 +1,7 @@ |
|||||||
|
gen |
||||||
|
tests |
||||||
|
.idea |
||||||
|
local.properties |
||||||
|
build.sh |
||||||
|
bin |
||||||
|
log* |
@ -0,0 +1,25 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
|
package="org.purplei2p.i2pd" |
||||||
|
android:versionCode="1" |
||||||
|
android:versionName="1.0"> |
||||||
|
<uses-sdk android:minSdkVersion="9" android:targetSdkVersion="24"/> |
||||||
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> |
||||||
|
<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"> |
||||||
|
<intent-filter> |
||||||
|
<action android:name="android.intent.action.MAIN" /> |
||||||
|
<category android:name="android.intent.category.LAUNCHER" /> |
||||||
|
</intent-filter> |
||||||
|
</activity> |
||||||
|
<service android:enabled="true" android:name=".ForegroundService"/> |
||||||
|
</application> |
||||||
|
</manifest> |
@ -0,0 +1,97 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<project name="i2pd" default="help"> |
||||||
|
|
||||||
|
<!-- The local.properties file is created and updated by the 'android' tool. |
||||||
|
It contains the path to the SDK. It should *NOT* be checked into |
||||||
|
Version Control Systems. --> |
||||||
|
<property file="local.properties" /> |
||||||
|
|
||||||
|
<!-- The ant.properties file can be created by you. It is only edited by the |
||||||
|
'android' tool to add properties to it. |
||||||
|
This is the place to change some Ant specific build properties. |
||||||
|
Here are some properties you may want to change/update: |
||||||
|
|
||||||
|
source.dir |
||||||
|
The name of the source directory. Default is 'src'. |
||||||
|
out.dir |
||||||
|
The name of the output directory. Default is 'bin'. |
||||||
|
|
||||||
|
For other overridable properties, look at the beginning of the rules |
||||||
|
files in the SDK, at tools/ant/build.xml |
||||||
|
|
||||||
|
Properties related to the SDK location or the project target should |
||||||
|
be updated using the 'android' tool with the 'update' action. |
||||||
|
|
||||||
|
This file is an integral part of the build system for your |
||||||
|
application and should be checked into Version Control Systems. |
||||||
|
|
||||||
|
--> |
||||||
|
<property file="ant.properties" /> |
||||||
|
|
||||||
|
<!-- if sdk.dir was not set from one of the property file, then |
||||||
|
get it from the ANDROID_HOME env var. |
||||||
|
This must be done before we load project.properties since |
||||||
|
the proguard config can use sdk.dir --> |
||||||
|
<property environment="env" /> |
||||||
|
<condition property="sdk.dir" value="${env.ANDROID_HOME}"> |
||||||
|
<isset property="env.ANDROID_HOME" /> |
||||||
|
</condition> |
||||||
|
|
||||||
|
<!-- The project.properties file is created and updated by the 'android' |
||||||
|
tool, as well as ADT. |
||||||
|
|
||||||
|
This contains project specific properties such as project target, and library |
||||||
|
dependencies. Lower level build properties are stored in ant.properties |
||||||
|
(or in .classpath for Eclipse projects). |
||||||
|
|
||||||
|
This file is an integral part of the build system for your |
||||||
|
application and should be checked into Version Control Systems. --> |
||||||
|
<loadproperties srcFile="project.properties" /> |
||||||
|
|
||||||
|
<!-- quick check on sdk.dir --> |
||||||
|
<fail |
||||||
|
message="sdk.dir is missing. Insert sdk.dir=... into './local.properties'. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable." |
||||||
|
unless="sdk.dir" |
||||||
|
/> |
||||||
|
|
||||||
|
<fail |
||||||
|
message="ndk.dir is missing. Insert ndk.dir=... into './local.properties'." |
||||||
|
unless="ndk.dir" |
||||||
|
/> |
||||||
|
|
||||||
|
<!-- |
||||||
|
Import per project custom build rules if present at the root of the project. |
||||||
|
This is the place to put custom intermediary targets such as: |
||||||
|
-pre-build |
||||||
|
-pre-compile |
||||||
|
-post-compile (This is typically used for code obfuscation. |
||||||
|
Compiled code location: ${out.classes.absolute.dir} |
||||||
|
If this is not done in place, override ${out.dex.input.absolute.dir}) |
||||||
|
-post-package |
||||||
|
-post-build |
||||||
|
-pre-clean |
||||||
|
--> |
||||||
|
<import file="custom_rules.xml" optional="true" /> |
||||||
|
|
||||||
|
<!-- Import the actual build file. |
||||||
|
|
||||||
|
To customize existing targets, there are two options: |
||||||
|
- Customize only one target: |
||||||
|
- copy/paste the target into this file, *before* the |
||||||
|
<import> task. |
||||||
|
- customize it to your needs. |
||||||
|
- Customize the whole content of build.xml |
||||||
|
- copy/paste the content of the rules files (minus the top node) |
||||||
|
into this file, replacing the <import> task. |
||||||
|
- customize to your needs. |
||||||
|
|
||||||
|
*********************** |
||||||
|
****** IMPORTANT ****** |
||||||
|
*********************** |
||||||
|
In all cases you must update the value of version-tag below to read 'custom' instead of an integer, |
||||||
|
in order to avoid having your file be overridden by tools such as "android update project" |
||||||
|
--> |
||||||
|
<!-- version-tag: 1 --> |
||||||
|
<import file="${sdk.dir}/tools/ant/build.xml" /> |
||||||
|
|
||||||
|
</project> |
@ -0,0 +1,113 @@ |
|||||||
|
LOCAL_PATH := $(call my-dir) |
||||||
|
include $(CLEAR_VARS) |
||||||
|
LOCAL_MODULE := i2pd |
||||||
|
LOCAL_CPP_FEATURES := rtti exceptions |
||||||
|
LOCAL_C_INCLUDES += $(IFADDRS_PATH) ../.. |
||||||
|
LOCAL_STATIC_LIBRARIES := \
|
||||||
|
boost_system-gcc-mt-1_53 \
|
||||||
|
boost_date_time-gcc-mt-1_53 \
|
||||||
|
boost_filesystem-gcc-mt-1_53 \
|
||||||
|
boost_program_options-gcc-mt-1_53 \
|
||||||
|
crypto ssl \
|
||||||
|
miniupnpc |
||||||
|
LOCAL_LDLIBS := -lz |
||||||
|
|
||||||
|
LOCAL_SRC_FILES := DaemonAndroid.cpp i2pd_android.cpp \
|
||||||
|
$(IFADDRS_PATH)/ifaddrs.c \
|
||||||
|
../../HTTPServer.cpp ../../I2PControl.cpp ../../Daemon.cpp ../../Config.cpp \
|
||||||
|
../../AddressBook.cpp \
|
||||||
|
../../api.cpp \
|
||||||
|
../../Base.cpp \
|
||||||
|
../../BOB.cpp \
|
||||||
|
../../ClientContext.cpp \
|
||||||
|
../../Crypto.cpp \
|
||||||
|
../../Datagram.cpp \
|
||||||
|
../../Destination.cpp \
|
||||||
|
../../Family.cpp \
|
||||||
|
../../FS.cpp \
|
||||||
|
../../Garlic.cpp \
|
||||||
|
../../Gzip.cpp \
|
||||||
|
../../HTTP.cpp \
|
||||||
|
../../HTTPProxy.cpp \
|
||||||
|
../../I2CP.cpp \
|
||||||
|
../../I2NPProtocol.cpp \
|
||||||
|
../../I2PEndian.cpp \
|
||||||
|
../../I2PService.cpp \
|
||||||
|
../../I2PTunnel.cpp \
|
||||||
|
../../Identity.cpp \
|
||||||
|
../../LeaseSet.cpp \
|
||||||
|
../../Log.cpp \
|
||||||
|
../../NetDb.cpp \
|
||||||
|
../../NetDbRequests.cpp \
|
||||||
|
../../NTCPSession.cpp \
|
||||||
|
../../Profiling.cpp \
|
||||||
|
../../Reseed.cpp \
|
||||||
|
../../RouterContext.cpp \
|
||||||
|
../../RouterInfo.cpp \
|
||||||
|
../../SAM.cpp \
|
||||||
|
../../Signature.cpp \
|
||||||
|
../../SOCKS.cpp \
|
||||||
|
../../SSU.cpp \
|
||||||
|
../../SSUData.cpp \
|
||||||
|
../../SSUSession.cpp \
|
||||||
|
../../Streaming.cpp \
|
||||||
|
../../TransitTunnel.cpp \
|
||||||
|
../../Transports.cpp \
|
||||||
|
../../Tunnel.cpp \
|
||||||
|
../../TunnelEndpoint.cpp \
|
||||||
|
../../TunnelGateway.cpp \
|
||||||
|
../../TunnelPool.cpp \
|
||||||
|
../../util.cpp \
|
||||||
|
../../i2pd.cpp ../../UPnP.cpp |
||||||
|
|
||||||
|
include $(BUILD_SHARED_LIBRARY) |
||||||
|
|
||||||
|
LOCAL_PATH := $(call my-dir) |
||||||
|
include $(CLEAR_VARS) |
||||||
|
LOCAL_MODULE := boost_system-gcc-mt-1_53 |
||||||
|
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_53_0/$(TARGET_ARCH_ABI)/lib/libboost_system-gcc-mt-1_53.a |
||||||
|
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_53_0/include |
||||||
|
include $(PREBUILT_STATIC_LIBRARY) |
||||||
|
|
||||||
|
LOCAL_PATH := $(call my-dir) |
||||||
|
include $(CLEAR_VARS) |
||||||
|
LOCAL_MODULE := boost_date_time-gcc-mt-1_53 |
||||||
|
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_53_0/$(TARGET_ARCH_ABI)/lib/libboost_date_time-gcc-mt-1_53.a |
||||||
|
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_53_0/include |
||||||
|
include $(PREBUILT_STATIC_LIBRARY) |
||||||
|
|
||||||
|
LOCAL_PATH := $(call my-dir) |
||||||
|
include $(CLEAR_VARS) |
||||||
|
LOCAL_MODULE := boost_filesystem-gcc-mt-1_53 |
||||||
|
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_53_0/$(TARGET_ARCH_ABI)/lib/libboost_filesystem-gcc-mt-1_53.a |
||||||
|
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_53_0/include |
||||||
|
include $(PREBUILT_STATIC_LIBRARY) |
||||||
|
|
||||||
|
LOCAL_PATH := $(call my-dir) |
||||||
|
include $(CLEAR_VARS) |
||||||
|
LOCAL_MODULE := boost_program_options-gcc-mt-1_53 |
||||||
|
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_53_0/$(TARGET_ARCH_ABI)/lib/libboost_program_options-gcc-mt-1_53.a |
||||||
|
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_53_0/include |
||||||
|
include $(PREBUILT_STATIC_LIBRARY) |
||||||
|
|
||||||
|
LOCAL_PATH := $(call my-dir) |
||||||
|
include $(CLEAR_VARS) |
||||||
|
LOCAL_MODULE := crypto |
||||||
|
LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.0.2/$(TARGET_ARCH_ABI)/lib/libcrypto.a |
||||||
|
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.0.2/include |
||||||
|
include $(PREBUILT_STATIC_LIBRARY) |
||||||
|
|
||||||
|
LOCAL_PATH := $(call my-dir) |
||||||
|
include $(CLEAR_VARS) |
||||||
|
LOCAL_MODULE := ssl |
||||||
|
LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.0.2/$(TARGET_ARCH_ABI)/lib/libssl.a |
||||||
|
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.0.2/include |
||||||
|
LOCAL_STATIC_LIBRARIES := crypto |
||||||
|
include $(PREBUILT_STATIC_LIBRARY) |
||||||
|
|
||||||
|
LOCAL_PATH := $(call my-dir) |
||||||
|
include $(CLEAR_VARS) |
||||||
|
LOCAL_MODULE := miniupnpc |
||||||
|
LOCAL_SRC_FILES := $(MINIUPNP_PATH)/miniupnp-2.0/$(TARGET_ARCH_ABI)/lib/libminiupnpc.a |
||||||
|
LOCAL_EXPORT_C_INCLUDES := $(MINIUPNP_PATH)/miniupnp-2.0/include |
||||||
|
include $(PREBUILT_STATIC_LIBRARY) |
@ -0,0 +1,32 @@ |
|||||||
|
#APP_ABI := all
|
||||||
|
#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.
|
||||||
|
APP_PLATFORM := android-9 |
||||||
|
|
||||||
|
# http://stackoverflow.com/a/21386866/529442 http://stackoverflow.com/a/15616255/529442 to enable c++11 support in Eclipse
|
||||||
|
NDK_TOOLCHAIN_VERSION := 4.9 |
||||||
|
# APP_STL := stlport_shared --> does not seem to contain C++11 features
|
||||||
|
APP_STL := gnustl_shared |
||||||
|
|
||||||
|
# Enable c++11 extentions in source code
|
||||||
|
APP_CPPFLAGS += -std=c++11 |
||||||
|
|
||||||
|
APP_CPPFLAGS += -DANDROID -D__ANDROID__ -DUSE_UPNP |
||||||
|
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a) |
||||||
|
APP_CPPFLAGS += -DANDROID_ARM7A |
||||||
|
endif |
||||||
|
|
||||||
|
APP_OPTIM := debug |
||||||
|
|
||||||
|
# git clone https://github.com/PurpleI2P/Boost-for-Android-Prebuilt.git
|
||||||
|
# git clone https://github.com/PurpleI2P/OpenSSL-for-Android-Prebuilt.git
|
||||||
|
# git clone https://github.com/PurpleI2P/MiniUPnP-for-Android-Prebuilt.git
|
||||||
|
# git clone https://github.com/PurpleI2P/android-ifaddrs.git
|
||||||
|
# change to your own
|
||||||
|
I2PD_LIBS_PATH=/path/to/libraries |
||||||
|
BOOST_PATH = $(I2PD_LIBS_PATH)/Boost-for-Android-Prebuilt |
||||||
|
OPENSSL_PATH = $(I2PD_LIBS_PATH)/OpenSSL-for-Android-Prebuilt |
||||||
|
MINIUPNP_PATH = $(I2PD_LIBS_PATH)/MiniUPnP-for-Android-Prebuilt |
||||||
|
IFADDRS_PATH = $(I2PD_LIBS_PATH)/android-ifaddrs |
@ -0,0 +1,194 @@ |
|||||||
|
#include "DaemonAndroid.h" |
||||||
|
#include "../../Daemon.h" |
||||||
|
#include <iostream> |
||||||
|
#include <boost/exception/diagnostic_information.hpp> |
||||||
|
#include <boost/exception_ptr.hpp> |
||||||
|
#include <exception> |
||||||
|
//#include "mainwindow.h"
|
||||||
|
|
||||||
|
namespace i2p |
||||||
|
{ |
||||||
|
namespace android |
||||||
|
{ |
||||||
|
/* Worker::Worker (DaemonAndroidImpl& daemon):
|
||||||
|
m_Daemon (daemon) |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
void Worker::startDaemon() |
||||||
|
{ |
||||||
|
Log.d(TAG"Performing daemon start..."); |
||||||
|
m_Daemon.start(); |
||||||
|
Log.d(TAG"Daemon started."); |
||||||
|
emit resultReady(); |
||||||
|
} |
||||||
|
void Worker::restartDaemon() |
||||||
|
{ |
||||||
|
Log.d(TAG"Performing daemon restart..."); |
||||||
|
m_Daemon.restart(); |
||||||
|
Log.d(TAG"Daemon restarted."); |
||||||
|
emit resultReady(); |
||||||
|
} |
||||||
|
void Worker::stopDaemon() { |
||||||
|
Log.d(TAG"Performing daemon stop..."); |
||||||
|
m_Daemon.stop(); |
||||||
|
Log.d(TAG"Daemon stopped."); |
||||||
|
emit resultReady(); |
||||||
|
} |
||||||
|
|
||||||
|
Controller::Controller(DaemonAndroidImpl& daemon): |
||||||
|
m_Daemon (daemon) |
||||||
|
{ |
||||||
|
Worker *worker = new Worker (m_Daemon); |
||||||
|
worker->moveToThread(&workerThread); |
||||||
|
connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater); |
||||||
|
connect(this, &Controller::startDaemon, worker, &Worker::startDaemon); |
||||||
|
connect(this, &Controller::stopDaemon, worker, &Worker::stopDaemon); |
||||||
|
connect(this, &Controller::restartDaemon, worker, &Worker::restartDaemon); |
||||||
|
connect(worker, &Worker::resultReady, this, &Controller::handleResults); |
||||||
|
workerThread.start(); |
||||||
|
} |
||||||
|
Controller::~Controller() |
||||||
|
{ |
||||||
|
Log.d(TAG"Closing and waiting for daemon worker thread..."); |
||||||
|
workerThread.quit(); |
||||||
|
workerThread.wait(); |
||||||
|
Log.d(TAG"Waiting for daemon worker thread finished."); |
||||||
|
if(m_Daemon.isRunning()) |
||||||
|
{ |
||||||
|
Log.d(TAG"Stopping the daemon..."); |
||||||
|
m_Daemon.stop(); |
||||||
|
Log.d(TAG"Stopped the daemon."); |
||||||
|
} |
||||||
|
} |
||||||
|
*/ |
||||||
|
DaemonAndroidImpl::DaemonAndroidImpl () |
||||||
|
//:
|
||||||
|
/*mutex(nullptr), */ |
||||||
|
//m_IsRunning(false),
|
||||||
|
//m_RunningChangedCallback(nullptr)
|
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
DaemonAndroidImpl::~DaemonAndroidImpl () |
||||||
|
{ |
||||||
|
//delete mutex;
|
||||||
|
} |
||||||
|
|
||||||
|
bool DaemonAndroidImpl::init(int argc, char* argv[]) |
||||||
|
{ |
||||||
|
//mutex=new QMutex(QMutex::Recursive);
|
||||||
|
//setRunningCallback(0);
|
||||||
|
//m_IsRunning=false;
|
||||||
|
return Daemon.init(argc,argv); |
||||||
|
} |
||||||
|
|
||||||
|
void DaemonAndroidImpl::start() |
||||||
|
{ |
||||||
|
//QMutexLocker locker(mutex);
|
||||||
|
//setRunning(true);
|
||||||
|
Daemon.start(); |
||||||
|
} |
||||||
|
|
||||||
|
void DaemonAndroidImpl::stop() |
||||||
|
{ |
||||||
|
//QMutexLocker locker(mutex);
|
||||||
|
Daemon.stop(); |
||||||
|
//setRunning(false);
|
||||||
|
} |
||||||
|
|
||||||
|
void DaemonAndroidImpl::restart() |
||||||
|
{ |
||||||
|
//QMutexLocker locker(mutex);
|
||||||
|
stop(); |
||||||
|
start(); |
||||||
|
} |
||||||
|
/*
|
||||||
|
void DaemonAndroidImpl::setRunningCallback(runningChangedCallback cb) |
||||||
|
{ |
||||||
|
m_RunningChangedCallback = cb; |
||||||
|
} |
||||||
|
|
||||||
|
bool DaemonAndroidImpl::isRunning() |
||||||
|
{ |
||||||
|
return m_IsRunning; |
||||||
|
} |
||||||
|
|
||||||
|
void DaemonAndroidImpl::setRunning(bool newValue) |
||||||
|
{ |
||||||
|
bool oldValue = m_IsRunning; |
||||||
|
if(oldValue!=newValue) |
||||||
|
{ |
||||||
|
m_IsRunning = newValue; |
||||||
|
if(m_RunningChangedCallback) |
||||||
|
m_RunningChangedCallback(); |
||||||
|
} |
||||||
|
} |
||||||
|
*/ |
||||||
|
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[]*/) |
||||||
|
{ |
||||||
|
try |
||||||
|
{ |
||||||
|
//int result;
|
||||||
|
|
||||||
|
{ |
||||||
|
//Log.d(TAG"Initialising the daemon...");
|
||||||
|
bool daemonInitSuccess = daemon.init(1,argv); |
||||||
|
if(!daemonInitSuccess) |
||||||
|
{ |
||||||
|
//QMessageBox::critical(0, "Error", "Daemon init failed");
|
||||||
|
return "Daemon init failed"; |
||||||
|
} |
||||||
|
//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"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) |
||||||
|
{ |
||||||
|
std::stringstream ss; |
||||||
|
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() |
||||||
|
{ |
||||||
|
daemon.stop(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
@ -0,0 +1,87 @@ |
|||||||
|
#ifndef DAEMON_ANDROID_H |
||||||
|
#define DAEMON_ANDROID_H |
||||||
|
|
||||||
|
#include <string> |
||||||
|
|
||||||
|
namespace i2p |
||||||
|
{ |
||||||
|
namespace android |
||||||
|
{ |
||||||
|
class DaemonAndroidImpl |
||||||
|
{ |
||||||
|
public: |
||||||
|
|
||||||
|
DaemonAndroidImpl (); |
||||||
|
~DaemonAndroidImpl (); |
||||||
|
|
||||||
|
//typedef void (*runningChangedCallback)();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return success |
||||||
|
*/ |
||||||
|
bool init(int argc, char* argv[]); |
||||||
|
void start(); |
||||||
|
void stop(); |
||||||
|
void restart(); |
||||||
|
//void setRunningCallback(runningChangedCallback cb);
|
||||||
|
//bool isRunning();
|
||||||
|
private: |
||||||
|
//void setRunning(bool running);
|
||||||
|
private: |
||||||
|
//QMutex* mutex;
|
||||||
|
//bool m_IsRunning;
|
||||||
|
//runningChangedCallback m_RunningChangedCallback;
|
||||||
|
}; |
||||||
|
|
||||||
|
/**
|
||||||
|
* returns "ok" if daemon init failed |
||||||
|
* returns errinfo if daemon initialized and started okay |
||||||
|
*/ |
||||||
|
std::string start(); |
||||||
|
|
||||||
|
// stops the daemon
|
||||||
|
void stop(); |
||||||
|
|
||||||
|
/*
|
||||||
|
class Worker : public QObject |
||||||
|
{ |
||||||
|
Q_OBJECT |
||||||
|
public: |
||||||
|
|
||||||
|
Worker (DaemonAndroidImpl& daemon); |
||||||
|
|
||||||
|
private: |
||||||
|
|
||||||
|
DaemonAndroidImpl& m_Daemon; |
||||||
|
|
||||||
|
public slots: |
||||||
|
void startDaemon(); |
||||||
|
void restartDaemon(); |
||||||
|
void stopDaemon(); |
||||||
|
|
||||||
|
signals: |
||||||
|
void resultReady(); |
||||||
|
}; |
||||||
|
|
||||||
|
class Controller : public QObject |
||||||
|
{ |
||||||
|
Q_OBJECT |
||||||
|
QThread workerThread; |
||||||
|
public: |
||||||
|
Controller(DaemonAndroidImpl& daemon); |
||||||
|
~Controller(); |
||||||
|
private: |
||||||
|
DaemonAndroidImpl& m_Daemon; |
||||||
|
|
||||||
|
public slots: |
||||||
|
void handleResults(){} |
||||||
|
signals: |
||||||
|
void startDaemon(); |
||||||
|
void stopDaemon(); |
||||||
|
void restartDaemon(); |
||||||
|
}; |
||||||
|
*/ |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#endif // DAEMON_ANDROID_H
|
@ -0,0 +1,66 @@ |
|||||||
|
|
||||||
|
//#include <string.h>
|
||||||
|
#include <jni.h> |
||||||
|
#include "org_purplei2p_i2pd_I2PD_JNI.h" |
||||||
|
#include "DaemonAndroid.h" |
||||||
|
#include "../../RouterContext.h" |
||||||
|
#include "../../Transports.h" |
||||||
|
|
||||||
|
JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getABICompiledWith |
||||||
|
(JNIEnv * env, jclass clazz) { |
||||||
|
#if defined(__arm__) |
||||||
|
#if defined(__ARM_ARCH_7A__) |
||||||
|
#if defined(__ARM_NEON__) |
||||||
|
#if defined(__ARM_PCS_VFP) |
||||||
|
#define ABI "armeabi-v7a/NEON (hard-float)" |
||||||
|
#else |
||||||
|
#define ABI "armeabi-v7a/NEON" |
||||||
|
#endif |
||||||
|
#else |
||||||
|
#if defined(__ARM_PCS_VFP) |
||||||
|
#define ABI "armeabi-v7a (hard-float)" |
||||||
|
#else |
||||||
|
#define ABI "armeabi-v7a" |
||||||
|
#endif |
||||||
|
#endif |
||||||
|
#else |
||||||
|
#define ABI "armeabi" |
||||||
|
#endif |
||||||
|
#elif defined(__i386__) |
||||||
|
#define ABI "x86" |
||||||
|
#elif defined(__x86_64__) |
||||||
|
#define ABI "x86_64" |
||||||
|
#elif defined(__mips64) /* mips64el-* toolchain defines __mips__ too */ |
||||||
|
#define ABI "mips64" |
||||||
|
#elif defined(__mips__) |
||||||
|
#define ABI "mips" |
||||||
|
#elif defined(__aarch64__) |
||||||
|
#define ABI "arm64-v8a" |
||||||
|
#else |
||||||
|
#define ABI "unknown" |
||||||
|
#endif |
||||||
|
|
||||||
|
return env->NewStringUTF(ABI); |
||||||
|
} |
||||||
|
|
||||||
|
JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startDaemon |
||||||
|
(JNIEnv * env, jclass clazz) { |
||||||
|
return env->NewStringUTF(i2p::android::start().c_str()); |
||||||
|
} |
||||||
|
|
||||||
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopDaemon |
||||||
|
(JNIEnv * env, jclass clazz) { |
||||||
|
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; |
||||||
|
i2p::transport::transports.SetOnline (isConnectedBool); |
||||||
|
} |
@ -0,0 +1,33 @@ |
|||||||
|
/* DO NOT EDIT THIS FILE - it is machine generated */ |
||||||
|
#include <jni.h> |
||||||
|
/* Header for class org_purplei2p_i2pd_I2PD_JNI */ |
||||||
|
|
||||||
|
#ifndef _Included_org_purplei2p_i2pd_I2PD_JNI |
||||||
|
#define _Included_org_purplei2p_i2pd_I2PD_JNI |
||||||
|
#ifdef __cplusplus |
||||||
|
extern "C" { |
||||||
|
#endif |
||||||
|
/*
|
||||||
|
* Class: org_purplei2p_i2pd_I2PD_JNI |
||||||
|
* Method: stringFromJNI |
||||||
|
* Signature: ()Ljava/lang/String; |
||||||
|
*/ |
||||||
|
JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getABICompiledWith |
||||||
|
(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 |
||||||
|
} |
||||||
|
#endif |
||||||
|
#endif |
Binary file not shown.
@ -0,0 +1,20 @@ |
|||||||
|
# To enable ProGuard in your project, edit project.properties |
||||||
|
# to define the proguard.config property as described in that file. |
||||||
|
# |
||||||
|
# Add project specific ProGuard rules here. |
||||||
|
# By default, the flags in this file are appended to flags specified |
||||||
|
# in ${sdk.dir}/tools/proguard/proguard-android.txt |
||||||
|
# You can edit the include path and order by changing the ProGuard |
||||||
|
# include property in project.properties. |
||||||
|
# |
||||||
|
# For more details, see |
||||||
|
# http://developer.android.com/guide/developing/tools/proguard.html |
||||||
|
|
||||||
|
# Add any project specific keep options here: |
||||||
|
|
||||||
|
# If your project uses WebView with JS, uncomment the following |
||||||
|
# and specify the fully qualified class name to the JavaScript interface |
||||||
|
# class: |
||||||
|
#-keepclassmembers class fqcn.of.javascript.interface.for.webview { |
||||||
|
# public *; |
||||||
|
#} |
@ -0,0 +1,14 @@ |
|||||||
|
# This file is automatically generated by Android Tools. |
||||||
|
# Do not modify this file -- YOUR CHANGES WILL BE ERASED! |
||||||
|
# |
||||||
|
# This file must be checked in Version Control Systems. |
||||||
|
# |
||||||
|
# To customize properties used by the Ant build system edit |
||||||
|
# "ant.properties", and override values to adapt the script to your |
||||||
|
# project structure. |
||||||
|
# |
||||||
|
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): |
||||||
|
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt |
||||||
|
|
||||||
|
# Project target. |
||||||
|
target=android-24 |
After Width: | Height: | Size: 8.5 KiB |
After Width: | Height: | Size: 32 KiB |
@ -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> |
@ -0,0 +1,9 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<resources> |
||||||
|
<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> |
@ -0,0 +1,124 @@ |
|||||||
|
package org.purplei2p.i2pd; |
||||||
|
|
||||||
|
import java.util.HashSet; |
||||||
|
import java.util.Set; |
||||||
|
|
||||||
|
import android.util.Log; |
||||||
|
|
||||||
|
public class DaemonSingleton { |
||||||
|
private static final String TAG="i2pd"; |
||||||
|
private static final DaemonSingleton instance = new DaemonSingleton(); |
||||||
|
public static interface StateChangeListener { void daemonStateChanged(); } |
||||||
|
private final Set<StateChangeListener> stateChangeListeners = new HashSet<StateChangeListener>(); |
||||||
|
|
||||||
|
public static DaemonSingleton getInstance() { |
||||||
|
return instance; |
||||||
|
} |
||||||
|
|
||||||
|
public synchronized void addStateChangeListener(StateChangeListener listener) { stateChangeListeners.add(listener); } |
||||||
|
public synchronized void removeStateChangeListener(StateChangeListener listener) { stateChangeListeners.remove(listener); } |
||||||
|
|
||||||
|
public synchronized void stopAcceptingTunnels() { |
||||||
|
if(isStartedOkay()){ |
||||||
|
state=State.gracefulShutdownInProgress; |
||||||
|
fireStateChange(); |
||||||
|
I2PD_JNI.stopAcceptingTunnels(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void onNetworkStateChange(boolean isConnected) { |
||||||
|
I2PD_JNI.onNetworkStateChanged(isConnected); |
||||||
|
} |
||||||
|
|
||||||
|
private boolean startedOkay; |
||||||
|
|
||||||
|
public static enum State {starting,jniLibraryLoaded,startedOkay,startFailed,gracefulShutdownInProgress}; |
||||||
|
|
||||||
|
private State state = State.starting; |
||||||
|
|
||||||
|
public State getState() { return state; } |
||||||
|
|
||||||
|
{ |
||||||
|
synchronized(this){ |
||||||
|
fireStateChange(); |
||||||
|
new Thread(new Runnable(){ |
||||||
|
|
||||||
|
@Override |
||||||
|
public void run() { |
||||||
|
try { |
||||||
|
I2PD_JNI.loadLibraries(); |
||||||
|
synchronized (DaemonSingleton.this) { |
||||||
|
state = State.jniLibraryLoaded; |
||||||
|
fireStateChange(); |
||||||
|
} |
||||||
|
} catch (Throwable tr) { |
||||||
|
lastThrowable=tr; |
||||||
|
synchronized (DaemonSingleton.this) { |
||||||
|
state = State.startFailed; |
||||||
|
fireStateChange(); |
||||||
|
} |
||||||
|
return; |
||||||
|
} |
||||||
|
try { |
||||||
|
synchronized (DaemonSingleton.this) { |
||||||
|
daemonStartResult = I2PD_JNI.startDaemon(); |
||||||
|
if("ok".equals(daemonStartResult)){state=State.startedOkay;setStartedOkay(true);} |
||||||
|
else state=State.startFailed; |
||||||
|
fireStateChange(); |
||||||
|
} |
||||||
|
} catch (Throwable tr) { |
||||||
|
lastThrowable=tr; |
||||||
|
synchronized (DaemonSingleton.this) { |
||||||
|
state = State.startFailed; |
||||||
|
fireStateChange(); |
||||||
|
} |
||||||
|
return; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
}, "i2pdDaemonStart").start(); |
||||||
|
} |
||||||
|
} |
||||||
|
private Throwable lastThrowable; |
||||||
|
private String daemonStartResult="N/A"; |
||||||
|
|
||||||
|
private synchronized void fireStateChange() { |
||||||
|
Log.i(TAG, "daemon state change: "+state); |
||||||
|
for(StateChangeListener listener : stateChangeListeners) { |
||||||
|
try { |
||||||
|
listener.daemonStateChanged(); |
||||||
|
} catch (Throwable tr) { |
||||||
|
Log.e(TAG, "exception in listener ignored", tr); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public Throwable getLastThrowable() { |
||||||
|
return lastThrowable; |
||||||
|
} |
||||||
|
|
||||||
|
public String getDaemonStartResult() { |
||||||
|
return daemonStartResult; |
||||||
|
} |
||||||
|
|
||||||
|
private final Object startedOkayLock = new Object(); |
||||||
|
|
||||||
|
public boolean isStartedOkay() { |
||||||
|
synchronized (startedOkayLock) { |
||||||
|
return startedOkay; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private void setStartedOkay(boolean startedOkay) { |
||||||
|
synchronized (startedOkayLock) { |
||||||
|
this.startedOkay = startedOkay; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public synchronized void stopDaemon() { |
||||||
|
if(isStartedOkay()){ |
||||||
|
try {I2PD_JNI.stopDaemon();}catch(Throwable tr){Log.e(TAG, "", tr);} |
||||||
|
setStartedOkay(false); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -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); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,243 @@ |
|||||||
|
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.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.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 { |
||||||
|
private static final String TAG = "i2pd"; |
||||||
|
private DaemonSingleton daemon = DaemonSingleton.getInstance(); |
||||||
|
private DaemonSingleton.StateChangeListener daemonStateChangeListener = |
||||||
|
new DaemonSingleton.StateChangeListener() { |
||||||
|
|
||||||
|
@Override |
||||||
|
public void daemonStateChanged() { |
||||||
|
runOnUiThread(new Runnable(){ |
||||||
|
|
||||||
|
@Override |
||||||
|
public void run() { |
||||||
|
try { |
||||||
|
if(textView==null)return; |
||||||
|
Throwable tr = daemon.getLastThrowable(); |
||||||
|
if(tr!=null) { |
||||||
|
textView.setText(throwableToString(tr)); |
||||||
|
return; |
||||||
|
} |
||||||
|
DaemonSingleton.State state = daemon.getState(); |
||||||
|
textView.setText(String.valueOf(state)+ |
||||||
|
(DaemonSingleton.State.startFailed.equals(state)?": "+daemon.getDaemonStartResult():"")); |
||||||
|
} catch (Throwable tr) { |
||||||
|
Log.e(TAG,"error ignored",tr); |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
private TextView textView; |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onCreate(Bundle savedInstanceState) { |
||||||
|
super.onCreate(savedInstanceState); |
||||||
|
|
||||||
|
//set the app be foreground (do not unload when RAM needed)
|
||||||
|
doBindService(); |
||||||
|
|
||||||
|
textView = new TextView(this); |
||||||
|
setContentView(textView); |
||||||
|
daemonStateChangeListener.daemonStateChanged(); |
||||||
|
daemon.addStateChangeListener(daemonStateChangeListener); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void onDestroy() { |
||||||
|
super.onDestroy(); |
||||||
|
localDestroy(); |
||||||
|
} |
||||||
|
|
||||||
|
private void localDestroy() { |
||||||
|
textView = null; |
||||||
|
daemon.removeStateChangeListener(daemonStateChangeListener); |
||||||
|
Timer gracefulQuitTimer = getGracefulQuitTimer(); |
||||||
|
if(gracefulQuitTimer!=null) { |
||||||
|
gracefulQuitTimer.cancel(); |
||||||
|
setGracefulQuitTimer(null); |
||||||
|
} |
||||||
|
try{ |
||||||
|
doUnbindService(); |
||||||
|
}catch(Throwable tr){ |
||||||
|
Log.e(TAG, "", tr); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private CharSequence throwableToString(Throwable tr) { |
||||||
|
StringWriter sw = new StringWriter(8192); |
||||||
|
PrintWriter pw = new PrintWriter(sw); |
||||||
|
tr.printStackTrace(pw); |
||||||
|
pw.close(); |
||||||
|
return sw.toString(); |
||||||
|
} |
||||||
|
|
||||||
|
// 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 { |
||||||
|
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); |
||||||
|
} |
||||||
|
try{ |
||||||
|
daemon.stopDaemon(); |
||||||
|
}catch (Throwable tr) { |
||||||
|
Log.e(TAG, "", tr); |
||||||
|
} |
||||||
|
System.exit(0); |
||||||
|
} |
||||||
|
|
||||||
|
private Timer gracefulQuitTimer; |
||||||
|
private final Object gracefulQuitTimerLock = new Object(); |
||||||
|
private void gracefulQuit() { |
||||||
|
if(getGracefulQuitTimer()!=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{ |
||||||
|
Log.d(TAG, "grac stopping"); |
||||||
|
if(daemon.isStartedOkay()) { |
||||||
|
daemon.stopAcceptingTunnels(); |
||||||
|
Timer gracefulQuitTimer = new Timer(true); |
||||||
|
setGracefulQuitTimer(gracefulQuitTimer); |
||||||
|
gracefulQuitTimer.schedule(new TimerTask(){ |
||||||
|
|
||||||
|
@Override |
||||||
|
public void run() { |
||||||
|
quit(); |
||||||
|
} |
||||||
|
|
||||||
|
}, 10*60*1000/*milliseconds*/); |
||||||
|
}else{ |
||||||
|
quit(); |
||||||
|
} |
||||||
|
} catch(Throwable tr) { |
||||||
|
Log.e(TAG,"",tr); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
},"gracQuitInit").start(); |
||||||
|
} |
||||||
|
|
||||||
|
private Timer getGracefulQuitTimer() { |
||||||
|
synchronized (gracefulQuitTimerLock) { |
||||||
|
return gracefulQuitTimer; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private void setGracefulQuitTimer(Timer gracefulQuitTimer) { |
||||||
|
synchronized (gracefulQuitTimerLock) { |
||||||
|
this.gracefulQuitTimer = gracefulQuitTimer; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,21 @@ |
|||||||
|
package org.purplei2p.i2pd; |
||||||
|
|
||||||
|
public class I2PD_JNI { |
||||||
|
public static native String getABICompiledWith(); |
||||||
|
/** |
||||||
|
* returns error info if failed |
||||||
|
* returns "ok" if daemon initialized and started okay |
||||||
|
*/ |
||||||
|
public static native String startDaemon(); |
||||||
|
//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() { |
||||||
|
System.loadLibrary("gnustl_shared"); |
||||||
|
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