mirror of
https://github.com/PurpleI2P/i2pd-android.git
synced 2025-02-09 05:14:24 +00:00
revert switching from JNI to binary
Signed-off-by: r4sas <r4sas@i2pmail.org>
This commit is contained in:
parent
8347c04fb1
commit
503f8a003e
6
.github/workflows/android.yml
vendored
6
.github/workflows/android.yml
vendored
@ -21,7 +21,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
export ANDROID_NDK_HOME=$ANDROID_HOME/ndk/23.2.8568313
|
export ANDROID_NDK_HOME=$ANDROID_HOME/ndk/23.2.8568313
|
||||||
pushd binary/jni
|
pushd binary/jni
|
||||||
./build.sh -md
|
./build.sh
|
||||||
popd
|
popd
|
||||||
- name: Build with Gradle
|
- name: Build with Gradle
|
||||||
run: ./gradlew --no-daemon assembleDebug
|
run: ./gradlew --no-daemon assembleDebug
|
||||||
@ -45,11 +45,11 @@ jobs:
|
|||||||
run: export JAVA_HOME=$JAVA_HOME_11_X64
|
run: export JAVA_HOME=$JAVA_HOME_11_X64
|
||||||
- name: Install required Android SDK packages
|
- name: Install required Android SDK packages
|
||||||
run: $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager "cmake;3.22.1" "ndk;23.2.8568313"
|
run: $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager "cmake;3.22.1" "ndk;23.2.8568313"
|
||||||
- name: Build binaries with NDK
|
- name: Build binary with NDK
|
||||||
run: |
|
run: |
|
||||||
export ANDROID_NDK_HOME=$ANDROID_HOME/ndk/23.2.8568313
|
export ANDROID_NDK_HOME=$ANDROID_HOME/ndk/23.2.8568313
|
||||||
pushd binary/jni
|
pushd binary/jni
|
||||||
./build.sh
|
./build.sh -b
|
||||||
popd
|
popd
|
||||||
- name: Create package with built binaries
|
- name: Create package with built binaries
|
||||||
run: |
|
run: |
|
||||||
|
@ -42,7 +42,6 @@ unzip commandlinetools-linux-8092744_latest.zip
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone --recurse-submodules https://github.com/PurpleI2P/i2pd-android.git
|
git clone --recurse-submodules https://github.com/PurpleI2P/i2pd-android.git
|
||||||
cd i2pd-android
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Compile application
|
### Compile application
|
||||||
@ -54,8 +53,10 @@ export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64
|
|||||||
export ANDROID_HOME=/opt/android-sdk
|
export ANDROID_HOME=/opt/android-sdk
|
||||||
export ANDROID_NDK_HOME=$ANDROID_HOME/ndk/23.2.8568313
|
export ANDROID_NDK_HOME=$ANDROID_HOME/ndk/23.2.8568313
|
||||||
|
|
||||||
pushd binary/jni
|
pushd app/jni
|
||||||
./build.sh -md
|
./build_boost.sh
|
||||||
|
./build_openssl.sh
|
||||||
|
./build_miniupnpc.sh
|
||||||
popd
|
popd
|
||||||
|
|
||||||
gradle clean assembleDebug
|
gradle clean assembleDebug
|
||||||
|
@ -29,8 +29,8 @@ android {
|
|||||||
targetSdkVersion 33
|
targetSdkVersion 33
|
||||||
// TODO: 24?
|
// TODO: 24?
|
||||||
minSdkVersion 16
|
minSdkVersion 16
|
||||||
versionCode 2530000
|
versionCode 2530010
|
||||||
versionName "2.53.0"
|
versionName "2.53.0.1"
|
||||||
archivesBaseName += "-$versionName"
|
archivesBaseName += "-$versionName"
|
||||||
ndkVersion "23.2.8568313"
|
ndkVersion "23.2.8568313"
|
||||||
|
|
||||||
@ -40,6 +40,13 @@ android {
|
|||||||
abiFilters "arm64-v8a"
|
abiFilters "arm64-v8a"
|
||||||
abiFilters "x86_64"
|
abiFilters "x86_64"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
externalNativeBuild {
|
||||||
|
ndkBuild {
|
||||||
|
arguments "NDK_MODULE_PATH:=${rootProject.projectDir}/binary/jni"
|
||||||
|
arguments "-j${Runtime.getRuntime().availableProcessors()}"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
splits {
|
splits {
|
||||||
@ -71,9 +78,9 @@ android {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceSets {
|
externalNativeBuild {
|
||||||
main {
|
ndkBuild {
|
||||||
jniLibs.srcDir file("${rootProject.projectDir}/binary/libs")
|
path "${rootProject.projectDir}/app/jni/Android.mk"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
80
app/jni/Android.mk
Normal file
80
app/jni/Android.mk
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
LOCAL_PATH := $(call my-dir)
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := i2pd
|
||||||
|
LOCAL_CPP_FEATURES := rtti exceptions
|
||||||
|
LOCAL_C_INCLUDES += $(IFADDRS_PATH) $(LIB_SRC_PATH) $(LIB_CLIENT_SRC_PATH) $(LANG_SRC_PATH) $(DAEMON_SRC_PATH)
|
||||||
|
LOCAL_STATIC_LIBRARIES := \
|
||||||
|
boost_system \
|
||||||
|
boost_date_time \
|
||||||
|
boost_filesystem \
|
||||||
|
boost_program_options \
|
||||||
|
crypto \
|
||||||
|
ssl \
|
||||||
|
miniupnpc
|
||||||
|
LOCAL_LDLIBS := -lz
|
||||||
|
|
||||||
|
LOCAL_SRC_FILES := \
|
||||||
|
DaemonAndroid.cpp \
|
||||||
|
i2pd_android.cpp \
|
||||||
|
$(IFADDRS_PATH)/ifaddrs.cpp \
|
||||||
|
$(IFADDRS_PATH)/bionic_netlink.cpp \
|
||||||
|
$(wildcard $(LIB_SRC_PATH)/*.cpp) \
|
||||||
|
$(wildcard $(LIB_CLIENT_SRC_PATH)/*.cpp) \
|
||||||
|
$(wildcard $(LANG_SRC_PATH)/*.cpp) \
|
||||||
|
$(DAEMON_SRC_PATH)/Daemon.cpp \
|
||||||
|
$(DAEMON_SRC_PATH)/UPnP.cpp \
|
||||||
|
$(DAEMON_SRC_PATH)/HTTPServer.cpp \
|
||||||
|
$(DAEMON_SRC_PATH)/I2PControl.cpp \
|
||||||
|
$(DAEMON_SRC_PATH)/I2PControlHandlers.cpp
|
||||||
|
|
||||||
|
include $(BUILD_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
LOCAL_PATH := $(call my-dir)
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := boost_system
|
||||||
|
LOCAL_SRC_FILES := $(BOOST_PATH)/build/out/$(TARGET_ARCH_ABI)/lib/libboost_system.a
|
||||||
|
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/build/out/$(TARGET_ARCH_ABI)/include
|
||||||
|
include $(PREBUILT_STATIC_LIBRARY)
|
||||||
|
|
||||||
|
LOCAL_PATH := $(call my-dir)
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := boost_date_time
|
||||||
|
LOCAL_SRC_FILES := $(BOOST_PATH)/build/out/$(TARGET_ARCH_ABI)/lib/libboost_date_time.a
|
||||||
|
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/build/out/$(TARGET_ARCH_ABI)/include
|
||||||
|
include $(PREBUILT_STATIC_LIBRARY)
|
||||||
|
|
||||||
|
LOCAL_PATH := $(call my-dir)
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := boost_filesystem
|
||||||
|
LOCAL_SRC_FILES := $(BOOST_PATH)/build/out/$(TARGET_ARCH_ABI)/lib/libboost_filesystem.a
|
||||||
|
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/build/out/$(TARGET_ARCH_ABI)/include
|
||||||
|
include $(PREBUILT_STATIC_LIBRARY)
|
||||||
|
|
||||||
|
LOCAL_PATH := $(call my-dir)
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := boost_program_options
|
||||||
|
LOCAL_SRC_FILES := $(BOOST_PATH)/build/out/$(TARGET_ARCH_ABI)/lib/libboost_program_options.a
|
||||||
|
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/build/out/$(TARGET_ARCH_ABI)/include
|
||||||
|
include $(PREBUILT_STATIC_LIBRARY)
|
||||||
|
|
||||||
|
LOCAL_PATH := $(call my-dir)
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := crypto
|
||||||
|
LOCAL_SRC_FILES := $(OPENSSL_PATH)/out/$(TARGET_ARCH_ABI)/lib/libcrypto.a
|
||||||
|
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/out/$(TARGET_ARCH_ABI)/include
|
||||||
|
include $(PREBUILT_STATIC_LIBRARY)
|
||||||
|
|
||||||
|
LOCAL_PATH := $(call my-dir)
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := ssl
|
||||||
|
LOCAL_SRC_FILES := $(OPENSSL_PATH)/out/$(TARGET_ARCH_ABI)/lib/libssl.a
|
||||||
|
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/out/$(TARGET_ARCH_ABI)/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)/miniupnpc/out/$(TARGET_ARCH_ABI)/lib/libminiupnpc.a
|
||||||
|
LOCAL_EXPORT_C_INCLUDES := $(MINIUPNP_PATH)/miniupnpc/out/$(TARGET_ARCH_ABI)/include
|
||||||
|
include $(PREBUILT_STATIC_LIBRARY)
|
23
app/jni/Application.mk
Normal file
23
app/jni/Application.mk
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
NDK_TOOLCHAIN_VERSION := clang
|
||||||
|
APP_STL := c++_static
|
||||||
|
|
||||||
|
# Enable c++17 extensions in source code
|
||||||
|
APP_CPPFLAGS += -std=c++17 -fexceptions -frtti
|
||||||
|
|
||||||
|
APP_CPPFLAGS += -DANDROID -D__ANDROID__ -DUSE_UPNP -Wno-deprecated-declarations
|
||||||
|
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
|
||||||
|
APP_CPPFLAGS += -DANDROID_ARM7A
|
||||||
|
endif
|
||||||
|
|
||||||
|
IFADDRS_PATH = $(NDK_MODULE_PATH)/android-ifaddrs
|
||||||
|
BOOST_PATH = $(NDK_MODULE_PATH)/boost
|
||||||
|
MINIUPNP_PATH = $(NDK_MODULE_PATH)/miniupnp
|
||||||
|
OPENSSL_PATH = $(NDK_MODULE_PATH)/openssl
|
||||||
|
|
||||||
|
# don't change me
|
||||||
|
I2PD_SRC_PATH = $(NDK_MODULE_PATH)/i2pd
|
||||||
|
|
||||||
|
LIB_SRC_PATH = $(I2PD_SRC_PATH)/libi2pd
|
||||||
|
LIB_CLIENT_SRC_PATH = $(I2PD_SRC_PATH)/libi2pd_client
|
||||||
|
LANG_SRC_PATH = $(I2PD_SRC_PATH)/i18n
|
||||||
|
DAEMON_SRC_PATH = $(I2PD_SRC_PATH)/daemon
|
138
app/jni/DaemonAndroid.cpp
Normal file
138
app/jni/DaemonAndroid.cpp
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||||
|
*
|
||||||
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
|
*
|
||||||
|
* See full license text in LICENSE file at top of project tree
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <chrono>
|
||||||
|
#include <thread>
|
||||||
|
#include <exception>
|
||||||
|
#include <boost/exception/diagnostic_information.hpp>
|
||||||
|
#include <boost/exception_ptr.hpp>
|
||||||
|
//#include "mainwindow.h"
|
||||||
|
#include "FS.h"
|
||||||
|
#include "DaemonAndroid.h"
|
||||||
|
#include "Daemon.h"
|
||||||
|
#include "I18N.h"
|
||||||
|
|
||||||
|
namespace i2p
|
||||||
|
{
|
||||||
|
namespace android
|
||||||
|
{
|
||||||
|
std::string dataDir = "";
|
||||||
|
std::string language = "";
|
||||||
|
|
||||||
|
DaemonAndroidImpl::DaemonAndroidImpl ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
DaemonAndroidImpl::~DaemonAndroidImpl ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DaemonAndroidImpl::init(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
return Daemon.init(argc, argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DaemonAndroidImpl::start()
|
||||||
|
{
|
||||||
|
Daemon.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DaemonAndroidImpl::stop()
|
||||||
|
{
|
||||||
|
Daemon.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DaemonAndroidImpl::restart()
|
||||||
|
{
|
||||||
|
stop();
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DaemonAndroidImpl::setDataDir(std::string path)
|
||||||
|
{
|
||||||
|
Daemon.setDataDir(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
{
|
||||||
|
{
|
||||||
|
// make sure assets are ready before proceed
|
||||||
|
i2p::fs::DetectDataDir(dataDir, false);
|
||||||
|
int numAttempts = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (i2p::fs::Exists (i2p::fs::DataDirPath("assets.ready"))) break; // assets ready
|
||||||
|
numAttempts++;
|
||||||
|
std::this_thread::sleep_for (std::chrono::seconds(1)); // otherwise wait for 1 more second
|
||||||
|
}
|
||||||
|
while (numAttempts <= 10); // 10 seconds max
|
||||||
|
|
||||||
|
// Set application directory
|
||||||
|
daemon.setDataDir(dataDir);
|
||||||
|
|
||||||
|
bool daemonInitSuccess = daemon.init(1, argv);
|
||||||
|
if(!daemonInitSuccess)
|
||||||
|
{
|
||||||
|
return "Daemon init failed";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set webconsole language from application
|
||||||
|
i2p::i18n::SetLanguage(language);
|
||||||
|
|
||||||
|
daemon.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetDataDir(std::string jdataDir)
|
||||||
|
{
|
||||||
|
dataDir = jdataDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GetDataDir(void)
|
||||||
|
{
|
||||||
|
return dataDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetLanguage(std::string jlanguage)
|
||||||
|
{
|
||||||
|
language = jlanguage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
53
app/jni/DaemonAndroid.h
Normal file
53
app/jni/DaemonAndroid.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||||
|
*
|
||||||
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
|
*
|
||||||
|
* See full license text in LICENSE file at top of project tree
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DAEMON_ANDROID_H
|
||||||
|
#define DAEMON_ANDROID_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace i2p
|
||||||
|
{
|
||||||
|
namespace android
|
||||||
|
{
|
||||||
|
class DaemonAndroidImpl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
DaemonAndroidImpl ();
|
||||||
|
~DaemonAndroidImpl ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return success
|
||||||
|
*/
|
||||||
|
bool init (int argc, char* argv[]);
|
||||||
|
void start ();
|
||||||
|
void stop ();
|
||||||
|
void restart ();
|
||||||
|
|
||||||
|
void setDataDir (std::string path);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns "ok" if daemon init failed
|
||||||
|
* returns errinfo if daemon initialized and started okay
|
||||||
|
*/
|
||||||
|
std::string start ();
|
||||||
|
|
||||||
|
void stop ();
|
||||||
|
|
||||||
|
// set datadir received from jni
|
||||||
|
void SetDataDir (std::string jdataDir);
|
||||||
|
// get datadir
|
||||||
|
std::string GetDataDir (void);
|
||||||
|
// set webconsole language
|
||||||
|
void SetLanguage (std::string jlanguage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // DAEMON_ANDROID_H
|
141
app/jni/i2pd_android.cpp
Normal file
141
app/jni/i2pd_android.cpp
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||||
|
*
|
||||||
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
|
*
|
||||||
|
* See full license text in LICENSE file at top of project tree
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <jni.h>
|
||||||
|
#include "org_purplei2p_i2pd_I2PD_JNI.h"
|
||||||
|
#include "DaemonAndroid.h"
|
||||||
|
#include "Config.h"
|
||||||
|
#include "RouterContext.h"
|
||||||
|
#include "ClientContext.h"
|
||||||
|
#include "Transports.h"
|
||||||
|
#include "Tunnel.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 jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getDataDir
|
||||||
|
(JNIEnv *env, jclass clazz) {
|
||||||
|
return env->NewStringUTF(i2p::android::GetDataDir().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_startAcceptingTunnels
|
||||||
|
(JNIEnv *env, jclass clazz) {
|
||||||
|
i2p::context.SetAcceptsTunnels (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_reloadTunnelsConfigs
|
||||||
|
(JNIEnv *env, jclass clazz) {
|
||||||
|
i2p::client::context.ReloadConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_setDataDir
|
||||||
|
(JNIEnv *env, jclass clazz, jstring jdataDir) {
|
||||||
|
auto dataDir = env->GetStringUTFChars(jdataDir, NULL);
|
||||||
|
i2p::android::SetDataDir(dataDir);
|
||||||
|
env->ReleaseStringUTFChars(jdataDir, dataDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jint JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getTransitTunnelsCount
|
||||||
|
(JNIEnv *env, jclass clazz) {
|
||||||
|
return i2p::tunnel::tunnels.CountTransitTunnels();
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getWebConsAddr
|
||||||
|
(JNIEnv *env, jclass clazz) {
|
||||||
|
std::string httpAddr; i2p::config::GetOption("http.address", httpAddr);
|
||||||
|
uint16_t httpPort; i2p::config::GetOption("http.port", httpPort);
|
||||||
|
std::string result = "http://" + httpAddr + ":" + std::to_string(httpPort) + "/";
|
||||||
|
return env->NewStringUTF(result.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_setLanguage
|
||||||
|
(JNIEnv *env, jclass clazz, jstring jlanguage) {
|
||||||
|
auto language = env->GetStringUTFChars(jlanguage, NULL);
|
||||||
|
i2p::android::SetLanguage(language);
|
||||||
|
env->ReleaseStringUTFChars(jlanguage, language);
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getHTTPProxyState
|
||||||
|
(JNIEnv *, jclass) {
|
||||||
|
return i2p::client::context.GetHttpProxy () ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getSOCKSProxyState
|
||||||
|
(JNIEnv *, jclass) {
|
||||||
|
return i2p::client::context.GetSocksProxy() ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getBOBState
|
||||||
|
(JNIEnv *, jclass) {
|
||||||
|
return i2p::client::context.GetBOBCommandChannel() ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getSAMState
|
||||||
|
(JNIEnv *, jclass) {
|
||||||
|
return i2p::client::context.GetSAMBridge() ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getI2CPState
|
||||||
|
(JNIEnv *, jclass) {
|
||||||
|
return i2p::client::context.GetI2CPServer() ? true : false;
|
||||||
|
}
|
73
app/jni/org_purplei2p_i2pd_I2PD_JNI.h
Normal file
73
app/jni/org_purplei2p_i2pd_I2PD_JNI.h
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||||
|
*
|
||||||
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
|
*
|
||||||
|
* See full license text in LICENSE file at top of project tree
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
|
||||||
|
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_startAcceptingTunnels
|
||||||
|
(JNIEnv *, jclass);
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopAcceptingTunnels
|
||||||
|
(JNIEnv *, jclass);
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_reloadTunnelsConfigs
|
||||||
|
(JNIEnv *, jclass);
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_setDataDir
|
||||||
|
(JNIEnv *env, jclass clazz, jstring jdataDir);
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_setLanguage
|
||||||
|
(JNIEnv *env, jclass clazz, jstring jlanguage);
|
||||||
|
|
||||||
|
JNIEXPORT jint JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getTransitTunnelsCount
|
||||||
|
(JNIEnv *, jclass);
|
||||||
|
|
||||||
|
JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getWebConsAddr
|
||||||
|
(JNIEnv *, jclass);
|
||||||
|
|
||||||
|
JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getDataDir
|
||||||
|
(JNIEnv *, jclass);
|
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getHTTPProxyState
|
||||||
|
(JNIEnv *, jclass);
|
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getSOCKSProxyState
|
||||||
|
(JNIEnv *, jclass);
|
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getBOBState
|
||||||
|
(JNIEnv *, jclass);
|
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getSAMState
|
||||||
|
(JNIEnv *, jclass) ;
|
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getI2CPState
|
||||||
|
(JNIEnv *, jclass);
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_onNetworkStateChanged
|
||||||
|
(JNIEnv * env, jclass clazz, jboolean isConnected);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
@ -16,7 +16,6 @@
|
|||||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name=".appscope.App"
|
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:icon="@mipmap/logo"
|
android:icon="@mipmap/logo"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
package org.purplei2p.i2pd;
|
|
||||||
|
|
||||||
public interface AbstractProcess {
|
|
||||||
/** @param tr can be null
|
|
||||||
*/
|
|
||||||
void kill(Throwable tr);
|
|
||||||
}
|
|
@ -13,7 +13,6 @@ import java.util.Set;
|
|||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import android.annotation.TargetApi;
|
import android.annotation.TargetApi;
|
||||||
import android.content.Context;
|
|
||||||
import android.content.res.AssetManager;
|
import android.content.res.AssetManager;
|
||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
import android.net.Network;
|
import android.net.Network;
|
||||||
@ -68,25 +67,25 @@ public class DaemonWrapper {
|
|||||||
public synchronized void stopAcceptingTunnels() {
|
public synchronized void stopAcceptingTunnels() {
|
||||||
if (isStartedOkay()) {
|
if (isStartedOkay()) {
|
||||||
setState(State.gracefulShutdownInProgress);
|
setState(State.gracefulShutdownInProgress);
|
||||||
//I2PD_JNI.stopAcceptingTunnels();
|
I2PD_JNI.stopAcceptingTunnels();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void startAcceptingTunnels() {
|
public synchronized void startAcceptingTunnels() {
|
||||||
if (isStartedOkay()) {
|
if (isStartedOkay()) {
|
||||||
setState(State.startedOkay);
|
setState(State.startedOkay);
|
||||||
//I2PD_JNI.startAcceptingTunnels();
|
I2PD_JNI.startAcceptingTunnels();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void reloadTunnelsConfigs() {
|
public synchronized void reloadTunnelsConfigs() {
|
||||||
if (isStartedOkay()) {
|
if (isStartedOkay()) {
|
||||||
//I2PD_JNI.reloadTunnelsConfigs();
|
I2PD_JNI.reloadTunnelsConfigs();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getTransitTunnelsCount() {
|
public int getTransitTunnelsCount() {
|
||||||
return 0;//I2PD_JNI.getTransitTunnelsCount();
|
return I2PD_JNI.getTransitTunnelsCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum State {
|
public enum State {
|
||||||
@ -118,11 +117,11 @@ public class DaemonWrapper {
|
|||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DaemonWrapper(Context ctx, AssetManager assetManager, ConnectivityManager connectivityManager){
|
public DaemonWrapper(AssetManager assetManager, ConnectivityManager connectivityManager){
|
||||||
this.assetManager = assetManager;
|
this.assetManager = assetManager;
|
||||||
this.connectivityManager = connectivityManager;
|
this.connectivityManager = connectivityManager;
|
||||||
setState(State.starting);
|
setState(State.starting);
|
||||||
//startDaemon(ctx); //need to start when storage permissions to the datadir exist
|
startDaemon();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Throwable lastThrowable;
|
private Throwable lastThrowable;
|
||||||
@ -148,13 +147,11 @@ public class DaemonWrapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String getDataDir() { // for settings iniEditor
|
public static String getDataDir() { // for settings iniEditor
|
||||||
return i2pdDataDir;
|
return I2PD_JNI.getDataDir();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String i2pdDataDir;
|
|
||||||
|
|
||||||
public void changeDataDir(String dataDir, Boolean updateAssets) {
|
public void changeDataDir(String dataDir, Boolean updateAssets) {
|
||||||
i2pdDataDir=dataDir;
|
I2PD_JNI.setDataDir(dataDir);
|
||||||
if (updateAssets) processAssets();
|
if (updateAssets) processAssets();
|
||||||
//ToDo: move old dir to new dir?
|
//ToDo: move old dir to new dir?
|
||||||
}
|
}
|
||||||
@ -163,44 +160,44 @@ public class DaemonWrapper {
|
|||||||
return getState().isStartedOkay();
|
return getState().isStartedOkay();
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void stopDaemon(final Throwable throwable) {
|
public synchronized void stopDaemon() {
|
||||||
if (isStartedOkay()) {
|
if (isStartedOkay()) {
|
||||||
try {
|
try {
|
||||||
I2pdApi.stopDaemon(throwable);
|
I2PD_JNI.stopDaemon();
|
||||||
} catch (Throwable tr) {
|
} catch (Throwable tr) {
|
||||||
Log.e(TAG, "", tr);
|
Log.e(TAG, "", tr);
|
||||||
}
|
}
|
||||||
if (throwable != null) lastThrowable = throwable;
|
|
||||||
setState(State.stopped);
|
setState(State.stopped);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public synchronized void startDaemon() {
|
||||||
public synchronized void startDaemonIfStopped(Context ctx) {
|
if( getState() != State.stopped && getState() != State.starting ) return;
|
||||||
if (getState() == State.startedOkay) return;
|
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
synchronized(DaemonWrapper.this) {
|
try {
|
||||||
if (getState() == State.startedOkay) return;
|
processAssets();
|
||||||
try {
|
I2PD_JNI.loadLibraries();
|
||||||
processAssets();
|
//registerNetworkCallback();
|
||||||
//registerNetworkCallback();
|
} catch (Throwable tr) {
|
||||||
} catch (Throwable tr) {
|
lastThrowable = tr;
|
||||||
lastThrowable = tr;
|
setState(State.startFailed);
|
||||||
setState(State.startFailed);
|
return;
|
||||||
return;
|
}
|
||||||
}
|
try {
|
||||||
try {
|
synchronized (DaemonWrapper.this) {
|
||||||
String locale = getAppLocale();
|
I2PD_JNI.setDataDir(i2pdpath); // (Environment.getExternalStorageDirectory().getAbsolutePath() + "/i2pd");
|
||||||
Log.i(TAG, "setting webconsole language to " + locale);
|
|
||||||
|
|
||||||
daemonStartResult = I2pdApi.startDaemon(ctx, i2pdpath, locale, DaemonWrapper.this);
|
Log.i(TAG, "setting webconsole language to " + appLocale);
|
||||||
|
I2PD_JNI.setLanguage(appLocale);
|
||||||
|
|
||||||
|
daemonStartResult = I2PD_JNI.startDaemon();
|
||||||
if ("ok".equals(daemonStartResult)) {
|
if ("ok".equals(daemonStartResult)) {
|
||||||
setState(State.startedOkay);
|
setState(State.startedOkay);
|
||||||
} else
|
} else
|
||||||
setState(State.startFailed);
|
setState(State.startFailed);
|
||||||
} catch (Throwable tr) {
|
|
||||||
lastThrowable = tr;
|
|
||||||
setState(State.startFailed);
|
|
||||||
}
|
}
|
||||||
|
} catch (Throwable tr) {
|
||||||
|
lastThrowable = tr;
|
||||||
|
setState(State.startFailed);
|
||||||
}
|
}
|
||||||
}, "i2pdDaemonStart").start();
|
}, "i2pdDaemonStart").start();
|
||||||
}
|
}
|
||||||
@ -210,75 +207,71 @@ public class DaemonWrapper {
|
|||||||
String versionName = BuildConfig.VERSION_NAME; // here will be app version, like 2.XX.XX
|
String versionName = BuildConfig.VERSION_NAME; // here will be app version, like 2.XX.XX
|
||||||
StringBuilder text = new StringBuilder();
|
StringBuilder text = new StringBuilder();
|
||||||
Log.d(TAG, "checking assets");
|
Log.d(TAG, "checking assets");
|
||||||
try {
|
|
||||||
if (holderFile.exists()) {
|
if (holderFile.exists()) {
|
||||||
try { // if holder file exists, read assets version string
|
try { // if holder file exists, read assets version string
|
||||||
FileReader fileReader = new FileReader(holderFile);
|
FileReader fileReader = new FileReader(holderFile);
|
||||||
|
|
||||||
|
try {
|
||||||
|
BufferedReader br = new BufferedReader(fileReader);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
BufferedReader br = new BufferedReader(fileReader);
|
String line;
|
||||||
|
|
||||||
try {
|
while ((line = br.readLine()) != null) {
|
||||||
String line;
|
text.append(line);
|
||||||
|
|
||||||
while ((line = br.readLine()) != null) {
|
|
||||||
text.append(line);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
br.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.e(TAG, "", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} finally {
|
}finally {
|
||||||
try {
|
try {
|
||||||
fileReader.close();
|
br.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.e(TAG, "", e);
|
Log.e(TAG, "", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} finally {
|
||||||
Log.e(TAG, "", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if version differs from current app version or null, try to delete certificates folder
|
|
||||||
if (!text.toString().contains(versionName)) {
|
|
||||||
try {
|
|
||||||
boolean deleteResult = holderFile.delete();
|
|
||||||
if (!deleteResult)
|
|
||||||
Log.e(TAG, "holderFile.delete() returned " + deleteResult + ", absolute path='" + holderFile.getAbsolutePath() + "'");
|
|
||||||
File certPath = new File(i2pdpath, "certificates");
|
|
||||||
deleteRecursive(certPath);
|
|
||||||
|
|
||||||
// copy assets. If processed file exists, it won't be overwritten
|
|
||||||
copyAsset("addressbook");
|
|
||||||
copyAsset("certificates");
|
|
||||||
copyAsset("tunnels.d");
|
|
||||||
copyAsset("i2pd.conf");
|
|
||||||
copyAsset("tunnels.conf");
|
|
||||||
|
|
||||||
// update holder file about successful copying
|
|
||||||
FileWriter writer = new FileWriter(holderFile);
|
|
||||||
try {
|
try {
|
||||||
writer.append(versionName);
|
fileReader.close();
|
||||||
} finally {
|
} catch (IOException e) {
|
||||||
try {
|
Log.e(TAG, "", e);
|
||||||
writer.close();
|
}
|
||||||
} catch (IOException e) {
|
}
|
||||||
Log.e(TAG, "on writer close", e);
|
} catch (IOException e) {
|
||||||
}
|
Log.e(TAG, "", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if version differs from current app version or null, try to delete certificates folder
|
||||||
|
if (!text.toString().contains(versionName)) {
|
||||||
|
try {
|
||||||
|
boolean deleteResult = holderFile.delete();
|
||||||
|
if (!deleteResult)
|
||||||
|
Log.e(TAG, "holderFile.delete() returned " + deleteResult + ", absolute path='" + holderFile.getAbsolutePath() + "'");
|
||||||
|
File certPath = new File(i2pdpath, "certificates");
|
||||||
|
deleteRecursive(certPath);
|
||||||
|
|
||||||
|
// copy assets. If processed file exists, it won't be overwritten
|
||||||
|
copyAsset("addressbook");
|
||||||
|
copyAsset("certificates");
|
||||||
|
copyAsset("tunnels.d");
|
||||||
|
copyAsset("i2pd.conf");
|
||||||
|
copyAsset("tunnels.conf");
|
||||||
|
|
||||||
|
// update holder file about successful copying
|
||||||
|
FileWriter writer = new FileWriter(holderFile);
|
||||||
|
try {
|
||||||
|
writer.append(versionName);
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
writer.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.e(TAG,"on writer close", e);
|
||||||
}
|
}
|
||||||
} catch (Throwable tr) {
|
|
||||||
Log.e(TAG, "on assets copying", tr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}catch(Throwable tr) {
|
catch (Throwable tr)
|
||||||
if(tr.getMessage().contains("Permission denied")) {
|
{
|
||||||
Log.e(TAG, "Permission denied on assets copying", tr);
|
Log.e(TAG,"on assets copying", tr);
|
||||||
}
|
}
|
||||||
throw new RuntimeException(tr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -378,18 +371,15 @@ public class DaemonWrapper {
|
|||||||
@Override
|
@Override
|
||||||
public void onAvailable(Network network) {
|
public void onAvailable(Network network) {
|
||||||
super.onAvailable(network);
|
super.onAvailable(network);
|
||||||
//I2PD_JNI.onNetworkStateChanged(true);
|
I2PD_JNI.onNetworkStateChanged(true);
|
||||||
Log.d(TAG, "NetworkCallback.onAvailable");
|
Log.d(TAG, "NetworkCallback.onAvailable");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLost(Network network) {
|
public void onLost(Network network) {
|
||||||
super.onLost(network);
|
super.onLost(network);
|
||||||
//I2PD_JNI.onNetworkStateChanged(false);
|
I2PD_JNI.onNetworkStateChanged(false);
|
||||||
Log.d(TAG, " NetworkCallback.onLost");
|
Log.d(TAG, " NetworkCallback.onLost");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private String getAppLocale() {
|
|
||||||
return Locale.getDefault().getDisplayLanguage(Locale.ENGLISH).toLowerCase(); // lower-case system language (like "english")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -19,11 +19,6 @@ import android.util.Log;
|
|||||||
public class ForegroundService extends Service {
|
public class ForegroundService extends Service {
|
||||||
private static final String TAG = "FgService";
|
private static final String TAG = "FgService";
|
||||||
private volatile boolean shown;
|
private volatile boolean shown;
|
||||||
|
|
||||||
public static ForegroundService getInstance() {
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ForegroundService instance;
|
private static ForegroundService instance;
|
||||||
private static volatile DaemonWrapper daemon;
|
private static volatile DaemonWrapper daemon;
|
||||||
private static final Object initDeinitLock = new Object();
|
private static final Object initDeinitLock = new Object();
|
||||||
@ -97,10 +92,6 @@ public class ForegroundService extends Service {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void stop() {
|
|
||||||
cancelNotification();
|
cancelNotification();
|
||||||
deinitCheck();
|
deinitCheck();
|
||||||
instance = null;
|
instance = null;
|
||||||
|
@ -38,8 +38,6 @@ import androidx.core.content.ContextCompat;
|
|||||||
|
|
||||||
import static android.provider.Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS;
|
import static android.provider.Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS;
|
||||||
|
|
||||||
import org.purplei2p.i2pd.appscope.App;
|
|
||||||
|
|
||||||
public class I2PDActivity extends Activity {
|
public class I2PDActivity extends Activity {
|
||||||
private static final String TAG = "i2pdActvt";
|
private static final String TAG = "i2pdActvt";
|
||||||
private static final int MY_PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE = 1;
|
private static final int MY_PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE = 1;
|
||||||
@ -47,12 +45,14 @@ public class I2PDActivity extends Activity {
|
|||||||
public static final String PACKAGE_URI_SCHEME = "package:";
|
public static final String PACKAGE_URI_SCHEME = "package:";
|
||||||
|
|
||||||
private TextView textView;
|
private TextView textView;
|
||||||
/*private CheckBox HTTPProxyState;
|
private CheckBox HTTPProxyState;
|
||||||
private CheckBox SOCKSProxyState;
|
private CheckBox SOCKSProxyState;
|
||||||
private CheckBox BOBState;
|
private CheckBox BOBState;
|
||||||
private CheckBox SAMState;
|
private CheckBox SAMState;
|
||||||
private CheckBox I2CPState;
|
private CheckBox I2CPState;
|
||||||
*/
|
|
||||||
|
|
||||||
|
private static volatile DaemonWrapper daemon;
|
||||||
|
|
||||||
private final DaemonWrapper.StateUpdateListener daemonStateUpdatedListener = new DaemonWrapper.StateUpdateListener() {
|
private final DaemonWrapper.StateUpdateListener daemonStateUpdatedListener = new DaemonWrapper.StateUpdateListener() {
|
||||||
@Override
|
@Override
|
||||||
@ -60,10 +60,6 @@ public class I2PDActivity extends Activity {
|
|||||||
updateStatusText();
|
updateStatusText();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private DaemonWrapper getDaemon() {
|
|
||||||
return App.getDaemonWrapper();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateStatusText() {
|
private void updateStatusText() {
|
||||||
runOnUiThread(() -> {
|
runOnUiThread(() -> {
|
||||||
@ -71,25 +67,23 @@ public class I2PDActivity extends Activity {
|
|||||||
if (textView == null)
|
if (textView == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Throwable tr = getDaemon().getLastThrowable();
|
Throwable tr = daemon.getLastThrowable();
|
||||||
if (tr != null) {
|
if (tr != null) {
|
||||||
textView.setText(throwableToString(tr));
|
textView.setText(throwableToString(tr));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DaemonWrapper.State state = getDaemon().getState();
|
DaemonWrapper.State state = daemon.getState();
|
||||||
|
|
||||||
if (getDaemon().isStartedOkay()) {
|
if (daemon.isStartedOkay()) {
|
||||||
/*
|
|
||||||
HTTPProxyState.setChecked(I2PD_JNI.getHTTPProxyState());
|
HTTPProxyState.setChecked(I2PD_JNI.getHTTPProxyState());
|
||||||
SOCKSProxyState.setChecked(I2PD_JNI.getSOCKSProxyState());
|
SOCKSProxyState.setChecked(I2PD_JNI.getSOCKSProxyState());
|
||||||
BOBState.setChecked(I2PD_JNI.getBOBState());
|
BOBState.setChecked(I2PD_JNI.getBOBState());
|
||||||
SAMState.setChecked(I2PD_JNI.getSAMState());
|
SAMState.setChecked(I2PD_JNI.getSAMState());
|
||||||
I2CPState.setChecked(I2PD_JNI.getI2CPState());
|
I2CPState.setChecked(I2PD_JNI.getI2CPState());
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String startResultStr = DaemonWrapper.State.startFailed==state ? String.format(": %s", getDaemon().getDaemonStartResult()) : "";
|
String startResultStr = DaemonWrapper.State.startFailed.equals(state) ? String.format(": %s", daemon.getDaemonStartResult()) : "";
|
||||||
String graceStr = DaemonWrapper.State.gracefulShutdownInProgress.equals(state) ? String.format(": %s %s", formatGraceTimeRemaining(), getText(R.string.remaining)) : "";
|
String graceStr = DaemonWrapper.State.gracefulShutdownInProgress.equals(state) ? String.format(": %s %s", formatGraceTimeRemaining(), getText(R.string.remaining)) : "";
|
||||||
textView.setText(String.format("%s%s%s", getText(state.getStatusStringResourceId()), startResultStr, graceStr));
|
textView.setText(String.format("%s%s%s", getText(state.getStatusStringResourceId()), startResultStr, graceStr));
|
||||||
} catch (Throwable tr) {
|
} catch (Throwable tr) {
|
||||||
@ -119,21 +113,20 @@ public class I2PDActivity extends Activity {
|
|||||||
setContentView(R.layout.activity_main);
|
setContentView(R.layout.activity_main);
|
||||||
startService(new Intent(this, ForegroundService.class));
|
startService(new Intent(this, ForegroundService.class));
|
||||||
textView = (TextView) findViewById(R.id.appStatusText);
|
textView = (TextView) findViewById(R.id.appStatusText);
|
||||||
/*
|
|
||||||
HTTPProxyState = (CheckBox) findViewById(R.id.service_httpproxy_box);
|
HTTPProxyState = (CheckBox) findViewById(R.id.service_httpproxy_box);
|
||||||
SOCKSProxyState = (CheckBox) findViewById(R.id.service_socksproxy_box);
|
SOCKSProxyState = (CheckBox) findViewById(R.id.service_socksproxy_box);
|
||||||
BOBState = (CheckBox) findViewById(R.id.service_bob_box);
|
BOBState = (CheckBox) findViewById(R.id.service_bob_box);
|
||||||
SAMState = (CheckBox) findViewById(R.id.service_sam_box);
|
SAMState = (CheckBox) findViewById(R.id.service_sam_box);
|
||||||
I2CPState = (CheckBox) findViewById(R.id.service_i2cp_box);*/
|
I2CPState = (CheckBox) findViewById(R.id.service_i2cp_box);
|
||||||
|
|
||||||
/*if (getDaemon() == null) {
|
if (daemon == null) {
|
||||||
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
|
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||||
getDaemon() = new getDaemon()Wrapper(getAssets(), connectivityManager);
|
daemon = new DaemonWrapper(getAssets(), connectivityManager);
|
||||||
}
|
}
|
||||||
ForegroundService.init(getDaemon());
|
ForegroundService.init(daemon);
|
||||||
|
|
||||||
*/
|
daemon.addStateChangeListener(daemonStateUpdatedListener);
|
||||||
//getDaemon()StateUpdatedListener.getDaemon()StateUpdate(getDaemon()Wrapper.State.uninitialized, App.getgetDaemon()Wrapper().getState());
|
daemonStateUpdatedListener.daemonStateUpdate(DaemonWrapper.State.uninitialized, daemon.getState());
|
||||||
|
|
||||||
// request permissions
|
// request permissions
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||||
@ -149,11 +142,6 @@ public class I2PDActivity extends Activity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//here, we might have datadir access permissions,
|
|
||||||
// it's maybe safe to call daemon start which copies i2pd assets
|
|
||||||
getDaemon().startDaemonIfStopped(getApplicationContext());
|
|
||||||
getDaemon().addStateChangeListener(daemonStateUpdatedListener);
|
|
||||||
updateStatusText();
|
|
||||||
doBindService();
|
doBindService();
|
||||||
|
|
||||||
final Timer gracefulQuitTimer = getGracefulQuitTimer();
|
final Timer gracefulQuitTimer = getGracefulQuitTimer();
|
||||||
@ -173,7 +161,7 @@ public class I2PDActivity extends Activity {
|
|||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
textView = null;
|
textView = null;
|
||||||
ForegroundService.deinit();
|
ForegroundService.deinit();
|
||||||
getDaemon().removeStateChangeListener(daemonStateUpdatedListener);
|
daemon.removeStateChangeListener(daemonStateUpdatedListener);
|
||||||
//cancelGracefulStop0();
|
//cancelGracefulStop0();
|
||||||
try {
|
try {
|
||||||
doUnbindService();
|
doUnbindService();
|
||||||
@ -306,15 +294,15 @@ public class I2PDActivity extends Activity {
|
|||||||
onActionBatteryOptimizations();
|
onActionBatteryOptimizations();
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
/* case R.id.action_reload_tunnels_config:
|
case R.id.action_reload_tunnels_config:
|
||||||
onReloadTunnelsConfig();
|
onReloadTunnelsConfig();
|
||||||
return true;*/
|
return true;
|
||||||
|
|
||||||
case R.id.action_start_webview:
|
case R.id.action_start_webview:
|
||||||
if(getDaemon().isStartedOkay())
|
if(daemon.isStartedOkay())
|
||||||
startActivity(new Intent(getApplicationContext(), WebConsoleActivity.class));
|
startActivity(new Intent(getApplicationContext(), WebConsoleActivity.class));
|
||||||
else
|
else
|
||||||
Toast.makeText(this,"I2Pd not started!", Toast.LENGTH_SHORT).show();
|
Toast.makeText(this,"I2Pd not was started!", Toast.LENGTH_SHORT).show();
|
||||||
return true;
|
return true;
|
||||||
case R.id.action_settings:
|
case R.id.action_settings:
|
||||||
startActivity(new Intent(getApplicationContext(), SettingsActivity.class));
|
startActivity(new Intent(getApplicationContext(), SettingsActivity.class));
|
||||||
@ -337,7 +325,7 @@ public class I2PDActivity extends Activity {
|
|||||||
|
|
||||||
private void onReloadTunnelsConfig() {
|
private void onReloadTunnelsConfig() {
|
||||||
Log.i(TAG, "reloading tunnels");
|
Log.i(TAG, "reloading tunnels");
|
||||||
getDaemon().reloadTunnelsConfigs();
|
daemon.reloadTunnelsConfigs();
|
||||||
Toast.makeText(this, R.string.tunnels_reloading, Toast.LENGTH_SHORT).show();
|
Toast.makeText(this, R.string.tunnels_reloading, Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -347,7 +335,7 @@ public class I2PDActivity extends Activity {
|
|||||||
textView.setText(getText(R.string.stopping));
|
textView.setText(getText(R.string.stopping));
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
try {
|
try {
|
||||||
getDaemon().stopDaemon(null);
|
daemon.stopDaemon();
|
||||||
} catch (Throwable tr) {
|
} catch (Throwable tr) {
|
||||||
Log.e(TAG, "", tr);
|
Log.e(TAG, "", tr);
|
||||||
}
|
}
|
||||||
@ -358,7 +346,7 @@ public class I2PDActivity extends Activity {
|
|||||||
private static volatile Timer gracefulQuitTimer;
|
private static volatile Timer gracefulQuitTimer;
|
||||||
|
|
||||||
private void i2pdGracefulStop() {
|
private void i2pdGracefulStop() {
|
||||||
if (getDaemon().getState() == DaemonWrapper.State.stopped) {
|
if (daemon.getState() == DaemonWrapper.State.stopped) {
|
||||||
Toast.makeText(this, R.string.already_stopped, Toast.LENGTH_SHORT).show();
|
Toast.makeText(this, R.string.already_stopped, Toast.LENGTH_SHORT).show();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -370,8 +358,8 @@ public class I2PDActivity extends Activity {
|
|||||||
Toast.makeText(this, R.string.graceful_stop_is_in_progress, Toast.LENGTH_SHORT).show();
|
Toast.makeText(this, R.string.graceful_stop_is_in_progress, Toast.LENGTH_SHORT).show();
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
try {
|
try {
|
||||||
if (getDaemon().isStartedOkay()) {
|
if (daemon.isStartedOkay()) {
|
||||||
getDaemon().stopAcceptingTunnels();
|
daemon.stopAcceptingTunnels();
|
||||||
long gracefulStopAtMillis;
|
long gracefulStopAtMillis;
|
||||||
synchronized (graceStartedMillis_LOCK) {
|
synchronized (graceStartedMillis_LOCK) {
|
||||||
graceStartedMillis = System.currentTimeMillis();
|
graceStartedMillis = System.currentTimeMillis();
|
||||||
@ -392,8 +380,8 @@ public class I2PDActivity extends Activity {
|
|||||||
Log.i(TAG, "canceling graceful stop");
|
Log.i(TAG, "canceling graceful stop");
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
try {
|
try {
|
||||||
if (getDaemon().isStartedOkay()) {
|
if (daemon.isStartedOkay()) {
|
||||||
getDaemon().startAcceptingTunnels();
|
daemon.startAcceptingTunnels();
|
||||||
runOnUiThread(() -> Toast.makeText(this, R.string.shutdown_canceled, Toast.LENGTH_SHORT).show());
|
runOnUiThread(() -> Toast.makeText(this, R.string.shutdown_canceled, Toast.LENGTH_SHORT).show());
|
||||||
} else
|
} else
|
||||||
i2pdStop();
|
i2pdStop();
|
||||||
@ -407,7 +395,7 @@ public class I2PDActivity extends Activity {
|
|||||||
if (gracefulQuitTimerOld != null)
|
if (gracefulQuitTimerOld != null)
|
||||||
gracefulQuitTimerOld.cancel();
|
gracefulQuitTimerOld.cancel();
|
||||||
|
|
||||||
if (getDaemon().getTransitTunnelsCount() <= 0) { // no tunnels left
|
if (daemon.getTransitTunnelsCount() <= 0) { // no tunnels left
|
||||||
Log.i(TAG, "no transit tunnels left, stopping");
|
Log.i(TAG, "no transit tunnels left, stopping");
|
||||||
i2pdStop();
|
i2pdStop();
|
||||||
return;
|
return;
|
||||||
@ -519,7 +507,7 @@ public class I2PDActivity extends Activity {
|
|||||||
Log.e(TAG, "", tr);
|
Log.e(TAG, "", tr);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
((App)getApplication()).quit();
|
daemon.stopDaemon();
|
||||||
} catch (Throwable tr) {
|
} catch (Throwable tr) {
|
||||||
Log.e(TAG, "", tr);
|
Log.e(TAG, "", tr);
|
||||||
}
|
}
|
||||||
|
35
app/src/main/java/org/purplei2p/i2pd/I2PD_JNI.java
Normal file
35
app/src/main/java/org/purplei2p/i2pd/I2PD_JNI.java
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package org.purplei2p.i2pd;
|
||||||
|
|
||||||
|
public class I2PD_JNI {
|
||||||
|
public static native String getABICompiledWith();
|
||||||
|
|
||||||
|
public static void loadLibraries() {
|
||||||
|
System.loadLibrary("i2pd");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns error info if failed
|
||||||
|
* returns "ok" if daemon initialized and started okay
|
||||||
|
*/
|
||||||
|
public static native String startDaemon();
|
||||||
|
public static native void stopDaemon();
|
||||||
|
|
||||||
|
public static native void startAcceptingTunnels();
|
||||||
|
public static native void stopAcceptingTunnels();
|
||||||
|
public static native void reloadTunnelsConfigs();
|
||||||
|
|
||||||
|
public static native void setDataDir(String jdataDir);
|
||||||
|
public static native void setLanguage(String jlanguage);
|
||||||
|
|
||||||
|
public static native int getTransitTunnelsCount();
|
||||||
|
public static native String getWebConsAddr();
|
||||||
|
public static native String getDataDir();
|
||||||
|
|
||||||
|
public static native boolean getHTTPProxyState();
|
||||||
|
public static native boolean getSOCKSProxyState();
|
||||||
|
public static native boolean getBOBState();
|
||||||
|
public static native boolean getSAMState();
|
||||||
|
public static native boolean getI2CPState();
|
||||||
|
|
||||||
|
public static native void onNetworkStateChanged(boolean isConnected);
|
||||||
|
}
|
@ -1,154 +0,0 @@
|
|||||||
package org.purplei2p.i2pd;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
|
|
||||||
/** i2pd process API calls via TCP between the Android Java app and i2pd C++-only process.
|
|
||||||
* TODO
|
|
||||||
*/
|
|
||||||
public class I2pdApi {
|
|
||||||
private static String dataDir;
|
|
||||||
private static AbstractProcess i2pdProcess;
|
|
||||||
private static final String TAG = "I2pdApi";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* returns error info if failed
|
|
||||||
* returns "ok" if daemon initialized and started okay
|
|
||||||
*/
|
|
||||||
public static String startDaemon(final Context ctx, final String dataDir, String ignoredLanguage, final DaemonWrapper daemonWrapper){
|
|
||||||
try {
|
|
||||||
i2pdProcess = null;
|
|
||||||
I2pdApi.dataDir = dataDir;
|
|
||||||
File pidFile = new File(dataDir, "i2pd.pid");
|
|
||||||
Log.i(TAG,"Launching an i2pd process");
|
|
||||||
final Process p = Runtime.getRuntime().exec(new String[]{
|
|
||||||
"/system/bin/sh",
|
|
||||||
"-c",
|
|
||||||
"ulimit -c unlimited && "+
|
|
||||||
ctx.getApplicationInfo().nativeLibraryDir +
|
|
||||||
"/libi2pd.so --datadir=" + dataDir +
|
|
||||||
" --pidfile=" + pidFile.getAbsolutePath() +
|
|
||||||
" > "+dataDir+"/s.log 2>&1"
|
|
||||||
});
|
|
||||||
i2pdProcess = (Throwable tr) -> {
|
|
||||||
try {
|
|
||||||
if (tr != null)
|
|
||||||
Log.e(TAG, "destroying the subprocess \"i2pd\", reason: " + tr, tr);
|
|
||||||
else
|
|
||||||
Log.e(TAG, "destroying the subprocess \"i2pd\", reason: null");
|
|
||||||
p.destroy();
|
|
||||||
} catch (Throwable tr2) {
|
|
||||||
Log.e(TAG, "", tr2);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
new Thread(() -> {
|
|
||||||
try {
|
|
||||||
try (BufferedInputStream bis = new BufferedInputStream(p.getInputStream())) {
|
|
||||||
try (InputStreamReader sr = new InputStreamReader(bis)) {
|
|
||||||
try (BufferedReader r = new BufferedReader(sr)) {
|
|
||||||
while (true) {
|
|
||||||
String s = r.readLine();
|
|
||||||
if (s == null) break;
|
|
||||||
Log.i(TAG, s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Throwable tr) {
|
|
||||||
Log.e(TAG, "", tr);
|
|
||||||
}
|
|
||||||
}, "i2pd-stdout").start();
|
|
||||||
new Thread(() -> {
|
|
||||||
try {
|
|
||||||
try (BufferedInputStream bis = new BufferedInputStream(p.getErrorStream())) {
|
|
||||||
try (InputStreamReader sr = new InputStreamReader(bis)) {
|
|
||||||
try (BufferedReader r = new BufferedReader(sr)) {
|
|
||||||
while (true) {
|
|
||||||
String s = r.readLine();
|
|
||||||
if (s == null) break;
|
|
||||||
Log.i(TAG, s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Throwable tr) {
|
|
||||||
Log.e(TAG, "", tr);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
p.waitFor();
|
|
||||||
} catch (Throwable tr) {
|
|
||||||
Log.e(TAG, "", tr);
|
|
||||||
}
|
|
||||||
final int errorLevel = p.exitValue();
|
|
||||||
Log.i(TAG, "i2pd process exit code: " + errorLevel);
|
|
||||||
final Throwable trReason = new Throwable("subprocess \"i2pd\" exited with exit code " + errorLevel);
|
|
||||||
try {
|
|
||||||
stopDaemon(trReason);
|
|
||||||
Log.i(TAG, "stopDaemon completed");
|
|
||||||
} catch (Throwable tr) {
|
|
||||||
Log.e(TAG, "Called stopDaemon, got exception", tr);
|
|
||||||
}
|
|
||||||
new Thread(() -> {
|
|
||||||
try {
|
|
||||||
daemonWrapper.stopDaemon(trReason);
|
|
||||||
Log.i(TAG, "daemonWrapper.stopDaemon completed");
|
|
||||||
} catch (Throwable tr) {
|
|
||||||
Log.e(TAG, "Called daemonWrapper.stopDaemon, got exception", tr);
|
|
||||||
}
|
|
||||||
}, "stop the daemonWrapper thread").start();
|
|
||||||
}, "i2pd-stderr").start();
|
|
||||||
new Thread(() -> {
|
|
||||||
try {
|
|
||||||
// try (BufferedOutputStream bos = new BufferedOutputStream(p.getOutputStream())) {
|
|
||||||
// try (OutputStreamWriter sr = new OutputStreamWriter(bos)) {
|
|
||||||
// try (BufferedWriter r = new BufferedWriter(sr)) {
|
|
||||||
while (true) {
|
|
||||||
synchronized (Thread.currentThread()) {
|
|
||||||
Thread.currentThread().wait(100);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
} catch (Throwable tr) {
|
|
||||||
Log.e(TAG, "", tr);
|
|
||||||
}
|
|
||||||
}, "i2pd-stdin").start();
|
|
||||||
return "ok";
|
|
||||||
} catch (Throwable tr) {
|
|
||||||
Log.e(TAG, "", tr);
|
|
||||||
return "Error in exec(): " + tr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void stopDaemon(Throwable tr){
|
|
||||||
AbstractProcess p = i2pdProcess;
|
|
||||||
if (p != null) {
|
|
||||||
p.kill(tr);
|
|
||||||
i2pdProcess = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void startAcceptingTunnels(){}
|
|
||||||
public static void stopAcceptingTunnels(){}
|
|
||||||
public static void reloadTunnelsConfigs(){}
|
|
||||||
|
|
||||||
public static int getTransitTunnelsCount(){return -1;}
|
|
||||||
public static String getWebConsAddr(){return "";}
|
|
||||||
public static String getDataDir() {
|
|
||||||
return dataDir;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean getHTTPProxyState(){return false;}
|
|
||||||
public static boolean getSOCKSProxyState(){return false;}
|
|
||||||
public static boolean getBOBState(){return false;}
|
|
||||||
public static boolean getSAMState(){return false;}
|
|
||||||
public static boolean getI2CPState(){return false;}
|
|
||||||
|
|
||||||
public static void onNetworkStateChanged(boolean isConnected){}
|
|
||||||
}
|
|
@ -19,7 +19,7 @@ public class NetworkStateChangeReceiver extends BroadcastReceiver {
|
|||||||
NetworkInfo activeNetworkInfo = cm.getActiveNetworkInfo();
|
NetworkInfo activeNetworkInfo = cm.getActiveNetworkInfo();
|
||||||
boolean isConnected = activeNetworkInfo != null && activeNetworkInfo.isConnected();
|
boolean isConnected = activeNetworkInfo != null && activeNetworkInfo.isConnected();
|
||||||
|
|
||||||
//I2PD_JNI.onNetworkStateChanged(isConnected);
|
I2PD_JNI.onNetworkStateChanged(isConnected);
|
||||||
} catch (Throwable tr) {
|
} catch (Throwable tr) {
|
||||||
Log.e(TAG, "", tr);
|
Log.e(TAG, "", tr);
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ public class WebConsoleActivity extends Activity {
|
|||||||
final WebSettings webSettings = webView.getSettings();
|
final WebSettings webSettings = webView.getSettings();
|
||||||
webSettings.setBuiltInZoomControls(true);
|
webSettings.setBuiltInZoomControls(true);
|
||||||
webSettings.setJavaScriptEnabled(false);
|
webSettings.setJavaScriptEnabled(false);
|
||||||
webView.loadUrl("http://localhost:7070/"/*I2PD_JNI.getWebConsAddr()*/);
|
webView.loadUrl(I2PD_JNI.getWebConsAddr());
|
||||||
|
|
||||||
swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe);
|
swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe);
|
||||||
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
|
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
|
||||||
|
@ -1,126 +0,0 @@
|
|||||||
package org.purplei2p.i2pd.appscope;
|
|
||||||
|
|
||||||
import android.app.Application;
|
|
||||||
import android.content.ComponentName;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.ServiceConnection;
|
|
||||||
import android.net.ConnectivityManager;
|
|
||||||
import android.os.IBinder;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import org.purplei2p.i2pd.BuildConfig;
|
|
||||||
import org.purplei2p.i2pd.I2PDActivity;
|
|
||||||
import org.purplei2p.i2pd.*;
|
|
||||||
|
|
||||||
public class App extends Application {
|
|
||||||
private static final String TAG = "i2pd.app";
|
|
||||||
|
|
||||||
//private static final I2PD_JNI jniHolder = new I2PD_JNI();
|
|
||||||
|
|
||||||
private static volatile DaemonWrapper daemonWrapper;
|
|
||||||
private String versionName;
|
|
||||||
|
|
||||||
private static volatile boolean mIsBound;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public synchronized static DaemonWrapper getDaemonWrapper() {
|
|
||||||
return daemonWrapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate() {
|
|
||||||
super.onCreate();
|
|
||||||
synchronized (this) {
|
|
||||||
if (getDaemonWrapper() == null) {
|
|
||||||
createDaemonWrapper();
|
|
||||||
}
|
|
||||||
versionName = BuildConfig.VERSION_NAME;
|
|
||||||
doBindService();
|
|
||||||
startService(new Intent(this, ForegroundService.class));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createDaemonWrapper() {
|
|
||||||
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(
|
|
||||||
Context.CONNECTIVITY_SERVICE);
|
|
||||||
daemonWrapper = new DaemonWrapper(getApplicationContext(), getAssets(), connectivityManager);
|
|
||||||
ForegroundService.init(daemonWrapper);
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized void doBindService() {
|
|
||||||
if (mIsBound)
|
|
||||||
return;
|
|
||||||
// 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 synchronized void doUnbindService() {
|
|
||||||
if (mIsBound) {
|
|
||||||
// Detach our existing connection.
|
|
||||||
unbindService(mConnection);
|
|
||||||
mIsBound = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onTerminate() {
|
|
||||||
quit();
|
|
||||||
super.onTerminate();
|
|
||||||
}
|
|
||||||
|
|
||||||
private final 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();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public synchronized void quit() {
|
|
||||||
try {
|
|
||||||
if(daemonWrapper!=null)daemonWrapper.stopDaemon(null);
|
|
||||||
} catch (Throwable tr) {
|
|
||||||
Log.e(TAG, "", tr);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
doUnbindService();
|
|
||||||
} catch (IllegalArgumentException ex) {
|
|
||||||
Log.e(TAG, "throwable caught and ignored", ex);
|
|
||||||
if (ex.getMessage().startsWith("Service not registered: " + I2PDActivity.class.getName())) {
|
|
||||||
Log.i(TAG, "Service not registered exception seems to be normal, not a bug it seems.");
|
|
||||||
}
|
|
||||||
} catch (Throwable tr) {
|
|
||||||
Log.e(TAG, "throwable caught and ignored", tr);
|
|
||||||
}
|
|
||||||
try{
|
|
||||||
ForegroundService fs = ForegroundService.getInstance();
|
|
||||||
if(fs!=null)fs.stop();
|
|
||||||
}catch(Throwable tr) {
|
|
||||||
Log.e(TAG, "", tr);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -58,7 +58,7 @@
|
|||||||
<Space
|
<Space
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="@dimen/margin_medium" />
|
android:layout_height="@dimen/margin_medium" />
|
||||||
<!--
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/textView"
|
android:id="@+id/textView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -149,7 +149,7 @@
|
|||||||
android:textColor="#DFDFDF" />
|
android:textColor="#DFDFDF" />
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableLayout>
|
</TableLayout>
|
||||||
-->
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
@ -15,10 +15,10 @@
|
|||||||
android:id="@+id/action_start_webview"
|
android:id="@+id/action_start_webview"
|
||||||
android:orderInCategory="96"
|
android:orderInCategory="96"
|
||||||
android:title="@string/action_start_webview" />
|
android:title="@string/action_start_webview" />
|
||||||
<!--<item
|
<item
|
||||||
android:id="@+id/action_reload_tunnels_config"
|
android:id="@+id/action_reload_tunnels_config"
|
||||||
android:orderInCategory="97"
|
android:orderInCategory="97"
|
||||||
android:title="@string/action_reload_tunnels_config" />-->
|
android:title="@string/action_reload_tunnels_config" />
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_graceful_stop"
|
android:id="@+id/action_graceful_stop"
|
||||||
android:orderInCategory="98"
|
android:orderInCategory="98"
|
||||||
|
@ -27,7 +27,7 @@ help()
|
|||||||
{
|
{
|
||||||
echo "Syntax: $(basename "$SOURCE") [-m|d|s|h|v]"
|
echo "Syntax: $(basename "$SOURCE") [-m|d|s|h|v]"
|
||||||
echo "Options:"
|
echo "Options:"
|
||||||
echo "m Rename binaries as libraries."
|
echo "b Build binary."
|
||||||
echo "d Debug build."
|
echo "d Debug build."
|
||||||
echo "s Strip binaries."
|
echo "s Strip binaries."
|
||||||
echo "x Skip libraries rebuild."
|
echo "x Skip libraries rebuild."
|
||||||
@ -36,13 +36,13 @@ help()
|
|||||||
echo
|
echo
|
||||||
}
|
}
|
||||||
|
|
||||||
while getopts ":dmsvxh" option; do
|
while getopts ":dbsvxh" option; do
|
||||||
case $option in
|
case $option in
|
||||||
d) # debug build
|
d) # debug build
|
||||||
_NDK_OPTS="$_NDK_OPTS NDK_DEBUG=1"
|
_NDK_OPTS="$_NDK_OPTS NDK_DEBUG=1"
|
||||||
;;
|
;;
|
||||||
m) # make module
|
b) # build binary
|
||||||
_MODULE=1
|
_BINARY=1
|
||||||
;;
|
;;
|
||||||
s) # strip binaries
|
s) # strip binaries
|
||||||
_STRIP=1
|
_STRIP=1
|
||||||
@ -74,8 +74,10 @@ if [ -z "$_SKIP_LIBS" ]; then
|
|||||||
./build_miniupnpc.sh
|
./build_miniupnpc.sh
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Building i2pd..."
|
if [ ! -z "$_BINARY" ]; then
|
||||||
$ANDROID_NDK_HOME/ndk-build $_NDK_OPTS
|
echo "Building i2pd..."
|
||||||
|
$ANDROID_NDK_HOME/ndk-build $_NDK_OPTS
|
||||||
|
fi
|
||||||
|
|
||||||
echo "Processing binaries (if requested)..."
|
echo "Processing binaries (if requested)..."
|
||||||
pushd $DIR/../libs > /dev/null
|
pushd $DIR/../libs > /dev/null
|
||||||
|
0
binary/libs/.gitkeep
Normal file
0
binary/libs/.gitkeep
Normal file
2
fastlane/metadata/android/en-US/changelogs/2530010.txt
Normal file
2
fastlane/metadata/android/en-US/changelogs/2530010.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
* Updated codebase to 2.53.1
|
||||||
|
* Revert to usage of the JNI
|
Loading…
x
Reference in New Issue
Block a user