mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-02-07 07:44:13 +00:00
[android] build libi2pd staticly, add update strings, fix messages
This commit is contained in:
parent
65c2c7d80b
commit
d7609f119c
@ -28,15 +28,17 @@ android {
|
|||||||
applicationId "org.purplei2p.i2pd"
|
applicationId "org.purplei2p.i2pd"
|
||||||
targetSdkVersion 28
|
targetSdkVersion 28
|
||||||
minSdkVersion 14
|
minSdkVersion 14
|
||||||
versionCode 1
|
versionCode 2220
|
||||||
versionName "2.22.0"
|
versionName "2.22.0"
|
||||||
ndk {
|
ndk {
|
||||||
abiFilters 'armeabi-v7a'
|
abiFilters 'armeabi-v7a'
|
||||||
abiFilters 'x86'
|
abiFilters 'x86'
|
||||||
|
//abiFilters 'arm64-v8a'
|
||||||
|
//abiFilters 'x86_64'
|
||||||
}
|
}
|
||||||
externalNativeBuild {
|
externalNativeBuild {
|
||||||
ndkBuild {
|
ndkBuild {
|
||||||
arguments "-j4"
|
arguments "-j3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -49,6 +51,15 @@ android {
|
|||||||
assets.srcDirs = ['assets']
|
assets.srcDirs = ['assets']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
splits {
|
||||||
|
abi {
|
||||||
|
// change that to true if you need splitted apk
|
||||||
|
enable false
|
||||||
|
reset()
|
||||||
|
include "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
|
||||||
|
universalApk true
|
||||||
|
}
|
||||||
|
}
|
||||||
signingConfigs {
|
signingConfigs {
|
||||||
orignal {
|
orignal {
|
||||||
storeFile file("i2pdapk.jks")
|
storeFile file("i2pdapk.jks")
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
APP_ABI := armeabi-v7a x86
|
#APP_ABI := armeabi-v7a x86
|
||||||
APP_PLATFORM := android-14
|
#APP_PLATFORM := android-14
|
||||||
|
|
||||||
# ABI arm64-v8a and x86_64 supported only from platform-21
|
# ABI arm64-v8a and x86_64 supported only from platform-21
|
||||||
#APP_ABI := arm64-v8a x86_64
|
#APP_ABI := arm64-v8a x86_64
|
||||||
#APP_PLATFORM := android-21
|
#APP_PLATFORM := android-21
|
||||||
|
|
||||||
NDK_TOOLCHAIN_VERSION := clang
|
NDK_TOOLCHAIN_VERSION := clang
|
||||||
APP_STL := c++_shared
|
#APP_STL := c++_shared
|
||||||
|
APP_STL := c++_static
|
||||||
|
|
||||||
# Enable c++11 extensions in source code
|
# Enable c++11 extensions in source code
|
||||||
APP_CPPFLAGS += -std=c++11 -fexceptions -frtti
|
APP_CPPFLAGS += -std=c++11 -fexceptions -frtti
|
||||||
|
@ -39,7 +39,7 @@ namespace android
|
|||||||
emit resultReady();
|
emit resultReady();
|
||||||
}
|
}
|
||||||
|
|
||||||
Controller::Controller(DaemonAndroidImpl& daemon):
|
Controller::Controller(DaemonAndroidImpl& daemon):
|
||||||
m_Daemon (daemon)
|
m_Daemon (daemon)
|
||||||
{
|
{
|
||||||
Worker *worker = new Worker (m_Daemon);
|
Worker *worker = new Worker (m_Daemon);
|
||||||
@ -57,19 +57,19 @@ namespace android
|
|||||||
workerThread.quit();
|
workerThread.quit();
|
||||||
workerThread.wait();
|
workerThread.wait();
|
||||||
Log.d(TAG"Waiting for daemon worker thread finished.");
|
Log.d(TAG"Waiting for daemon worker thread finished.");
|
||||||
if(m_Daemon.isRunning())
|
if(m_Daemon.isRunning())
|
||||||
{
|
{
|
||||||
Log.d(TAG"Stopping the daemon...");
|
Log.d(TAG"Stopping the daemon...");
|
||||||
m_Daemon.stop();
|
m_Daemon.stop();
|
||||||
Log.d(TAG"Stopped the daemon.");
|
Log.d(TAG"Stopped the daemon.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
DaemonAndroidImpl::DaemonAndroidImpl ()
|
DaemonAndroidImpl::DaemonAndroidImpl ()
|
||||||
//:
|
//:
|
||||||
/*mutex(nullptr), */
|
/*mutex(nullptr), */
|
||||||
//m_IsRunning(false),
|
//m_IsRunning(false),
|
||||||
//m_RunningChangedCallback(nullptr)
|
//m_RunningChangedCallback(nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,9 +82,9 @@ namespace android
|
|||||||
{
|
{
|
||||||
//mutex=new QMutex(QMutex::Recursive);
|
//mutex=new QMutex(QMutex::Recursive);
|
||||||
//setRunningCallback(0);
|
//setRunningCallback(0);
|
||||||
//m_IsRunning=false;
|
//m_IsRunning=false;
|
||||||
|
|
||||||
// make sure assets are ready before proceed
|
// make sure assets are ready before proceed
|
||||||
i2p::fs::DetectDataDir("", false);
|
i2p::fs::DetectDataDir("", false);
|
||||||
int numAttempts = 0;
|
int numAttempts = 0;
|
||||||
do
|
do
|
||||||
@ -93,7 +93,7 @@ namespace android
|
|||||||
numAttempts++;
|
numAttempts++;
|
||||||
std::this_thread::sleep_for (std::chrono::seconds(1)); // otherwise wait for 1 more second
|
std::this_thread::sleep_for (std::chrono::seconds(1)); // otherwise wait for 1 more second
|
||||||
}
|
}
|
||||||
while (numAttempts <= 10); // 10 seconds max
|
while (numAttempts <= 10); // 10 seconds max
|
||||||
return Daemon.init(argc,argv);
|
return Daemon.init(argc,argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,16 +125,16 @@ namespace android
|
|||||||
|
|
||||||
bool DaemonAndroidImpl::isRunning()
|
bool DaemonAndroidImpl::isRunning()
|
||||||
{
|
{
|
||||||
return m_IsRunning;
|
return m_IsRunning;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DaemonAndroidImpl::setRunning(bool newValue)
|
void DaemonAndroidImpl::setRunning(bool newValue)
|
||||||
{
|
{
|
||||||
bool oldValue = m_IsRunning;
|
bool oldValue = m_IsRunning;
|
||||||
if(oldValue!=newValue)
|
if(oldValue!=newValue)
|
||||||
{
|
{
|
||||||
m_IsRunning = newValue;
|
m_IsRunning = newValue;
|
||||||
if(m_RunningChangedCallback)
|
if(m_RunningChangedCallback)
|
||||||
m_RunningChangedCallback();
|
m_RunningChangedCallback();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -183,14 +183,14 @@ namespace android
|
|||||||
catch (boost::exception& ex)
|
catch (boost::exception& ex)
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << boost::diagnostic_information(ex);
|
ss << boost::diagnostic_information(ex);
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
catch (std::exception& ex)
|
catch (std::exception& ex)
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << ex.what();
|
ss << ex.what();
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
|
@ -7,45 +7,45 @@ namespace i2p
|
|||||||
{
|
{
|
||||||
namespace android
|
namespace android
|
||||||
{
|
{
|
||||||
class DaemonAndroidImpl
|
class DaemonAndroidImpl
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DaemonAndroidImpl ();
|
DaemonAndroidImpl ();
|
||||||
~DaemonAndroidImpl ();
|
~DaemonAndroidImpl ();
|
||||||
|
|
||||||
//typedef void (*runningChangedCallback)();
|
//typedef void (*runningChangedCallback)();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return success
|
* @return success
|
||||||
*/
|
*/
|
||||||
bool init(int argc, char* argv[]);
|
bool init(int argc, char* argv[]);
|
||||||
void start();
|
void start();
|
||||||
void stop();
|
void stop();
|
||||||
void restart();
|
void restart();
|
||||||
//void setRunningCallback(runningChangedCallback cb);
|
//void setRunningCallback(runningChangedCallback cb);
|
||||||
//bool isRunning();
|
//bool isRunning();
|
||||||
private:
|
private:
|
||||||
//void setRunning(bool running);
|
//void setRunning(bool running);
|
||||||
private:
|
private:
|
||||||
//QMutex* mutex;
|
//QMutex* mutex;
|
||||||
//bool m_IsRunning;
|
//bool m_IsRunning;
|
||||||
//runningChangedCallback m_RunningChangedCallback;
|
//runningChangedCallback m_RunningChangedCallback;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns "ok" if daemon init failed
|
* returns "ok" if daemon init failed
|
||||||
* returns errinfo if daemon initialized and started okay
|
* returns errinfo if daemon initialized and started okay
|
||||||
*/
|
*/
|
||||||
std::string start();
|
std::string start();
|
||||||
|
|
||||||
// stops the daemon
|
// stops the daemon
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
class Worker : public QObject
|
class Worker : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Worker (DaemonAndroidImpl& daemon);
|
Worker (DaemonAndroidImpl& daemon);
|
||||||
@ -54,33 +54,33 @@ namespace android
|
|||||||
|
|
||||||
DaemonAndroidImpl& m_Daemon;
|
DaemonAndroidImpl& m_Daemon;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void startDaemon();
|
void startDaemon();
|
||||||
void restartDaemon();
|
void restartDaemon();
|
||||||
void stopDaemon();
|
void stopDaemon();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void resultReady();
|
void resultReady();
|
||||||
};
|
};
|
||||||
|
|
||||||
class Controller : public QObject
|
class Controller : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
QThread workerThread;
|
QThread workerThread;
|
||||||
public:
|
public:
|
||||||
Controller(DaemonAndroidImpl& daemon);
|
Controller(DaemonAndroidImpl& daemon);
|
||||||
~Controller();
|
~Controller();
|
||||||
private:
|
private:
|
||||||
DaemonAndroidImpl& m_Daemon;
|
DaemonAndroidImpl& m_Daemon;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void handleResults(){}
|
void handleResults(){}
|
||||||
signals:
|
signals:
|
||||||
void startDaemon();
|
void startDaemon();
|
||||||
void stopDaemon();
|
void stopDaemon();
|
||||||
void restartDaemon();
|
void restartDaemon();
|
||||||
};
|
};
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
|
|
||||||
//#include <string.h>
|
|
||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
#include "org_purplei2p_i2pd_I2PD_JNI.h"
|
#include "org_purplei2p_i2pd_I2PD_JNI.h"
|
||||||
#include "DaemonAndroid.h"
|
#include "DaemonAndroid.h"
|
||||||
@ -7,65 +5,64 @@
|
|||||||
#include "Transports.h"
|
#include "Transports.h"
|
||||||
|
|
||||||
JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getABICompiledWith
|
JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getABICompiledWith
|
||||||
(JNIEnv * env, jclass clazz) {
|
(JNIEnv * env, jclass clazz) {
|
||||||
#if defined(__arm__)
|
#if defined(__arm__)
|
||||||
#if defined(__ARM_ARCH_7A__)
|
#if defined(__ARM_ARCH_7A__)
|
||||||
#if defined(__ARM_NEON__)
|
#if defined(__ARM_NEON__)
|
||||||
#if defined(__ARM_PCS_VFP)
|
#if defined(__ARM_PCS_VFP)
|
||||||
#define ABI "armeabi-v7a/NEON (hard-float)"
|
#define ABI "armeabi-v7a/NEON (hard-float)"
|
||||||
#else
|
#else
|
||||||
#define ABI "armeabi-v7a/NEON"
|
#define ABI "armeabi-v7a/NEON"
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#if defined(__ARM_PCS_VFP)
|
#if defined(__ARM_PCS_VFP)
|
||||||
#define ABI "armeabi-v7a (hard-float)"
|
#define ABI "armeabi-v7a (hard-float)"
|
||||||
#else
|
#else
|
||||||
#define ABI "armeabi-v7a"
|
#define ABI "armeabi-v7a"
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#define ABI "armeabi"
|
#define ABI "armeabi"
|
||||||
#endif
|
#endif
|
||||||
#elif defined(__i386__)
|
#elif defined(__i386__)
|
||||||
#define ABI "x86"
|
#define ABI "x86"
|
||||||
#elif defined(__x86_64__)
|
#elif defined(__x86_64__)
|
||||||
#define ABI "x86_64"
|
#define ABI "x86_64"
|
||||||
#elif defined(__mips64) /* mips64el-* toolchain defines __mips__ too */
|
#elif defined(__mips64) /* mips64el-* toolchain defines __mips__ too */
|
||||||
#define ABI "mips64"
|
#define ABI "mips64"
|
||||||
#elif defined(__mips__)
|
#elif defined(__mips__)
|
||||||
#define ABI "mips"
|
#define ABI "mips"
|
||||||
#elif defined(__aarch64__)
|
#elif defined(__aarch64__)
|
||||||
#define ABI "arm64-v8a"
|
#define ABI "arm64-v8a"
|
||||||
#else
|
#else
|
||||||
#define ABI "unknown"
|
#define ABI "unknown"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return env->NewStringUTF(ABI);
|
return env->NewStringUTF(ABI);
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startDaemon
|
JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startDaemon
|
||||||
(JNIEnv * env, jclass clazz) {
|
(JNIEnv * env, jclass clazz) {
|
||||||
return env->NewStringUTF(i2p::android::start().c_str());
|
return env->NewStringUTF(i2p::android::start().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopDaemon
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopDaemon
|
||||||
(JNIEnv * env, jclass clazz) {
|
(JNIEnv * env, jclass clazz) {
|
||||||
i2p::android::stop();
|
i2p::android::stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopAcceptingTunnels
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopAcceptingTunnels
|
||||||
(JNIEnv * env, jclass clazz) {
|
(JNIEnv * env, jclass clazz) {
|
||||||
i2p::context.SetAcceptsTunnels (false);
|
i2p::context.SetAcceptsTunnels (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startAcceptingTunnels
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startAcceptingTunnels
|
||||||
(JNIEnv * env, jclass clazz) {
|
(JNIEnv * env, jclass clazz) {
|
||||||
i2p::context.SetAcceptsTunnels (true);
|
i2p::context.SetAcceptsTunnels (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_onNetworkStateChanged
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_onNetworkStateChanged
|
||||||
(JNIEnv * env, jclass clazz, jboolean isConnected)
|
(JNIEnv * env, jclass clazz, jboolean isConnected) {
|
||||||
{
|
|
||||||
bool isConnectedBool = (bool) isConnected;
|
bool isConnectedBool = (bool) isConnected;
|
||||||
i2p::transport::transports.SetOnline (isConnectedBool);
|
i2p::transport::transports.SetOnline (isConnectedBool);
|
||||||
}
|
}
|
||||||
|
@ -13,22 +13,22 @@ extern "C" {
|
|||||||
* Signature: ()Ljava/lang/String;
|
* Signature: ()Ljava/lang/String;
|
||||||
*/
|
*/
|
||||||
JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getABICompiledWith
|
JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getABICompiledWith
|
||||||
(JNIEnv *, jclass);
|
(JNIEnv *, jclass);
|
||||||
|
|
||||||
JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startDaemon
|
JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startDaemon
|
||||||
(JNIEnv *, jclass);
|
(JNIEnv *, jclass);
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopDaemon
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopDaemon
|
||||||
(JNIEnv *, jclass);
|
(JNIEnv *, jclass);
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopAcceptingTunnels
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopAcceptingTunnels
|
||||||
(JNIEnv *, jclass);
|
(JNIEnv *, jclass);
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startAcceptingTunnels
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startAcceptingTunnels
|
||||||
(JNIEnv *, jclass);
|
(JNIEnv *, jclass);
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_onNetworkStateChanged
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_onNetworkStateChanged
|
||||||
(JNIEnv * env, jclass clazz, jboolean isConnected);
|
(JNIEnv * env, jclass clazz, jboolean isConnected);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
19
android/res/values-ru/strings.xml
Executable file
19
android/res/values-ru/strings.xml
Executable file
@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="app_name">i2pd</string>
|
||||||
|
<string name="action_stop">Остановить</string>
|
||||||
|
<string name="action_graceful_stop">Корректная остановка</string>
|
||||||
|
<string name="action_cancel_graceful_stop">Отменить мягкую остановку</string>
|
||||||
|
<string name="graceful_stop_is_already_in_progress">Мягкая остановка уже запущена</string>
|
||||||
|
<string name="graceful_stop_is_in_progress">Мягкая остановка запущена</string>
|
||||||
|
<string name="already_stopped">Уже остановлено</string>
|
||||||
|
<string name="uninitialized">Приложение инициализируется</string>
|
||||||
|
<string name="starting">Приложение запускается</string>
|
||||||
|
<string name="jniLibraryLoaded">Загружены JNI библиотеки</string>
|
||||||
|
<string name="startedOkay">Приложение запущено</string>
|
||||||
|
<string name="startFailed">Запуск не удался</string>
|
||||||
|
<string name="gracefulShutdownInProgress">Мягкая остановка запущена</string>
|
||||||
|
<string name="stopped">Приложение было остановлено</string>
|
||||||
|
<string name="remaining">осталось</string>
|
||||||
|
<string name="title_activity_i2_pdperms_asker_prompt">Запрос</string>
|
||||||
|
</resources>
|
@ -1,19 +1,19 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
|
||||||
<string name="app_name">i2pd</string>
|
<string name="app_name">i2pd</string>
|
||||||
<string name="action_stop">Stop</string>
|
<string name="action_stop">Stop</string>
|
||||||
<string name="action_graceful_stop">Graceful Stop</string>
|
<string name="action_graceful_stop">Graceful Stop</string>
|
||||||
<string name="action_cancel_graceful_stop">Cancel Graceful Stop</string>
|
<string name="action_cancel_graceful_stop">Cancel Graceful Stop</string>
|
||||||
<string name="graceful_stop_is_already_in_progress">Graceful stop is already in progress</string>
|
<string name="graceful_stop_is_already_in_progress">Graceful stop is already in progress</string>
|
||||||
<string name="graceful_stop_is_in_progress">Graceful stop is in progress</string>
|
<string name="graceful_stop_is_in_progress">Graceful stop is in progress</string>
|
||||||
<string name="already_stopped">Already stopped</string>
|
<string name="already_stopped">Already stopped</string>
|
||||||
<string name="uninitialized">i2pd initializing</string>
|
<string name="uninitialized">Application initializing</string>
|
||||||
<string name="starting">i2pd is starting</string>
|
<string name="starting">Application starting</string>
|
||||||
<string name="jniLibraryLoaded">i2pd: loaded JNI libraries</string>
|
<string name="jniLibraryLoaded">Loaded JNI libraries</string>
|
||||||
<string name="startedOkay">i2pd started</string>
|
<string name="startedOkay">Application Started</string>
|
||||||
<string name="startFailed">i2pd start failed</string>
|
<string name="startFailed">Start failed</string>
|
||||||
<string name="gracefulShutdownInProgress">i2pd: graceful shutdown in progress</string>
|
<string name="gracefulShutdownInProgress">Graceful shutdown in progress</string>
|
||||||
<string name="stopped">i2pd has stopped</string>
|
<string name="stopped">Application stopped</string>
|
||||||
<string name="remaining">remaining</string>
|
<string name="remaining">remaining</string>
|
||||||
<string name="title_activity_i2_pdperms_asker_prompt">Prompt</string>
|
<string name="title_activity_i2_pdperms_asker_prompt">Prompt</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -2,8 +2,8 @@ package org.purplei2p.i2pd;
|
|||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import org.purplei2p.i2pd.R;
|
||||||
|
|
||||||
public class DaemonSingleton {
|
public class DaemonSingleton {
|
||||||
private static final String TAG="i2pd";
|
private static final String TAG="i2pd";
|
||||||
@ -43,24 +43,24 @@ public class DaemonSingleton {
|
|||||||
private volatile boolean startedOkay;
|
private volatile boolean startedOkay;
|
||||||
|
|
||||||
public enum State {
|
public enum State {
|
||||||
uninitialized(R.string.uninitialized),
|
uninitialized(R.string.uninitialized),
|
||||||
starting(R.string.starting),
|
starting(R.string.starting),
|
||||||
jniLibraryLoaded(R.string.jniLibraryLoaded),
|
jniLibraryLoaded(R.string.jniLibraryLoaded),
|
||||||
startedOkay(R.string.startedOkay),
|
startedOkay(R.string.startedOkay),
|
||||||
startFailed(R.string.startFailed),
|
startFailed(R.string.startFailed),
|
||||||
gracefulShutdownInProgress(R.string.gracefulShutdownInProgress),
|
gracefulShutdownInProgress(R.string.gracefulShutdownInProgress),
|
||||||
stopped(R.string.stopped);
|
stopped(R.string.stopped);
|
||||||
|
|
||||||
State(int statusStringResourceId) {
|
State(int statusStringResourceId) {
|
||||||
this.statusStringResourceId = statusStringResourceId;
|
this.statusStringResourceId = statusStringResourceId;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final int statusStringResourceId;
|
private final int statusStringResourceId;
|
||||||
|
|
||||||
public int getStatusStringResourceId() {
|
public int getStatusStringResourceId() {
|
||||||
return statusStringResourceId;
|
return statusStringResourceId;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private volatile State state = State.uninitialized;
|
private volatile State state = State.uninitialized;
|
||||||
|
|
||||||
|
@ -16,134 +16,133 @@ import android.util.Log;
|
|||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
private final DaemonSingleton.StateUpdateListener daemonStateUpdatedListener =
|
private final DaemonSingleton.StateUpdateListener daemonStateUpdatedListener =
|
||||||
new DaemonSingleton.StateUpdateListener() {
|
new DaemonSingleton.StateUpdateListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void daemonStateUpdate() {
|
public void daemonStateUpdate() {
|
||||||
try {
|
try {
|
||||||
synchronized (ForegroundService.this) {
|
synchronized (ForegroundService.this) {
|
||||||
if (shown) cancelNotification();
|
if (shown) cancelNotification();
|
||||||
showNotification();
|
showNotification();
|
||||||
}
|
}
|
||||||
} catch (Throwable tr) {
|
} catch (Throwable tr) {
|
||||||
Log.e(TAG,"error ignored",tr);
|
Log.e(TAG,"error ignored",tr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
private NotificationManager notificationManager;
|
private NotificationManager notificationManager;
|
||||||
|
|
||||||
// Unique Identification Number for the Notification.
|
// Unique Identification Number for the Notification.
|
||||||
// We use it on Notification start, and to cancel it.
|
// We use it on Notification start, and to cancel it.
|
||||||
private int NOTIFICATION = 1;
|
private int NOTIFICATION = 1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class for clients to access. Because we know this service always
|
* 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
|
* runs in the same process as its clients, we don't need to deal with
|
||||||
* IPC.
|
* IPC.
|
||||||
*/
|
*/
|
||||||
public class LocalBinder extends Binder {
|
public class LocalBinder extends Binder {
|
||||||
ForegroundService getService() {
|
ForegroundService getService() {
|
||||||
return ForegroundService.this;
|
return ForegroundService.this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
|
notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
|
||||||
|
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
DaemonSingleton.getInstance().addStateChangeListener(daemonStateUpdatedListener);
|
DaemonSingleton.getInstance().addStateChangeListener(daemonStateUpdatedListener);
|
||||||
if (!shown) daemonStateUpdatedListener.daemonStateUpdate();
|
if (!shown) daemonStateUpdatedListener.daemonStateUpdate();
|
||||||
}
|
}
|
||||||
// Tell the user we started.
|
// Tell the user we started.
|
||||||
// Toast.makeText(this, R.string.i2pd_service_started, Toast.LENGTH_SHORT).show();
|
// Toast.makeText(this, R.string.i2pd_service_started, Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||||
Log.i("ForegroundService", "Received start id " + startId + ": " + intent);
|
Log.i("ForegroundService", "Received start id " + startId + ": " + intent);
|
||||||
return START_STICKY;
|
return START_STICKY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
DaemonSingleton.getInstance().removeStateChangeListener(daemonStateUpdatedListener);
|
DaemonSingleton.getInstance().removeStateChangeListener(daemonStateUpdatedListener);
|
||||||
cancelNotification();
|
cancelNotification();
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void cancelNotification() {
|
private synchronized void cancelNotification() {
|
||||||
// Cancel the persistent notification.
|
// Cancel the persistent notification.
|
||||||
notificationManager.cancel(NOTIFICATION);
|
notificationManager.cancel(NOTIFICATION);
|
||||||
|
|
||||||
stopForeground(true);
|
stopForeground(true);
|
||||||
|
|
||||||
// Tell the user we stopped.
|
// Tell the user we stopped.
|
||||||
// Toast.makeText(this, R.string.i2pd_service_stopped, Toast.LENGTH_SHORT).show();
|
//Toast.makeText(this, R.string.i2pd_service_stopped, Toast.LENGTH_SHORT).show();
|
||||||
shown=false;
|
shown=false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IBinder onBind(Intent intent) {
|
public IBinder onBind(Intent intent) {
|
||||||
return mBinder;
|
return mBinder;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is the object that receives interactions from clients. See
|
// This is the object that receives interactions from clients. See
|
||||||
// RemoteService for a more complete example.
|
// RemoteService for a more complete example.
|
||||||
private final IBinder mBinder = new LocalBinder();
|
private final IBinder mBinder = new LocalBinder();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show a notification while this service is running.
|
* Show a notification while this service is running.
|
||||||
*/
|
*/
|
||||||
private synchronized void showNotification() {
|
private synchronized void showNotification() {
|
||||||
// In this sample, we'll use the same text for the ticker and the expanded notification
|
// In this sample, we'll use the same text for the ticker and the expanded notification
|
||||||
CharSequence text = getText(DaemonSingleton.getInstance().getState().getStatusStringResourceId());
|
CharSequence text = getText(DaemonSingleton.getInstance().getState().getStatusStringResourceId());
|
||||||
|
|
||||||
// The PendingIntent to launch our activity if the user selects this notification
|
// The PendingIntent to launch our activity if the user selects this notification
|
||||||
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
|
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
|
||||||
new Intent(this, I2PDActivity.class), 0);
|
new Intent(this, I2PDActivity.class), 0);
|
||||||
|
|
||||||
// If earlier version channel ID is not used
|
// If earlier version channel ID is not used
|
||||||
// https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Builder.html#NotificationCompat.Builder(android.content.Context)
|
// https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Builder.html#NotificationCompat.Builder(android.content.Context)
|
||||||
String channelId = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) ? createNotificationChannel() : "";
|
String channelId = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) ? createNotificationChannel() : "";
|
||||||
|
|
||||||
// Set the info for the views that show in the notification panel.
|
// Set the info for the views that show in the notification panel.
|
||||||
Notification notification = new NotificationCompat.Builder(this, channelId)
|
Notification notification = new NotificationCompat.Builder(this, channelId)
|
||||||
.setOngoing(true)
|
.setOngoing(true)
|
||||||
.setSmallIcon(R.drawable.itoopie_notification_icon) // the status icon
|
.setSmallIcon(R.drawable.itoopie_notification_icon) // the status icon
|
||||||
.setPriority(Notification.PRIORITY_DEFAULT)
|
.setPriority(Notification.PRIORITY_DEFAULT)
|
||||||
.setCategory(Notification.CATEGORY_SERVICE)
|
.setCategory(Notification.CATEGORY_SERVICE)
|
||||||
.setTicker(text) // the status text
|
.setTicker(text) // the status text
|
||||||
.setWhen(System.currentTimeMillis()) // the time stamp
|
.setWhen(System.currentTimeMillis()) // the time stamp
|
||||||
.setContentTitle(getText(R.string.app_name)) // the label of the entry
|
.setContentTitle(getText(R.string.app_name)) // the label of the entry
|
||||||
.setContentText(text) // the contents of the entry
|
.setContentText(text) // the contents of the entry
|
||||||
.setContentIntent(contentIntent) // The intent to send when the entry is clicked
|
.setContentIntent(contentIntent) // The intent to send when the entry is clicked
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
// Send the notification.
|
// Send the notification.
|
||||||
//mNM.notify(NOTIFICATION, notification);
|
//mNM.notify(NOTIFICATION, notification);
|
||||||
startForeground(NOTIFICATION, notification);
|
startForeground(NOTIFICATION, notification);
|
||||||
shown = true;
|
shown = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.O)
|
@RequiresApi(Build.VERSION_CODES.O)
|
||||||
private synchronized String createNotificationChannel() {
|
private synchronized String createNotificationChannel() {
|
||||||
String channelId = getString(R.string.app_name);
|
String channelId = getString(R.string.app_name);
|
||||||
CharSequence channelName = "I2Pd service";
|
CharSequence channelName = "I2Pd service";
|
||||||
NotificationChannel chan = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_LOW);
|
NotificationChannel chan = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_LOW);
|
||||||
//chan.setLightColor(Color.PURPLE);
|
//chan.setLightColor(Color.PURPLE);
|
||||||
chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
|
chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
|
||||||
NotificationManager service = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
|
NotificationManager service = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
service.createNotificationChannel(chan);
|
service.createNotificationChannel(chan);
|
||||||
return channelId;
|
return channelId;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final DaemonSingleton daemon = DaemonSingleton.getInstance();
|
private static final DaemonSingleton daemon = DaemonSingleton.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,9 +66,9 @@ public class I2PDActivity extends Activity {
|
|||||||
}
|
}
|
||||||
DaemonSingleton.State state = daemon.getState();
|
DaemonSingleton.State state = daemon.getState();
|
||||||
textView.setText(
|
textView.setText(
|
||||||
String.valueOf(state)+
|
String.valueOf(getText(state.getStatusStringResourceId()))+
|
||||||
(DaemonSingleton.State.startFailed.equals(state)?": "+daemon.getDaemonStartResult():"")+
|
(DaemonSingleton.State.startFailed.equals(state) ? ": "+daemon.getDaemonStartResult() : "")+
|
||||||
(DaemonSingleton.State.gracefulShutdownInProgress.equals(state)?": "+formatGraceTimeRemaining()+" "+getText(R.string.remaining):"")
|
(DaemonSingleton.State.gracefulShutdownInProgress.equals(state) ? ": "+formatGraceTimeRemaining()+" "+getText(R.string.remaining) : "")
|
||||||
);
|
);
|
||||||
} catch (Throwable tr) {
|
} catch (Throwable tr) {
|
||||||
Log.e(TAG,"error ignored",tr);
|
Log.e(TAG,"error ignored",tr);
|
||||||
@ -100,14 +100,14 @@ public class I2PDActivity extends Activity {
|
|||||||
daemonStateUpdatedListener.daemonStateUpdate();
|
daemonStateUpdatedListener.daemonStateUpdate();
|
||||||
|
|
||||||
// request permissions
|
// request permissions
|
||||||
if (Build.VERSION.SDK_INT >= 23)
|
if (Build.VERSION.SDK_INT >= 23)
|
||||||
{
|
{
|
||||||
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)
|
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)
|
||||||
{
|
{
|
||||||
ActivityCompat.requestPermissions(this,
|
ActivityCompat.requestPermissions(this,
|
||||||
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
|
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
|
||||||
MY_PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE);
|
MY_PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// set the app be foreground
|
// set the app be foreground
|
||||||
@ -139,19 +139,19 @@ public class I2PDActivity extends Activity {
|
|||||||
@Override
|
@Override
|
||||||
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults)
|
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults)
|
||||||
{
|
{
|
||||||
switch (requestCode)
|
switch (requestCode)
|
||||||
{
|
{
|
||||||
case MY_PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE:
|
case MY_PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE:
|
||||||
{
|
{
|
||||||
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
|
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
|
||||||
Log.e(TAG, "Memory permission granted");
|
Log.e(TAG, "Memory permission granted");
|
||||||
else
|
else
|
||||||
Log.e(TAG, "Memory permission declined");
|
Log.e(TAG, "Memory permission declined");
|
||||||
// TODO: terminate
|
// TODO: terminate
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
default: ;
|
default: ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void cancelGracefulStop() {
|
private static void cancelGracefulStop() {
|
||||||
@ -249,7 +249,7 @@ public class I2PDActivity extends Activity {
|
|||||||
{
|
{
|
||||||
item.setTitle(R.string.action_cancel_graceful_stop);
|
item.setTitle(R.string.action_cancel_graceful_stop);
|
||||||
i2pdGracefulStop();
|
i2pdGracefulStop();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -329,7 +329,7 @@ public class I2PDActivity extends Activity {
|
|||||||
daemon.startAcceptingTunnels();
|
daemon.startAcceptingTunnels();
|
||||||
else
|
else
|
||||||
i2pdStop();
|
i2pdStop();
|
||||||
}
|
}
|
||||||
catch(Throwable tr)
|
catch(Throwable tr)
|
||||||
{
|
{
|
||||||
Log.e(TAG,"",tr);
|
Log.e(TAG,"",tr);
|
||||||
|
@ -15,157 +15,157 @@ import java.lang.reflect.Method;
|
|||||||
//android.permission.WRITE_EXTERNAL_STORAGE
|
//android.permission.WRITE_EXTERNAL_STORAGE
|
||||||
public class I2PDPermsAskerActivity extends Activity {
|
public class I2PDPermsAskerActivity extends Activity {
|
||||||
|
|
||||||
private static final int PERMISSION_WRITE_EXTERNAL_STORAGE = 0;
|
private static final int PERMISSION_WRITE_EXTERNAL_STORAGE = 0;
|
||||||
|
|
||||||
private Button button_request_write_ext_storage_perms;
|
private Button button_request_write_ext_storage_perms;
|
||||||
private TextView textview_retry;
|
private TextView textview_retry;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
//if less than Android 6, no runtime perms req system present
|
//if less than Android 6, no runtime perms req system present
|
||||||
if (android.os.Build.VERSION.SDK_INT < 23) {
|
if (android.os.Build.VERSION.SDK_INT < 23) {
|
||||||
startMainActivity();
|
startMainActivity();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
setContentView(R.layout.activity_perms_asker);
|
setContentView(R.layout.activity_perms_asker);
|
||||||
button_request_write_ext_storage_perms = (Button) findViewById(R.id.button_request_write_ext_storage_perms);
|
button_request_write_ext_storage_perms = (Button) findViewById(R.id.button_request_write_ext_storage_perms);
|
||||||
textview_retry = (TextView) findViewById(R.id.textview_retry);
|
textview_retry = (TextView) findViewById(R.id.textview_retry);
|
||||||
|
|
||||||
button_request_write_ext_storage_perms.setOnClickListener(new View.OnClickListener() {
|
button_request_write_ext_storage_perms.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
request_write_ext_storage_perms();
|
request_write_ext_storage_perms();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
request_write_ext_storage_perms();
|
request_write_ext_storage_perms();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void request_write_ext_storage_perms() {
|
private void request_write_ext_storage_perms() {
|
||||||
|
|
||||||
textview_retry.setVisibility(TextView.GONE);
|
textview_retry.setVisibility(TextView.GONE);
|
||||||
button_request_write_ext_storage_perms.setVisibility(Button.GONE);
|
button_request_write_ext_storage_perms.setVisibility(Button.GONE);
|
||||||
|
|
||||||
Method methodCheckPermission;
|
Method methodCheckPermission;
|
||||||
Method method_shouldShowRequestPermissionRationale;
|
Method method_shouldShowRequestPermissionRationale;
|
||||||
Method method_requestPermissions;
|
Method method_requestPermissions;
|
||||||
try {
|
try {
|
||||||
methodCheckPermission = getClass().getMethod("checkSelfPermission", String.class);
|
methodCheckPermission = getClass().getMethod("checkSelfPermission", String.class);
|
||||||
method_shouldShowRequestPermissionRationale =
|
method_shouldShowRequestPermissionRationale =
|
||||||
getClass().getMethod("shouldShowRequestPermissionRationale", String.class);
|
getClass().getMethod("shouldShowRequestPermissionRationale", String.class);
|
||||||
method_requestPermissions =
|
method_requestPermissions =
|
||||||
getClass().getMethod("requestPermissions", String[].class, int.class);
|
getClass().getMethod("requestPermissions", String[].class, int.class);
|
||||||
} catch (NoSuchMethodException e) {
|
} catch (NoSuchMethodException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
Integer resultObj;
|
Integer resultObj;
|
||||||
try {
|
try {
|
||||||
resultObj = (Integer) methodCheckPermission.invoke(
|
resultObj = (Integer) methodCheckPermission.invoke(
|
||||||
this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
|
this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resultObj != PackageManager.PERMISSION_GRANTED) {
|
if (resultObj != PackageManager.PERMISSION_GRANTED) {
|
||||||
|
|
||||||
// Should we show an explanation?
|
// Should we show an explanation?
|
||||||
Boolean aBoolean;
|
Boolean aBoolean;
|
||||||
try {
|
try {
|
||||||
aBoolean = (Boolean) method_shouldShowRequestPermissionRationale.invoke(this,
|
aBoolean = (Boolean) method_shouldShowRequestPermissionRationale.invoke(this,
|
||||||
Manifest.permission.WRITE_EXTERNAL_STORAGE);
|
Manifest.permission.WRITE_EXTERNAL_STORAGE);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
if (aBoolean) {
|
if (aBoolean) {
|
||||||
|
|
||||||
// Show an explanation to the user *asynchronously* -- don't block
|
// Show an explanation to the user *asynchronously* -- don't block
|
||||||
// this thread waiting for the user's response! After the user
|
// this thread waiting for the user's response! After the user
|
||||||
// sees the explanation, try again to request the permission.
|
// sees the explanation, try again to request the permission.
|
||||||
|
|
||||||
showExplanation();
|
showExplanation();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// No explanation needed, we can request the permission.
|
// No explanation needed, we can request the permission.
|
||||||
|
|
||||||
try {
|
try {
|
||||||
method_requestPermissions.invoke(this,
|
method_requestPermissions.invoke(this,
|
||||||
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
|
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
|
||||||
PERMISSION_WRITE_EXTERNAL_STORAGE);
|
PERMISSION_WRITE_EXTERNAL_STORAGE);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else startMainActivity();
|
} else startMainActivity();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRequestPermissionsResult(int requestCode,
|
public void onRequestPermissionsResult(int requestCode,
|
||||||
String permissions[], int[] grantResults) {
|
String permissions[], int[] grantResults) {
|
||||||
switch (requestCode) {
|
switch (requestCode) {
|
||||||
case PERMISSION_WRITE_EXTERNAL_STORAGE: {
|
case PERMISSION_WRITE_EXTERNAL_STORAGE: {
|
||||||
// If request is cancelled, the result arrays are empty.
|
// If request is cancelled, the result arrays are empty.
|
||||||
if (grantResults.length > 0
|
if (grantResults.length > 0
|
||||||
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||||
|
|
||||||
// permission was granted, yay! Do the
|
// permission was granted, yay! Do the
|
||||||
// contacts-related task you need to do.
|
// contacts-related task you need to do.
|
||||||
|
|
||||||
startMainActivity();
|
startMainActivity();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// permission denied, boo! Disable the
|
// permission denied, boo! Disable the
|
||||||
// functionality that depends on this permission.
|
// functionality that depends on this permission.
|
||||||
textview_retry.setText("SD card write permission denied, you need to allow this to continue");
|
textview_retry.setText("SD card write permission denied, you need to allow this to continue");
|
||||||
textview_retry.setVisibility(TextView.VISIBLE);
|
textview_retry.setVisibility(TextView.VISIBLE);
|
||||||
button_request_write_ext_storage_perms.setVisibility(Button.VISIBLE);
|
button_request_write_ext_storage_perms.setVisibility(Button.VISIBLE);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// other 'case' lines to check for other
|
// other 'case' lines to check for other
|
||||||
// permissions this app might request.
|
// permissions this app might request.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startMainActivity() {
|
private void startMainActivity() {
|
||||||
startActivity(new Intent(this, I2PDActivity.class));
|
startActivity(new Intent(this, I2PDActivity.class));
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final int SHOW_EXPLANATION_REQUEST = 1; // The request code
|
private static final int SHOW_EXPLANATION_REQUEST = 1; // The request code
|
||||||
private void showExplanation() {
|
private void showExplanation() {
|
||||||
Intent intent = new Intent(this, I2PDPermsExplanationActivity.class);
|
Intent intent = new Intent(this, I2PDPermsExplanationActivity.class);
|
||||||
startActivityForResult(intent, SHOW_EXPLANATION_REQUEST);
|
startActivityForResult(intent, SHOW_EXPLANATION_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
// Check which request we're responding to
|
// Check which request we're responding to
|
||||||
if (requestCode == SHOW_EXPLANATION_REQUEST) {
|
if (requestCode == SHOW_EXPLANATION_REQUEST) {
|
||||||
// Make sure the request was successful
|
// Make sure the request was successful
|
||||||
if (resultCode == RESULT_OK) {
|
if (resultCode == RESULT_OK) {
|
||||||
// Request the permission
|
// Request the permission
|
||||||
Method method_requestPermissions;
|
Method method_requestPermissions;
|
||||||
try {
|
try {
|
||||||
method_requestPermissions =
|
method_requestPermissions =
|
||||||
getClass().getMethod("requestPermissions", String[].class, int.class);
|
getClass().getMethod("requestPermissions", String[].class, int.class);
|
||||||
} catch (NoSuchMethodException e) {
|
} catch (NoSuchMethodException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
method_requestPermissions.invoke(this,
|
method_requestPermissions.invoke(this,
|
||||||
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
|
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
|
||||||
PERMISSION_WRITE_EXTERNAL_STORAGE);
|
PERMISSION_WRITE_EXTERNAL_STORAGE);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
finish(); //close the app
|
finish(); //close the app
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,30 +9,30 @@ import android.widget.Button;
|
|||||||
|
|
||||||
public class I2PDPermsExplanationActivity extends Activity {
|
public class I2PDPermsExplanationActivity extends Activity {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_perms_explanation);
|
setContentView(R.layout.activity_perms_explanation);
|
||||||
ActionBar actionBar = getActionBar();
|
ActionBar actionBar = getActionBar();
|
||||||
if(actionBar!=null)actionBar.setHomeButtonEnabled(false);
|
if(actionBar!=null)actionBar.setHomeButtonEnabled(false);
|
||||||
Button button_ok = (Button) findViewById(R.id.button_ok);
|
Button button_ok = (Button) findViewById(R.id.button_ok);
|
||||||
button_ok.setOnClickListener(new View.OnClickListener() {
|
button_ok.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
returnFromActivity();
|
returnFromActivity();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void returnFromActivity() {
|
private void returnFromActivity() {
|
||||||
Intent data = new Intent();
|
Intent data = new Intent();
|
||||||
Activity parent = getParent();
|
Activity parent = getParent();
|
||||||
if (parent == null) {
|
if (parent == null) {
|
||||||
setResult(Activity.RESULT_OK, data);
|
setResult(Activity.RESULT_OK, data);
|
||||||
} else {
|
} else {
|
||||||
parent.setResult(Activity.RESULT_OK, data);
|
parent.setResult(Activity.RESULT_OK, data);
|
||||||
}
|
}
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,23 +1,25 @@
|
|||||||
package org.purplei2p.i2pd;
|
package org.purplei2p.i2pd;
|
||||||
|
|
||||||
public class I2PD_JNI {
|
public class I2PD_JNI {
|
||||||
public static native String getABICompiledWith();
|
public static native String getABICompiledWith();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns error info if failed
|
* returns error info if failed
|
||||||
* returns "ok" if daemon initialized and started okay
|
* returns "ok" if daemon initialized and started okay
|
||||||
*/
|
*/
|
||||||
public static native String startDaemon();
|
public static native String startDaemon();
|
||||||
//should only be called after startDaemon() success
|
|
||||||
public static native void stopDaemon();
|
|
||||||
|
|
||||||
public static native void stopAcceptingTunnels();
|
//should only be called after startDaemon() success
|
||||||
|
public static native void stopDaemon();
|
||||||
|
|
||||||
|
public static native void stopAcceptingTunnels();
|
||||||
|
|
||||||
public static native void startAcceptingTunnels();
|
public static native void startAcceptingTunnels();
|
||||||
|
|
||||||
public static native void onNetworkStateChanged(boolean isConnected);
|
public static native void onNetworkStateChanged(boolean isConnected);
|
||||||
|
|
||||||
public static void loadLibraries() {
|
public static void loadLibraries() {
|
||||||
System.loadLibrary("c++_shared");
|
//System.loadLibrary("c++_shared");
|
||||||
System.loadLibrary("i2pd");
|
System.loadLibrary("i2pd");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,12 +9,12 @@ import android.net.NetworkInfo;
|
|||||||
|
|
||||||
public class NetworkStateChangeReceiver extends BroadcastReceiver {
|
public class NetworkStateChangeReceiver extends BroadcastReceiver {
|
||||||
|
|
||||||
private static final String TAG = "i2pd";
|
private static final String TAG = "i2pd";
|
||||||
|
|
||||||
//api level 1
|
//api level 1
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(final Context context, final Intent intent) {
|
public void onReceive(final Context context, final Intent intent) {
|
||||||
Log.d(TAG,"Network state change");
|
Log.d(TAG,"Network state change");
|
||||||
try {
|
try {
|
||||||
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||||
NetworkInfo activeNetworkInfo = cm.getActiveNetworkInfo();
|
NetworkInfo activeNetworkInfo = cm.getActiveNetworkInfo();
|
||||||
@ -26,5 +26,5 @@ public class NetworkStateChangeReceiver extends BroadcastReceiver {
|
|||||||
} catch (Throwable tr) {
|
} catch (Throwable tr) {
|
||||||
Log.d(TAG,"",tr);
|
Log.d(TAG,"",tr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user