mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-10-01 02:35:48 -04:00
Do not depend on Qt at all on Android
Do the necessary modifications to not depend on Qt to run on Android both in libretroshare and in retroshare-service
This commit is contained in:
parent
941ec42502
commit
856ce2ffb1
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -17,3 +17,6 @@
|
|||||||
[submodule "supportlibs/libsam3"]
|
[submodule "supportlibs/libsam3"]
|
||||||
path = supportlibs/libsam3
|
path = supportlibs/libsam3
|
||||||
url = https://github.com/i2p/libsam3.git
|
url = https://github.com/i2p/libsam3.git
|
||||||
|
[submodule "supportlibs/jni.hpp"]
|
||||||
|
path = supportlibs/jni.hpp
|
||||||
|
url = https://github.com/RetroShare/jni.hpp.git
|
||||||
|
@ -112,6 +112,9 @@ define_default_value MVPTREE_SOURCE_VERSION origin/master
|
|||||||
|
|
||||||
define_default_value REPORT_DIR "$(pwd)/$(basename ${NATIVE_LIBS_TOOLCHAIN_PATH})_build_report/"
|
define_default_value REPORT_DIR "$(pwd)/$(basename ${NATIVE_LIBS_TOOLCHAIN_PATH})_build_report/"
|
||||||
|
|
||||||
|
define_default_value RS_SRC_DIR "$(realpath $(dirname $BASH_SOURCE)/../../)"
|
||||||
|
|
||||||
|
|
||||||
cArch=""
|
cArch=""
|
||||||
eABI=""
|
eABI=""
|
||||||
cmakeABI=""
|
cmakeABI=""
|
||||||
@ -829,6 +832,15 @@ build_phash()
|
|||||||
popd
|
popd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
task_register fetch_jni_hpp
|
||||||
|
fetch_jni_hpp()
|
||||||
|
{
|
||||||
|
local rDir="supportlibs/jni.hpp/"
|
||||||
|
|
||||||
|
[ "$(ls "${RS_SRC_DIR}/${rDir}" | wc -l)" -gt "4" ] ||
|
||||||
|
git -C ${RS_SRC_DIR} submodule update --init ${rDir}
|
||||||
|
}
|
||||||
|
|
||||||
task_register build_mvptree
|
task_register build_mvptree
|
||||||
build_mvptree()
|
build_mvptree()
|
||||||
{
|
{
|
||||||
@ -862,6 +874,7 @@ build_default_toolchain()
|
|||||||
task_run build_xapian || return $?
|
task_run build_xapian || return $?
|
||||||
task_run build_miniupnpc || return $?
|
task_run build_miniupnpc || return $?
|
||||||
task_run build_phash || return $?
|
task_run build_phash || return $?
|
||||||
|
task_run fetch_jni_hpp || return $?
|
||||||
task_run deduplicate_includes || return $?
|
task_run deduplicate_includes || return $?
|
||||||
task_run get_native_libs_toolchain_path || return $?
|
task_run get_native_libs_toolchain_path || return $?
|
||||||
}
|
}
|
||||||
|
@ -796,8 +796,9 @@ void JsonApiServer::run()
|
|||||||
}
|
}
|
||||||
catch(std::exception& e)
|
catch(std::exception& e)
|
||||||
{
|
{
|
||||||
RsErr() << __PRETTY_FUNCTION__ << " Failure starting JSON API server: "
|
/* TODO: find a way to report back programmatically if failed listening
|
||||||
<< e.what() << std::endl;
|
* port */
|
||||||
|
RS_ERR("Failure starting JSON API server: ", e.what());
|
||||||
print_stacktrace();
|
print_stacktrace();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1101,13 +1101,11 @@ android-* {
|
|||||||
DEFINES *= "fseeko64=fseeko"
|
DEFINES *= "fseeko64=fseeko"
|
||||||
DEFINES *= "ftello64=ftello"
|
DEFINES *= "ftello64=ftello"
|
||||||
|
|
||||||
## @See: android_ifaddrs/README.adoc
|
## @See: rs_android/README-ifaddrs-android.adoc
|
||||||
!contains(DEFINES, LIBRETROSHARE_ANDROID_IFADDRS_QT) {
|
HEADERS += \
|
||||||
HEADERS += \
|
rs_android/ifaddrs-android.h \
|
||||||
android_ifaddrs/ifaddrs-android.h \
|
rs_android/LocalArray.h \
|
||||||
android_ifaddrs/LocalArray.h \
|
rs_android/ScopedFd.h
|
||||||
android_ifaddrs/ScopedFd.h
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
## Static library are very susceptible to order in command line
|
## Static library are very susceptible to order in command line
|
||||||
@ -1116,6 +1114,13 @@ android-* {
|
|||||||
LIBS += $$linkStaticLibs(sLibs)
|
LIBS += $$linkStaticLibs(sLibs)
|
||||||
PRE_TARGETDEPS += $$pretargetStaticLibs(sLibs)
|
PRE_TARGETDEPS += $$pretargetStaticLibs(sLibs)
|
||||||
|
|
||||||
HEADERS += util/androiddebug.h
|
HEADERS += \
|
||||||
|
rs_android/androidcoutcerrcatcher.hpp \
|
||||||
|
rs_android/retroshareserviceandroid.hpp \
|
||||||
|
rs_android/rsjni.hpp
|
||||||
|
|
||||||
|
SOURCES += rs_android/rsjni.cpp \
|
||||||
|
rs_android/retroshareserviceandroid.cpp \
|
||||||
|
rs_android/errorconditionwrap.cpp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1398,11 +1398,11 @@ bool p3PeerMgrIMPL::UpdateOwnAddress( const sockaddr_storage& pLocalAddr,
|
|||||||
sockaddr_storage_copy(pExtAddr, extAddr);
|
sockaddr_storage_copy(pExtAddr, extAddr);
|
||||||
sockaddr_storage_ipv6_to_ipv4(extAddr);
|
sockaddr_storage_ipv6_to_ipv4(extAddr);
|
||||||
|
|
||||||
//#ifdef PEER_DEBUG
|
#ifdef PEER_DEBUG
|
||||||
std::cerr << "p3PeerMgrIMPL::UpdateOwnAddress("
|
std::cerr << "p3PeerMgrIMPL::UpdateOwnAddress("
|
||||||
<< sockaddr_storage_tostring(localAddr) << ", "
|
<< sockaddr_storage_tostring(localAddr) << ", "
|
||||||
<< sockaddr_storage_tostring(extAddr) << ")" << std::endl;
|
<< sockaddr_storage_tostring(extAddr) << ")" << std::endl;
|
||||||
//#endif
|
#endif
|
||||||
|
|
||||||
if( rsBanList &&
|
if( rsBanList &&
|
||||||
!rsBanList->isAddressAccepted(localAddr,
|
!rsBanList->isAddressAccepted(localAddr,
|
||||||
|
@ -21,16 +21,6 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||||
* *
|
* *
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
#ifdef WINDOWS_SYS
|
|
||||||
# include "util/rswin.h"
|
|
||||||
# include "util/rsmemory.h"
|
|
||||||
# include <ws2tcpip.h>
|
|
||||||
#endif // WINDOWS_SYS
|
|
||||||
|
|
||||||
/// @See: android_ifaddrs/README.adoc
|
|
||||||
#ifdef __ANDROID__
|
|
||||||
# include <android/api-level.h>
|
|
||||||
#endif // def __ANDROID__
|
|
||||||
|
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@ -44,6 +34,28 @@
|
|||||||
#include "util/rsnet.h"
|
#include "util/rsnet.h"
|
||||||
#include "util/stacktrace.h"
|
#include "util/stacktrace.h"
|
||||||
|
|
||||||
|
#ifdef WINDOWS_SYS
|
||||||
|
# include "util/rswin.h"
|
||||||
|
# include "util/rsmemory.h"
|
||||||
|
# include <ws2tcpip.h>
|
||||||
|
#endif // WINDOWS_SYS
|
||||||
|
|
||||||
|
/// @See: android_ifaddrs/README.adoc
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
# include <android/api-level.h>
|
||||||
|
#endif // def __ANDROID__
|
||||||
|
|
||||||
|
#ifdef WINDOWS_SYS /* Windows - define errno */
|
||||||
|
int errno;
|
||||||
|
#else /* Windows - define errno */
|
||||||
|
#include <netdb.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __HAIKU__
|
||||||
|
# include <sys/sockio.h>
|
||||||
|
# define IFF_RUNNING 0x0001
|
||||||
|
#endif
|
||||||
|
|
||||||
static struct RsLog::logInfo pqinetzoneInfo = {RsLog::Default, "pqinet"};
|
static struct RsLog::logInfo pqinetzoneInfo = {RsLog::Default, "pqinet"};
|
||||||
#define pqinetzone &pqinetzoneInfo
|
#define pqinetzone &pqinetzoneInfo
|
||||||
|
|
||||||
@ -51,21 +63,6 @@ static struct RsLog::logInfo pqinetzoneInfo = {RsLog::Default, "pqinet"};
|
|||||||
* #define NET_DEBUG 1
|
* #define NET_DEBUG 1
|
||||||
****/
|
****/
|
||||||
|
|
||||||
#ifdef WINDOWS_SYS /* Windows - define errno */
|
|
||||||
|
|
||||||
int errno;
|
|
||||||
|
|
||||||
#else /* Windows - define errno */
|
|
||||||
|
|
||||||
#include <netdb.h>
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __HAIKU__
|
|
||||||
#include <sys/sockio.h>
|
|
||||||
#define IFF_RUNNING 0x0001
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/********************************** WINDOWS/UNIX SPECIFIC PART ******************/
|
/********************************** WINDOWS/UNIX SPECIFIC PART ******************/
|
||||||
#ifndef WINDOWS_SYS
|
#ifndef WINDOWS_SYS
|
||||||
|
|
||||||
@ -271,24 +268,16 @@ int inet_aton(const char *name, struct in_addr *addr)
|
|||||||
#endif
|
#endif
|
||||||
/********************************** WINDOWS/UNIX SPECIFIC PART ******************/
|
/********************************** WINDOWS/UNIX SPECIFIC PART ******************/
|
||||||
|
|
||||||
|
#include "util/cxx17retrocompat.h"
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#ifdef WINDOWS_SYS
|
#ifdef WINDOWS_SYS
|
||||||
# include <winsock2.h>
|
# include <winsock2.h>
|
||||||
# include <iphlpapi.h>
|
# include <iphlpapi.h>
|
||||||
# pragma comment(lib, "IPHLPAPI.lib")
|
# pragma comment(lib, "IPHLPAPI.lib")
|
||||||
#elif defined(__ANDROID__) && __ANDROID_API__ < 24 && \
|
#elif defined(__ANDROID__) && __ANDROID_API__ < 24
|
||||||
defined(LIBRETROSHARE_ANDROID_IFADDRS_QT)
|
|
||||||
/// @See: android_ifaddrs/README.adoc
|
/// @See: android_ifaddrs/README.adoc
|
||||||
# include <string>
|
# include "rs_android/ifaddrs-android.h"
|
||||||
# include <QString>
|
#else // not WINDOWS => Linux and other unixes
|
||||||
# include <QHostAddress>
|
|
||||||
# include <QNetworkInterface>
|
|
||||||
#elif defined(__ANDROID__) && __ANDROID_API__ < 24 && \
|
|
||||||
!defined(LIBRETROSHARE_ANDROID_IFADDRS_QT)
|
|
||||||
/// @See: android_ifaddrs/README.adoc
|
|
||||||
# include "android_ifaddrs/ifaddrs-android.h"
|
|
||||||
#else // not __ANDROID__ nor WINDOWS => Linux and other unixes
|
|
||||||
# include <ifaddrs.h>
|
# include <ifaddrs.h>
|
||||||
# include <net/if.h>
|
# include <net/if.h>
|
||||||
#endif // WINDOWS_SYS
|
#endif // WINDOWS_SYS
|
||||||
@ -331,17 +320,7 @@ bool getLocalAddresses(std::vector<sockaddr_storage>& addrs)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(adapter_addresses);
|
free(adapter_addresses);
|
||||||
#elif defined(__ANDROID__) && __ANDROID_API__ < 24 && \
|
#else // not WINDOWS_SYS => Linux and other unixes
|
||||||
defined(LIBRETROSHARE_ANDROID_IFADDRS_QT)
|
|
||||||
/// @See: android_ifaddrs/README.adoc
|
|
||||||
for(auto& qAddr: QNetworkInterface::allAddresses())
|
|
||||||
{
|
|
||||||
sockaddr_storage tmpAddr;
|
|
||||||
sockaddr_storage_clear(tmpAddr);
|
|
||||||
if(sockaddr_storage_ipv4_aton(tmpAddr, qAddr.toString().toStdString().c_str()))
|
|
||||||
addrs.push_back(tmpAddr);
|
|
||||||
}
|
|
||||||
#else // not WINDOWS_SYS not ANDROID => Linux and other unixes
|
|
||||||
struct ifaddrs *ifsaddrs, *ifa;
|
struct ifaddrs *ifsaddrs, *ifa;
|
||||||
if(getifaddrs(&ifsaddrs) != 0)
|
if(getifaddrs(&ifsaddrs) != 0)
|
||||||
{
|
{
|
||||||
@ -355,18 +334,19 @@ bool getLocalAddresses(std::vector<sockaddr_storage>& addrs)
|
|||||||
{
|
{
|
||||||
sockaddr_storage tmp;
|
sockaddr_storage tmp;
|
||||||
sockaddr_storage_clear(tmp);
|
sockaddr_storage_clear(tmp);
|
||||||
if (sockaddr_storage_copyip(tmp, *reinterpret_cast<sockaddr_storage*>(ifa->ifa_addr)))
|
if(sockaddr_storage_copyip(
|
||||||
|
tmp,
|
||||||
|
*reinterpret_cast<sockaddr_storage*>(ifa->ifa_addr) ))
|
||||||
addrs.push_back(tmp);
|
addrs.push_back(tmp);
|
||||||
}
|
}
|
||||||
freeifaddrs(ifsaddrs);
|
freeifaddrs(ifsaddrs);
|
||||||
#endif // WINDOWS_SYS
|
#endif // WINDOWS_SYS
|
||||||
|
|
||||||
#ifdef NET_DEBUG
|
#ifdef NET_DEBUG
|
||||||
std::list<sockaddr_storage>::iterator it;
|
auto&& dbg = RS_DBG("returning: [");
|
||||||
std::cout << "getLocalAddresses(...) returning: <" ;
|
for(auto& addr: std::as_const(addrs))
|
||||||
for(it = addrs.begin(); it != addrs.end(); ++it)
|
dbg << sockaddr_storage_iptostring(addr) << ", ";
|
||||||
std::cout << sockaddr_storage_iptostring(*it) << ", ";
|
dbg << "]" << std::endl;
|
||||||
std::cout << ">" << std::endl;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return !addrs.empty();
|
return !addrs.empty();
|
||||||
|
@ -4,7 +4,8 @@
|
|||||||
* libretroshare: retroshare core library *
|
* libretroshare: retroshare core library *
|
||||||
* *
|
* *
|
||||||
* Copyright (C) 2004-2006 Robert Fernie <retroshare@lunamutt.com> *
|
* Copyright (C) 2004-2006 Robert Fernie <retroshare@lunamutt.com> *
|
||||||
* Copyright (C) 2015-2018 Gioacchino Mazzurco <gio@eigenlab.org> *
|
* Copyright (C) 2015-2021 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||||
|
* Copyright (C) 2021 Asociación Civil Altermundi <info@altermundi.net> *
|
||||||
* *
|
* *
|
||||||
* This program is free software: you can redistribute it and/or modify *
|
* This program is free software: you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU Lesser General Public License as *
|
* it under the terms of the GNU Lesser General Public License as *
|
||||||
@ -20,8 +21,7 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||||
* *
|
* *
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
#ifndef MRK_PQI_NETWORKING_HEADER
|
#pragma once
|
||||||
#define MRK_PQI_NETWORKING_HEADER
|
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -86,9 +86,13 @@ extern int errno; /* Define extern errno, to duplicate unix behaviour */
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
|
#include "util/rsdeprecate.h"
|
||||||
|
|
||||||
// Same def - different functions...
|
// Same def - different functions...
|
||||||
|
RS_DEPRECATED_FOR("use std::error_condition instead")
|
||||||
void showSocketError(std::string &out);
|
void showSocketError(std::string &out);
|
||||||
|
|
||||||
|
RS_DEPRECATED_FOR("use std::error_condition instead")
|
||||||
std::string socket_errorType(int err);
|
std::string socket_errorType(int err);
|
||||||
|
|
||||||
bool getLocalAddresses(std::vector<sockaddr_storage> & addrs);
|
bool getLocalAddresses(std::vector<sockaddr_storage> & addrs);
|
||||||
@ -103,10 +107,6 @@ int unix_getsockopt_error(int sockfd, int *err);
|
|||||||
|
|
||||||
#ifdef WINDOWS_SYS // WINDOWS
|
#ifdef WINDOWS_SYS // WINDOWS
|
||||||
/******************* WINDOWS SPECIFIC PART ******************/
|
/******************* WINDOWS SPECIFIC PART ******************/
|
||||||
|
RS_DEPRECATED_FOR("use std::error_condition instead")
|
||||||
int WinToUnixError(int error);
|
int WinToUnixError(int error);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
@ -24,9 +24,8 @@ plus depending on Qt networking module just for this is frustrating.
|
|||||||
Update: the warning flood seems have been fixed in later Qt versions
|
Update: the warning flood seems have been fixed in later Qt versions
|
||||||
https://bugreports.qt.io/browse/QTBUG-86394
|
https://bugreports.qt.io/browse/QTBUG-86394
|
||||||
|
|
||||||
This solution is the first working we implemented in our code it is disabled by
|
This solution was the first working we implemented in our code it has been
|
||||||
default but can be enabled passing `DEFINES+=LIBRETROSHARE_ANDROID_IFADDRS_QT`
|
removed to avoid dependency on Qt, as lighter alternatives are possible.
|
||||||
when running `qmake` command.
|
|
||||||
|
|
||||||
|
|
||||||
== Code copied from Android Gingerbread release
|
== Code copied from Android Gingerbread release
|
||||||
@ -43,3 +42,8 @@ https://android.googlesource.com/platform/libcore/+/refs/heads/gingerbread-relea
|
|||||||
is particularly easy to include in our code base and compile.
|
is particularly easy to include in our code base and compile.
|
||||||
|
|
||||||
This solution seems the best fitting and doesn't introduce dependency on Qt.
|
This solution seems the best fitting and doesn't introduce dependency on Qt.
|
||||||
|
Newer Android releases (expecially 11) have introduced multiple restrictions
|
||||||
|
on network information access so we suggest you to prepare different APK for
|
||||||
|
different API level in order to use the `getifaddrs` provided by Android NDK
|
||||||
|
which deal gracefully with those restrictions as soon as available.
|
||||||
|
|
@ -1,9 +1,9 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* libretroshare/src/util: androiddebug.h *
|
|
||||||
* *
|
* *
|
||||||
* libretroshare: retroshare core library *
|
* libretroshare: retroshare core library *
|
||||||
* *
|
* *
|
||||||
* Copyright (C) 2016 Gioacchino Mazzurco <gio@eigenlab.org> *
|
* Copyright (C) 2016-2021 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||||
|
* Copyright (C) 2021 Asociación Civil Altermundi <info@altermundi.net> *
|
||||||
* *
|
* *
|
||||||
* This program is free software: you can redistribute it and/or modify *
|
* This program is free software: you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU Lesser General Public License as *
|
* it under the terms of the GNU Lesser General Public License as *
|
||||||
@ -36,10 +36,10 @@
|
|||||||
* class at the beginning of the main of your program to get them (stdout and
|
* class at the beginning of the main of your program to get them (stdout and
|
||||||
* stderr) on logcat output.
|
* stderr) on logcat output.
|
||||||
*/
|
*/
|
||||||
class AndroidStdIOCatcher
|
class AndroidCoutCerrCatcher
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AndroidStdIOCatcher(const std::string& dTag = "RetroShare",
|
AndroidCoutCerrCatcher(const std::string& dTag = "RetroShare",
|
||||||
android_LogPriority stdout_pri = ANDROID_LOG_INFO,
|
android_LogPriority stdout_pri = ANDROID_LOG_INFO,
|
||||||
android_LogPriority stderr_pri = ANDROID_LOG_ERROR) :
|
android_LogPriority stderr_pri = ANDROID_LOG_ERROR) :
|
||||||
tag(dTag), cout_pri(stdout_pri), cerr_pri(stderr_pri), should_stop(false)
|
tag(dTag), cout_pri(stdout_pri), cerr_pri(stderr_pri), should_stop(false)
|
||||||
@ -63,10 +63,10 @@ public:
|
|||||||
pthread_detach(thr);
|
pthread_detach(thr);
|
||||||
}
|
}
|
||||||
|
|
||||||
~AndroidStdIOCatcher()
|
~AndroidCoutCerrCatcher()
|
||||||
{
|
{
|
||||||
should_stop = true;
|
should_stop = true;
|
||||||
pthread_join(thr, NULL);
|
pthread_join(thr, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -79,11 +79,13 @@ private:
|
|||||||
pthread_t thr;
|
pthread_t thr;
|
||||||
std::atomic<bool> should_stop;
|
std::atomic<bool> should_stop;
|
||||||
|
|
||||||
static void *thread_func(void* instance)
|
static void* thread_func(void* instance)
|
||||||
{
|
{
|
||||||
__android_log_write(ANDROID_LOG_INFO, "RetroShare", "Android debugging start");
|
__android_log_write(
|
||||||
|
ANDROID_LOG_INFO, "RetroShare",
|
||||||
|
"Android standard I/O catcher start" );
|
||||||
|
|
||||||
AndroidStdIOCatcher &i = *static_cast<AndroidStdIOCatcher*>(instance);
|
AndroidCoutCerrCatcher &i = *static_cast<AndroidCoutCerrCatcher*>(instance);
|
||||||
|
|
||||||
std::string out_buf;
|
std::string out_buf;
|
||||||
std::string err_buf;
|
std::string err_buf;
|
||||||
@ -113,9 +115,11 @@ private:
|
|||||||
usleep(10000);
|
usleep(10000);
|
||||||
}
|
}
|
||||||
|
|
||||||
__android_log_write(ANDROID_LOG_INFO, "RetroShare", "Android debugging stop");
|
__android_log_write(
|
||||||
|
ANDROID_LOG_INFO, "RetroShare",
|
||||||
|
"Android standard I/O catcher stop" );
|
||||||
|
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
42
libretroshare/src/rs_android/errorconditionwrap.cpp
Normal file
42
libretroshare/src/rs_android/errorconditionwrap.cpp
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* *
|
||||||
|
* libretroshare: retroshare core library *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2021 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||||
|
* Copyright (C) 2021 Asociación Civil Altermundi <info@altermundi.net> *
|
||||||
|
* *
|
||||||
|
* This program is free software: you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU Lesser General Public License as *
|
||||||
|
* published by the Free Software Foundation, either version 3 of the *
|
||||||
|
* License, or (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU Lesser General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License *
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#include "rs_android/rsjni.hpp"
|
||||||
|
|
||||||
|
namespace jni
|
||||||
|
{
|
||||||
|
Local<Object<RsJni::ErrorConditionWrap>> MakeAnything(
|
||||||
|
ThingToMake<RsJni::ErrorConditionWrap>, JNIEnv& env,
|
||||||
|
const std::error_condition& ec )
|
||||||
|
{
|
||||||
|
auto& clazz = jni::Class<RsJni::ErrorConditionWrap>::Singleton(env);
|
||||||
|
|
||||||
|
static auto method =
|
||||||
|
clazz.GetConstructor<jni::jint, jni::String, jni::String>(env);
|
||||||
|
|
||||||
|
jni::jint value = ec.value();
|
||||||
|
auto message = jni::Make<jni::String>(env, ec.message());
|
||||||
|
auto category = jni::Make<jni::String>(env, ec.category().name());
|
||||||
|
|
||||||
|
return clazz.New(env, method, value, message, category);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
* RetroShare
|
||||||
|
* Copyright (C) 2021 Gioacchino Mazzurco <gio@eigenlab.org>
|
||||||
|
* Copyright (C) 2021 Asociación Civil Altermundi <info@altermundi.net>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* SPDX-FileCopyrightText: Retroshare Team <contact@retroshare.cc>
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.retroshare.service;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
import android.content.Context;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
|
||||||
|
public class AssetHelper
|
||||||
|
{
|
||||||
|
public static boolean copyAsset(
|
||||||
|
Context ctx, String assetPath, String destinationFilePath )
|
||||||
|
{
|
||||||
|
Log.d(TAG, "copyAsset " + assetPath + " -> " + destinationFilePath);
|
||||||
|
|
||||||
|
InputStream in;
|
||||||
|
OutputStream out;
|
||||||
|
|
||||||
|
try { in = ctx.getAssets().open(assetPath); }
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
Log.e(
|
||||||
|
TAG,
|
||||||
|
"Failure opening asset: " + assetPath + " " + e.getMessage() );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try { out = new FileOutputStream(destinationFilePath); }
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
Log.e(
|
||||||
|
TAG,
|
||||||
|
"Failure opening destination: " + destinationFilePath + " " +
|
||||||
|
e.getMessage() );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
byte[] buf = new byte[1024];
|
||||||
|
int len;
|
||||||
|
while ((len = in.read(buf)) > 0) out.write(buf, 0, len);
|
||||||
|
}
|
||||||
|
catch(IOException e)
|
||||||
|
{
|
||||||
|
Log.e(
|
||||||
|
TAG,
|
||||||
|
"Failure coping: " + assetPath + " -> " + destinationFilePath +
|
||||||
|
" " + e.getMessage() );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try { in.close(); }
|
||||||
|
catch(IOException e)
|
||||||
|
{
|
||||||
|
Log.e(TAG, "Failure closing: " + assetPath + " " + e.getMessage() );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try { out.close(); }
|
||||||
|
catch(IOException e)
|
||||||
|
{
|
||||||
|
Log.e(
|
||||||
|
TAG,
|
||||||
|
"Failure closing: " + destinationFilePath + " " +
|
||||||
|
e.getMessage() );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final String TAG = "RetroShare AssetHelper.java";
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* RetroShare
|
||||||
|
* Copyright (C) 2021 Gioacchino Mazzurco <gio@eigenlab.org>
|
||||||
|
* Copyright (C) 2021 Asociación Civil Altermundi <info@altermundi.net>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* SPDX-FileCopyrightText: Retroshare Team <contact@retroshare.cc>
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.retroshare.service;
|
||||||
|
|
||||||
|
public class ErrorConditionWrap
|
||||||
|
{
|
||||||
|
public ErrorConditionWrap(
|
||||||
|
int value, String message, String categoryName )
|
||||||
|
{
|
||||||
|
mValue = value;
|
||||||
|
mMessage = message;
|
||||||
|
mCategoryName = categoryName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int value() { return mValue; }
|
||||||
|
public String message() { return mMessage; }
|
||||||
|
public String categoryName() { return mCategoryName; }
|
||||||
|
|
||||||
|
public boolean toBool() { return mValue != 0; }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{ return String.format("%d", mValue)+" "+mMessage+" [" + mCategoryName+ "]"; }
|
||||||
|
|
||||||
|
private int mValue = 0;
|
||||||
|
private String mMessage;
|
||||||
|
private String mCategoryName;
|
||||||
|
}
|
@ -0,0 +1,138 @@
|
|||||||
|
/*
|
||||||
|
* RetroShare
|
||||||
|
* Copyright (C) 2016-2021 Gioacchino Mazzurco <gio@eigenlab.org>
|
||||||
|
* Copyright (C) 2021 Asociación Civil Altermundi <info@altermundi.net>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* SPDX-FileCopyrightText: Retroshare Team <contact@retroshare.cc>
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.retroshare.service;
|
||||||
|
|
||||||
|
import android.app.Service;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.app.ActivityManager;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class RetroShareServiceAndroid extends Service
|
||||||
|
{
|
||||||
|
public static final int DEFAULT_JSON_API_PORT = 9092;
|
||||||
|
public static final String DEFAULT_JSON_API_BINDING_ADDRESS = "127.0.0.1";
|
||||||
|
|
||||||
|
static { System.loadLibrary("retroshare-service"); }
|
||||||
|
|
||||||
|
public static void start(
|
||||||
|
Context ctx, int jsonApiPort, String jsonApiBindAddress )
|
||||||
|
{
|
||||||
|
Log.d(TAG, "start");
|
||||||
|
Intent intent = new Intent(ctx, RetroShareServiceAndroid.class);
|
||||||
|
intent.putExtra(JSON_API_PORT_KEY, jsonApiPort);
|
||||||
|
intent.putExtra(JSON_API_BIND_ADDRESS_KEY, jsonApiBindAddress);
|
||||||
|
ctx.startService(intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void stop(Context ctx)
|
||||||
|
{
|
||||||
|
Log.d(TAG, "stop");
|
||||||
|
ctx.stopService(new Intent(ctx, RetroShareServiceAndroid.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isRunning(Context ctx)
|
||||||
|
{
|
||||||
|
Log.d(TAG, "isRunning");
|
||||||
|
ActivityManager manager =
|
||||||
|
(ActivityManager) ctx.getSystemService(Context.ACTIVITY_SERVICE);
|
||||||
|
for( ActivityManager.RunningServiceInfo service :
|
||||||
|
manager.getRunningServices(Integer.MAX_VALUE) )
|
||||||
|
if( RetroShareServiceAndroid.class.getName()
|
||||||
|
.equals(service.service.getClassName()) )
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Context getServiceContext()
|
||||||
|
{
|
||||||
|
if(sServiceContext == null)
|
||||||
|
Log.e(TAG, "getServiceContext() called before onCreate");
|
||||||
|
return Objects.requireNonNull(sServiceContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int onStartCommand(
|
||||||
|
Intent intent, int flags, int startId )
|
||||||
|
{
|
||||||
|
if(intent == null)
|
||||||
|
{
|
||||||
|
Log.i(TAG, "onStartCommand called without intent");
|
||||||
|
return Service.START_REDELIVER_INTENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
int jsonApiPort = DEFAULT_JSON_API_PORT;
|
||||||
|
String jsonApiBindAddress = DEFAULT_JSON_API_BINDING_ADDRESS;
|
||||||
|
|
||||||
|
Bundle args = intent.getExtras();
|
||||||
|
if(args.containsKey(JSON_API_PORT_KEY))
|
||||||
|
jsonApiPort = args.getInt(JSON_API_PORT_KEY);
|
||||||
|
if(args.containsKey(JSON_API_BIND_ADDRESS_KEY))
|
||||||
|
jsonApiBindAddress =
|
||||||
|
args.getString(JSON_API_BIND_ADDRESS_KEY);
|
||||||
|
|
||||||
|
ErrorConditionWrap ec = nativeStart(jsonApiPort, jsonApiBindAddress);
|
||||||
|
if(ec.toBool()) Log.e(TAG, "onStartCommand(...) " + ec.toString());
|
||||||
|
|
||||||
|
return super.onStartCommand(intent, flags, startId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate ()
|
||||||
|
{
|
||||||
|
super.onCreate();
|
||||||
|
sServiceContext = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy()
|
||||||
|
{
|
||||||
|
ErrorConditionWrap ec = nativeStop();
|
||||||
|
if(ec.toBool()) Log.e(TAG, "onDestroy() " + ec.toString());
|
||||||
|
sServiceContext = null;
|
||||||
|
super.onDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBinder onBind(Intent arg0) { return null; }
|
||||||
|
|
||||||
|
private static final String JSON_API_PORT_KEY =
|
||||||
|
RetroShareServiceAndroid.class.getCanonicalName() +
|
||||||
|
"/JSON_API_PORT_KEY";
|
||||||
|
|
||||||
|
private static final String JSON_API_BIND_ADDRESS_KEY =
|
||||||
|
RetroShareServiceAndroid.class.getCanonicalName() +
|
||||||
|
"/JSON_API_BIND_ADDRESS_KEY" ;
|
||||||
|
|
||||||
|
private static final String TAG = "RetroShareServiceAndroid.java";
|
||||||
|
|
||||||
|
private static Context sServiceContext;
|
||||||
|
|
||||||
|
protected static native ErrorConditionWrap nativeStart(
|
||||||
|
int jsonApiPort, String jsonApiBindAddress );
|
||||||
|
|
||||||
|
protected static native ErrorConditionWrap nativeStop();
|
||||||
|
}
|
103
libretroshare/src/rs_android/retroshareserviceandroid.cpp
Normal file
103
libretroshare/src/rs_android/retroshareserviceandroid.cpp
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
* RetroShare Service Android
|
||||||
|
* Copyright (C) 2016-2021 Gioacchino Mazzurco <gio@eigenlab.org>
|
||||||
|
* Copyright (C) 2021 Asociación Civil Altermundi <info@altermundi.net>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* SPDX-FileCopyrightText: Retroshare Team <contact@retroshare.cc>
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#include "util/stacktrace.h"
|
||||||
|
#include "retroshare/rsinit.h"
|
||||||
|
#include "retroshare/rsiface.h"
|
||||||
|
#include "util/rsdebug.h"
|
||||||
|
|
||||||
|
#include "rs_android/retroshareserviceandroid.hpp"
|
||||||
|
#include "rs_android/rsjni.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
/*static*/ std::unique_ptr<AndroidCoutCerrCatcher>
|
||||||
|
RetroShareServiceAndroid::sAndroidCoutCerrCatcher = nullptr;
|
||||||
|
|
||||||
|
using ErrorConditionWrap = RsJni::ErrorConditionWrap;
|
||||||
|
|
||||||
|
/*static*/ jni::Local<jni::Object<ErrorConditionWrap>>
|
||||||
|
RetroShareServiceAndroid::start(
|
||||||
|
JNIEnv& env, jni::Class<RetroShareServiceAndroid>&,
|
||||||
|
jni::jint jsonApiPort, const jni::String& jsonApiBindAddress )
|
||||||
|
{
|
||||||
|
if(jsonApiPort < 0 || jsonApiPort > std::numeric_limits<uint16_t>::max())
|
||||||
|
{
|
||||||
|
RS_ERR("Got invalid JSON API port: ", jsonApiPort);
|
||||||
|
return jni::Make<ErrorConditionWrap>(env, std::errc::invalid_argument);
|
||||||
|
}
|
||||||
|
|
||||||
|
RsInfo() << "\n" <<
|
||||||
|
"+================================================================+\n"
|
||||||
|
"| o---o o |\n"
|
||||||
|
"| \\ / - Retroshare Service Android - / \\ |\n"
|
||||||
|
"| o o---o |\n"
|
||||||
|
"+================================================================+"
|
||||||
|
<< std::endl << std::endl;
|
||||||
|
|
||||||
|
sAndroidCoutCerrCatcher = std::make_unique<AndroidCoutCerrCatcher>();
|
||||||
|
|
||||||
|
RsInit::InitRsConfig();
|
||||||
|
RsControl::earlyInitNotificationSystem();
|
||||||
|
|
||||||
|
RsConfigOptions conf;
|
||||||
|
conf.jsonApiPort = static_cast<uint16_t>(jsonApiPort);
|
||||||
|
conf.jsonApiBindAddress = jni::Make<std::string>(env, jsonApiBindAddress);
|
||||||
|
|
||||||
|
// Dirty workaround plugins not supported on Android ATM
|
||||||
|
conf.main_executable_path = " ";
|
||||||
|
|
||||||
|
int initResult = RsInit::InitRetroShare(conf);
|
||||||
|
if(initResult != RS_INIT_OK)
|
||||||
|
{
|
||||||
|
RS_ERR("Retroshare core initalization failed with: ", initResult);
|
||||||
|
return jni::Make<ErrorConditionWrap>(env, std::errc::no_child_process);
|
||||||
|
}
|
||||||
|
|
||||||
|
return jni::Make<ErrorConditionWrap>(env, std::error_condition());
|
||||||
|
}
|
||||||
|
|
||||||
|
jni::Local<jni::Object<ErrorConditionWrap>> RetroShareServiceAndroid::stop(
|
||||||
|
JNIEnv& env, jni::Class<RetroShareServiceAndroid>& )
|
||||||
|
{
|
||||||
|
if(RsControl::instance()->isReady())
|
||||||
|
{
|
||||||
|
RsControl::instance()->rsGlobalShutDown();
|
||||||
|
return jni::Make<ErrorConditionWrap>(env, std::error_condition());
|
||||||
|
}
|
||||||
|
|
||||||
|
sAndroidCoutCerrCatcher.reset();
|
||||||
|
|
||||||
|
return jni::Make<ErrorConditionWrap>(env, std::errc::no_such_process);
|
||||||
|
}
|
||||||
|
|
||||||
|
jni::Local<jni::Object<RetroShareServiceAndroid::Context> >
|
||||||
|
RetroShareServiceAndroid::getAndroidContext(JNIEnv& env)
|
||||||
|
{
|
||||||
|
auto& clazz = jni::Class<RetroShareServiceAndroid>::Singleton(env);
|
||||||
|
static auto method =
|
||||||
|
clazz.GetStaticMethod<jni::Object<RetroShareServiceAndroid::Context>()>(
|
||||||
|
env, "getServiceContext" );
|
||||||
|
return clazz.Call(env, method);
|
||||||
|
}
|
84
libretroshare/src/rs_android/retroshareserviceandroid.hpp
Normal file
84
libretroshare/src/rs_android/retroshareserviceandroid.hpp
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* RetroShare Service Android
|
||||||
|
* Copyright (C) 2016-2021 Gioacchino Mazzurco <gio@eigenlab.org>
|
||||||
|
* Copyright (C) 2021 Asociación Civil Altermundi <info@altermundi.net>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* SPDX-FileCopyrightText: Retroshare Team <contact@retroshare.cc>
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <system_error>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include <jni/jni.hpp>
|
||||||
|
|
||||||
|
#include "rs_android/rsjni.hpp"
|
||||||
|
#include "rs_android/androidcoutcerrcatcher.hpp"
|
||||||
|
|
||||||
|
#include "util/stacktrace.h"
|
||||||
|
|
||||||
|
/** Provide native methods that are registered into corresponding Java class
|
||||||
|
* to start/stop RetroShare with reasonable comfort on Android platform */
|
||||||
|
struct RetroShareServiceAndroid
|
||||||
|
{
|
||||||
|
static constexpr auto Name()
|
||||||
|
{ return "org/retroshare/service/RetroShareServiceAndroid"; }
|
||||||
|
|
||||||
|
using ErrorConditionWrap = RsJni::ErrorConditionWrap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called from RetroShareServiceAndroid Java to init libretroshare
|
||||||
|
* @param[in] env the usual JNI parafernalia
|
||||||
|
* @param[in] jclass the usual JNI parafernalia
|
||||||
|
* @param[in] jsonApiPort port on which JSON API server will listen
|
||||||
|
* @param[in] jsonApiBindAddress binding address of the JSON API server
|
||||||
|
* @note Yeah you read it well we use a full 32 bit signed integer for JSON
|
||||||
|
* API port. This is because Java lack even the minimum decency to implement
|
||||||
|
* unsigned integral types so we need to wrap the port (16 bit unsigned
|
||||||
|
* integer everywhere reasonable) into a full integer and then check at
|
||||||
|
* runtime the value.
|
||||||
|
*/
|
||||||
|
static jni::Local<jni::Object<ErrorConditionWrap>> start(
|
||||||
|
JNIEnv& env, jni::Class<RetroShareServiceAndroid>& jclass,
|
||||||
|
jni::jint jsonApiPort, const jni::String& jsonApiBindAddress );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called from RetroShareServiceAndroid Java to shutdown libretroshare
|
||||||
|
* @param[in] env the usual JNI parafernalia
|
||||||
|
* @param[in] jclass the usual JNI parafernalia
|
||||||
|
*/
|
||||||
|
static jni::Local<jni::Object<ErrorConditionWrap>> stop(
|
||||||
|
JNIEnv& env, jni::Class<RetroShareServiceAndroid>& );
|
||||||
|
|
||||||
|
struct Context
|
||||||
|
{
|
||||||
|
/// JNI parafernalia
|
||||||
|
static constexpr auto Name() { return "android/content/Context"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Return RetroShare Service Android Context
|
||||||
|
static jni::Local<jni::Object<Context>> getAndroidContext(JNIEnv& env);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/** Doesn't involve complex liftime handling stuff better let the runtime
|
||||||
|
* handle costruction (ASAP)/destruction for us */
|
||||||
|
static CrashStackTrace CrashStackTrace;
|
||||||
|
|
||||||
|
/** Involve threads, file descriptors etc. better handle lifetime
|
||||||
|
* explicitely */
|
||||||
|
static std::unique_ptr<AndroidCoutCerrCatcher> sAndroidCoutCerrCatcher;
|
||||||
|
};
|
70
libretroshare/src/rs_android/rsjni.cpp
Normal file
70
libretroshare/src/rs_android/rsjni.cpp
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* RetroShare JNI utilities *
|
||||||
|
* *
|
||||||
|
* libretroshare: retroshare core library *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2021 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||||
|
* Copyright (C) 2021 Asociación Civil Altermundi <info@altermundi.net> *
|
||||||
|
* *
|
||||||
|
* This program is free software: you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU Lesser General Public License as *
|
||||||
|
* published by the Free Software Foundation, either version 3 of the *
|
||||||
|
* License, or (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU Lesser General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License *
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#include "rs_android/rsjni.hpp"
|
||||||
|
#include "rs_android/retroshareserviceandroid.hpp"
|
||||||
|
|
||||||
|
rs_view_ptr<JavaVM> RsJni::mJvm = nullptr;
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT jint JNICALL JNI_OnLoad_retroshare(JavaVM* vm, void*)
|
||||||
|
{
|
||||||
|
RS_DBG(vm);
|
||||||
|
|
||||||
|
RsJni::mJvm = vm;
|
||||||
|
|
||||||
|
jni::JNIEnv& env { jni::GetEnv(*vm) };
|
||||||
|
|
||||||
|
/** Ensure singleton refereces to our own Java classes are inizialized here
|
||||||
|
* because default Java class loader which is the one accessible by native
|
||||||
|
* threads which is not main even if attached, is not capable to find them.
|
||||||
|
* https://stackoverflow.com/questions/20752352/classnotfoundexception-when-finding-a-class-in-jni-background-thread
|
||||||
|
* https://groups.google.com/g/android-ndk/c/2gkr1mXKn_E */
|
||||||
|
jni::Class<RsJni::AssetHelper>::Singleton(env);
|
||||||
|
jni::Class<RsJni::ErrorConditionWrap>::Singleton(env);
|
||||||
|
|
||||||
|
jni::RegisterNatives(
|
||||||
|
env, *jni::Class<RetroShareServiceAndroid>::Singleton(env),
|
||||||
|
jni::MakeNativeMethod<
|
||||||
|
decltype(&RetroShareServiceAndroid::start),
|
||||||
|
&RetroShareServiceAndroid::start >("nativeStart"),
|
||||||
|
jni::MakeNativeMethod<
|
||||||
|
decltype(&RetroShareServiceAndroid::stop),
|
||||||
|
&RetroShareServiceAndroid::stop >("nativeStop")
|
||||||
|
);
|
||||||
|
|
||||||
|
return jni::Unwrap(jni::jni_version_1_2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef RS_LIBRETROSHARE_EXPORT_JNI_ONLOAD
|
||||||
|
/** If libretroshare is linked statically to other components which already
|
||||||
|
* export JNI_OnLoad then a symbol clash may happen
|
||||||
|
* if RS_LIBRETROSHARE_EXPORT_JNI_ONLOAD is defined.
|
||||||
|
* @see JNI_OnLoad_retroshare should instead be called from the exported
|
||||||
|
* JNI_OnLoad */
|
||||||
|
extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* _reserved)
|
||||||
|
{
|
||||||
|
RS_DBG(vm);
|
||||||
|
return JNI_OnLoad_retroshare(vm, _reserved);
|
||||||
|
}
|
||||||
|
#endif // def RS_LIBRETROSHARE_EXPORT_JNI_ONLOAD
|
90
libretroshare/src/rs_android/rsjni.hpp
Normal file
90
libretroshare/src/rs_android/rsjni.hpp
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* RetroShare JNI utilities *
|
||||||
|
* *
|
||||||
|
* libretroshare: retroshare core library *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2021 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||||
|
* Copyright (C) 2021 Asociación Civil Altermundi <info@altermundi.net> *
|
||||||
|
* *
|
||||||
|
* This program is free software: you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU Lesser General Public License as *
|
||||||
|
* published by the Free Software Foundation, either version 3 of the *
|
||||||
|
* License, or (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU Lesser General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License *
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
*******************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <system_error>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
#include <jni/jni.hpp>
|
||||||
|
|
||||||
|
#include "util/rsmemory.h"
|
||||||
|
#include "util/cxx23retrocompat.h"
|
||||||
|
|
||||||
|
|
||||||
|
/** Store JVM pointer safely and register native methods */
|
||||||
|
extern "C" JNIEXPORT jint JNICALL JNI_OnLoad_retroshare(JavaVM* vm, void*);
|
||||||
|
|
||||||
|
|
||||||
|
/** Provide library wide JVM access with some safe measures
|
||||||
|
* The JVM pointer is set properly by @see JNI_OnLoad_retroshare
|
||||||
|
*/
|
||||||
|
class RsJni
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static inline JavaVM& getVM()
|
||||||
|
{
|
||||||
|
if(!mJvm) // [[unlikely]]
|
||||||
|
{
|
||||||
|
RS_FATAL( "Attempt to access JVM before JNI_OnLoad_retroshare ",
|
||||||
|
std::errc::bad_address );
|
||||||
|
print_stacktrace();
|
||||||
|
std::exit(std::to_underlying(std::errc::bad_address));
|
||||||
|
}
|
||||||
|
|
||||||
|
return *mJvm;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend jint JNI_OnLoad_retroshare(JavaVM* vm, void*);
|
||||||
|
|
||||||
|
/** Provide a comfortable way to access Android package assets like
|
||||||
|
* bdboot.txt from C++ */
|
||||||
|
struct AssetHelper
|
||||||
|
{
|
||||||
|
static constexpr auto Name()
|
||||||
|
{ return "org/retroshare/service/AssetHelper"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Provide a comfortable way to propagate C++ error_conditions to Java
|
||||||
|
* callers */
|
||||||
|
struct ErrorConditionWrap
|
||||||
|
{
|
||||||
|
static constexpr auto Name()
|
||||||
|
{ return "org/retroshare/service/ErrorConditionWrap"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
static rs_view_ptr<JavaVM> mJvm;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
namespace jni
|
||||||
|
{
|
||||||
|
/** Provides idiomatic way of creating instances via
|
||||||
|
@code{.cpp}
|
||||||
|
jni::Make<ErrorConditionWrap>(env, std::error_condition());
|
||||||
|
@endcode */
|
||||||
|
jni::Local<jni::Object<RsJni::ErrorConditionWrap>>
|
||||||
|
MakeAnything(
|
||||||
|
jni::ThingToMake<RsJni::ErrorConditionWrap>, JNIEnv& env,
|
||||||
|
const std::error_condition& ec );
|
||||||
|
}
|
@ -32,12 +32,12 @@
|
|||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <system_error>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "retroshare/rsinit.h"
|
#include "retroshare/rsinit.h"
|
||||||
#include "rsaccounts.h"
|
#include "rsaccounts.h"
|
||||||
|
#include "util/rsdebug.h"
|
||||||
#include "util/rsdir.h"
|
#include "util/rsdir.h"
|
||||||
#include "util/rsstring.h"
|
#include "util/rsstring.h"
|
||||||
#include "util/folderiterator.h"
|
#include "util/folderiterator.h"
|
||||||
@ -48,6 +48,11 @@
|
|||||||
|
|
||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
# include "rs_android/rsjni.hpp"
|
||||||
|
# include "rs_android/retroshareserviceandroid.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
// Global singleton declaration of data.
|
// Global singleton declaration of data.
|
||||||
RsAccountsDetail* RsAccounts::rsAccountsDetails = nullptr;
|
RsAccountsDetail* RsAccounts::rsAccountsDetails = nullptr;
|
||||||
|
|
||||||
@ -328,22 +333,7 @@ bool RsAccountsDetail::defaultBaseDirectory()
|
|||||||
{
|
{
|
||||||
std::string basedir;
|
std::string basedir;
|
||||||
|
|
||||||
/******************************** WINDOWS/UNIX SPECIFIC PART ******************/
|
#ifdef WINDOWS_SYS
|
||||||
#ifndef WINDOWS_SYS
|
|
||||||
|
|
||||||
// unix: homedir + /.retroshare
|
|
||||||
char *h = getenv("HOME");
|
|
||||||
if (h == NULL)
|
|
||||||
{
|
|
||||||
std::cerr << "defaultBaseDirectory() Error: cannot determine $HOME dir"
|
|
||||||
<< std::endl;
|
|
||||||
return false ;
|
|
||||||
}
|
|
||||||
|
|
||||||
basedir = h;
|
|
||||||
basedir += "/.retroshare";
|
|
||||||
|
|
||||||
#else
|
|
||||||
if (RsInit::isPortable())
|
if (RsInit::isPortable())
|
||||||
{
|
{
|
||||||
// use directory "Data" in portable version
|
// use directory "Data" in portable version
|
||||||
@ -375,13 +365,53 @@ bool RsAccountsDetail::defaultBaseDirectory()
|
|||||||
}
|
}
|
||||||
basedir += "\\RetroShare";
|
basedir += "\\RetroShare";
|
||||||
}
|
}
|
||||||
#endif
|
#elif defined (__ANDROID__) // def WINDOWS_SYS
|
||||||
/******************************** WINDOWS/UNIX SPECIFIC PART ******************/
|
|
||||||
|
struct ApplicationInfo
|
||||||
|
{
|
||||||
|
static constexpr auto Name()
|
||||||
|
{ return "android/content/pm/ApplicationInfo"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
auto uenv = jni::GetAttachedEnv(RsJni::getVM());
|
||||||
|
JNIEnv& env = *uenv;
|
||||||
|
auto androidContext = RetroShareServiceAndroid::getAndroidContext(env);
|
||||||
|
auto& contextClass =
|
||||||
|
jni::Class<RetroShareServiceAndroid::Context>::Singleton(env);
|
||||||
|
|
||||||
|
auto& applicationInfoClass = jni::Class<ApplicationInfo>::Singleton(env);
|
||||||
|
|
||||||
|
auto getApplicationInfo =
|
||||||
|
contextClass.GetMethod<jni::Object<ApplicationInfo> ()>(
|
||||||
|
env, "getApplicationInfo" );
|
||||||
|
|
||||||
|
auto applicationInfo = androidContext.Call(env, getApplicationInfo);
|
||||||
|
|
||||||
|
auto dataDirField = jni::Field<ApplicationInfo, jni::String>(
|
||||||
|
env, applicationInfoClass, "dataDir" );
|
||||||
|
|
||||||
|
jni::Local<jni::String> dataDir = applicationInfo.Get<jni::String>(
|
||||||
|
env, dataDirField );
|
||||||
|
|
||||||
|
basedir = jni::Make<std::string>(env, dataDir) + "/.retroshare/";
|
||||||
|
|
||||||
|
#else // def WINDOWS_SYS, if defined (__ANDROID__)
|
||||||
|
// unix: homedir + /.retroshare
|
||||||
|
char* h = getenv("HOME");
|
||||||
|
if(h == nullptr)
|
||||||
|
{
|
||||||
|
RS_ERR("cannot determine $HOME dir");
|
||||||
|
return false ;
|
||||||
|
}
|
||||||
|
|
||||||
|
basedir = h;
|
||||||
|
basedir += "/.retroshare";
|
||||||
|
#endif // def WINDOWS_SYS
|
||||||
|
|
||||||
/* store to class variable */
|
/* store to class variable */
|
||||||
mBaseDirectory = basedir;
|
mBaseDirectory = basedir;
|
||||||
std::cerr << "defaultBaseDirectory() = " << mBaseDirectory;
|
|
||||||
std::cerr << std::endl;
|
RS_INFO(mBaseDirectory);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -941,6 +971,11 @@ bool RsAccountsDetail::exportIdentityToString(
|
|||||||
|
|
||||||
bool RsAccountsDetail::copyGnuPGKeyrings()
|
bool RsAccountsDetail::copyGnuPGKeyrings()
|
||||||
{
|
{
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
RS_ERR(std::errc::not_supported);
|
||||||
|
print_stacktrace();
|
||||||
|
return false;
|
||||||
|
#else
|
||||||
std::string pgp_dir = PathPGPDirectory() ;
|
std::string pgp_dir = PathPGPDirectory() ;
|
||||||
|
|
||||||
if(!RsDirUtil::checkCreateDirectory(pgp_dir))
|
if(!RsDirUtil::checkCreateDirectory(pgp_dir))
|
||||||
@ -992,6 +1027,7 @@ bool RsAccountsDetail::copyGnuPGKeyrings()
|
|||||||
}
|
}
|
||||||
|
|
||||||
return true ;
|
return true ;
|
||||||
|
#endif // def __ANDROID__
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -32,8 +32,9 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
# include <QFile> // To install bdboot.txt
|
# include <jni/jni.hpp>
|
||||||
# include <QString> // for QString::fromStdString(...)
|
# include "rs_android/rsjni.hpp"
|
||||||
|
# include "rs_android/retroshareserviceandroid.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "util/argstream.h"
|
#include "util/argstream.h"
|
||||||
@ -194,7 +195,7 @@ static const int SSLPWD_LEN = 64;
|
|||||||
|
|
||||||
void RsInit::InitRsConfig()
|
void RsInit::InitRsConfig()
|
||||||
{
|
{
|
||||||
RsInfo() << " libretroshare version: " << RS_HUMAN_READABLE_VERSION
|
RsInfo() << "libretroshare version: " << RS_HUMAN_READABLE_VERSION
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
|
||||||
rsInitConfig = new RsInitConfig;
|
rsInitConfig = new RsInitConfig;
|
||||||
@ -1011,32 +1012,32 @@ int RsServer::StartupRetroShare()
|
|||||||
uint64_t tmp_size ;
|
uint64_t tmp_size ;
|
||||||
if (!RsDirUtil::checkFile(bootstrapfile,tmp_size,true))
|
if (!RsDirUtil::checkFile(bootstrapfile,tmp_size,true))
|
||||||
{
|
{
|
||||||
std::cerr << "DHT bootstrap file not in ConfigDir: " << bootstrapfile
|
RS_INFO("DHT bootstrap file not in ConfigDir: ", bootstrapfile);
|
||||||
<< std::endl;
|
|
||||||
#ifdef __ANDROID__
|
|
||||||
QFile bdbootRF("assets:/values/bdboot.txt");
|
|
||||||
if(!bdbootRF.open(QIODevice::ReadOnly | QIODevice::Text))
|
|
||||||
std::cerr << __PRETTY_FUNCTION__
|
|
||||||
<< " bdbootRF(assets:/values/bdboot.txt).open(...) fail: "
|
|
||||||
<< bdbootRF.errorString().toStdString() << std::endl;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
QFile bdbootCF(QString::fromStdString(bootstrapfile));
|
|
||||||
if(!bdbootCF.open(QIODevice::WriteOnly | QIODevice::Text))
|
|
||||||
std::cerr << __PRETTY_FUNCTION__ << " bdbootCF("
|
|
||||||
<< bootstrapfile << ").open(...) fail: "
|
|
||||||
<< bdbootRF.errorString().toStdString() << std::endl;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bdbootCF.write(bdbootRF.readAll());
|
|
||||||
bdbootCF.close();
|
|
||||||
std::cerr << "Installed DHT bootstrap file not in ConfigDir: "
|
|
||||||
<< bootstrapfile << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
bdbootRF.close();
|
#ifdef __ANDROID__
|
||||||
}
|
auto uenv = jni::GetAttachedEnv(RsJni::getVM());
|
||||||
#else
|
JNIEnv& env = *uenv;
|
||||||
|
|
||||||
|
using AContext = RetroShareServiceAndroid::Context;
|
||||||
|
|
||||||
|
auto& assetHelperClass = jni::Class<RsJni::AssetHelper>::Singleton(env);
|
||||||
|
|
||||||
|
static auto copyAsset =
|
||||||
|
assetHelperClass.GetStaticMethod<
|
||||||
|
jni::jboolean(jni::Object<AContext>, jni::String, jni::String)>(
|
||||||
|
env, "copyAsset" );
|
||||||
|
|
||||||
|
auto androidContext = RetroShareServiceAndroid::getAndroidContext(env);
|
||||||
|
|
||||||
|
jni::jboolean result = assetHelperClass.Call(
|
||||||
|
env, copyAsset,
|
||||||
|
androidContext,
|
||||||
|
jni::Make<jni::String>(env, "values/bdboot.txt"),
|
||||||
|
jni::Make<jni::String>(env, bootstrapfile) );
|
||||||
|
|
||||||
|
if(!result) RS_ERR("Failure installing ", bootstrapfile);
|
||||||
|
|
||||||
|
#else // def __ANDROID__
|
||||||
std::cerr << "Checking for Installation DHT bootstrap file " << installfile << std::endl;
|
std::cerr << "Checking for Installation DHT bootstrap file " << installfile << std::endl;
|
||||||
if ((installfile != "") && (RsDirUtil::checkFile(installfile,tmp_size)))
|
if ((installfile != "") && (RsDirUtil::checkFile(installfile,tmp_size)))
|
||||||
{
|
{
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* RetroShare Broadcast Domain Discovery *
|
* RetroShare Broadcast Domain Discovery *
|
||||||
* *
|
* *
|
||||||
* Copyright (C) 2019 Gioacchino Mazzurco <gio@altermundi.net> *
|
* Copyright (C) 2019-2021 Gioacchino Mazzurco <gio@altermundi.net> *
|
||||||
|
* Copyright (C) 2019-2021 Asociación Civil Altermundi <info@altermundi.net> *
|
||||||
* *
|
* *
|
||||||
* This program is free software: you can redistribute it and/or modify *
|
* This program is free software: you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU Lesser General Public License as *
|
* it under the terms of the GNU Lesser General Public License as *
|
||||||
@ -25,16 +26,17 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
|
||||||
# include <QtAndroid>
|
|
||||||
#endif // def __ANDROID__
|
|
||||||
|
|
||||||
#include "services/broadcastdiscoveryservice.h"
|
#include "services/broadcastdiscoveryservice.h"
|
||||||
#include "retroshare/rspeers.h"
|
#include "retroshare/rspeers.h"
|
||||||
#include "serialiser/rsserializable.h"
|
#include "serialiser/rsserializable.h"
|
||||||
#include "serialiser/rsserializer.h"
|
#include "serialiser/rsserializer.h"
|
||||||
#include "retroshare/rsevents.h"
|
#include "retroshare/rsevents.h"
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
# include "rs_android/retroshareserviceandroid.hpp"
|
||||||
|
#endif // def __ANDROID__
|
||||||
|
|
||||||
|
|
||||||
/*extern*/ RsBroadcastDiscovery* rsBroadcastDiscovery = nullptr;
|
/*extern*/ RsBroadcastDiscovery* rsBroadcastDiscovery = nullptr;
|
||||||
|
|
||||||
struct BroadcastDiscoveryPack : RsSerializable
|
struct BroadcastDiscoveryPack : RsSerializable
|
||||||
@ -99,7 +101,7 @@ BroadcastDiscoveryService::BroadcastDiscoveryService(
|
|||||||
if(mRsPeers.isHiddenNode(mRsPeers.getOwnId())) return;
|
if(mRsPeers.isHiddenNode(mRsPeers.getOwnId())) return;
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
createMulticastLock();
|
createAndroidMulticastLock();
|
||||||
#endif // def __ANDROID__
|
#endif // def __ANDROID__
|
||||||
|
|
||||||
enableMulticastListening();
|
enableMulticastListening();
|
||||||
@ -228,19 +230,47 @@ RsBroadcastDiscoveryResult BroadcastDiscoveryService::createResult(
|
|||||||
bool BroadcastDiscoveryService::isMulticastListeningEnabled()
|
bool BroadcastDiscoveryService::isMulticastListeningEnabled()
|
||||||
{
|
{
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
return assertMulticastLockIsvalid() &&
|
if(!mAndroidWifiMulticastLock)
|
||||||
mWifiMulticastLock.callMethod<jboolean>("isHeld");
|
{
|
||||||
#endif // def __ANDROID__
|
RS_ERR("Android multicast lock not initialized!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto uenv = jni::GetAttachedEnv(RsJni::getVM());
|
||||||
|
JNIEnv& env = *uenv;
|
||||||
|
auto& multicastLockClass = jni::Class<AndroidMulticastLock>::Singleton(env);
|
||||||
|
|
||||||
|
auto isHeld =
|
||||||
|
multicastLockClass.GetMethod<jni::jboolean()>(
|
||||||
|
env, "isHeld" );
|
||||||
|
|
||||||
|
return mAndroidWifiMulticastLock.Call(env, isHeld);
|
||||||
|
#else if // def __ANDROID__
|
||||||
return true;
|
return true;
|
||||||
|
#endif // def __ANDROID__
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BroadcastDiscoveryService::enableMulticastListening()
|
bool BroadcastDiscoveryService::enableMulticastListening()
|
||||||
{
|
{
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
if(assertMulticastLockIsvalid() && !isMulticastListeningEnabled())
|
if(!mAndroidWifiMulticastLock)
|
||||||
{
|
{
|
||||||
mWifiMulticastLock.callMethod<void>("acquire");
|
RS_ERR("Android multicast lock not initialized!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!isMulticastListeningEnabled())
|
||||||
|
{
|
||||||
|
auto uenv = jni::GetAttachedEnv(RsJni::getVM());
|
||||||
|
JNIEnv& env = *uenv;
|
||||||
|
auto& multicastLockClass = jni::Class<AndroidMulticastLock>::Singleton(env);
|
||||||
|
|
||||||
|
auto acquire =
|
||||||
|
multicastLockClass.GetMethod<void()>(
|
||||||
|
env, "acquire" );
|
||||||
|
|
||||||
|
mAndroidWifiMulticastLock.Call(env, acquire);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif // def __ANDROID__
|
#endif // def __ANDROID__
|
||||||
@ -251,9 +281,24 @@ bool BroadcastDiscoveryService::enableMulticastListening()
|
|||||||
bool BroadcastDiscoveryService::disableMulticastListening()
|
bool BroadcastDiscoveryService::disableMulticastListening()
|
||||||
{
|
{
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
if(assertMulticastLockIsvalid() && isMulticastListeningEnabled())
|
if(!mAndroidWifiMulticastLock)
|
||||||
{
|
{
|
||||||
mWifiMulticastLock.callMethod<void>("release");
|
RS_ERR("Android multicast lock not initialized!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isMulticastListeningEnabled())
|
||||||
|
{
|
||||||
|
auto uenv = jni::GetAttachedEnv(RsJni::getVM());
|
||||||
|
JNIEnv& env = *uenv;
|
||||||
|
auto& multicastLockClass = jni::Class<AndroidMulticastLock>::Singleton(env);
|
||||||
|
|
||||||
|
auto release =
|
||||||
|
multicastLockClass.GetMethod<void()>(
|
||||||
|
env, "release" );
|
||||||
|
|
||||||
|
mAndroidWifiMulticastLock.Call(env, release);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif // def __ANDROID__
|
#endif // def __ANDROID__
|
||||||
@ -262,56 +307,57 @@ bool BroadcastDiscoveryService::disableMulticastListening()
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
bool BroadcastDiscoveryService::createMulticastLock()
|
|
||||||
|
bool BroadcastDiscoveryService::createAndroidMulticastLock()
|
||||||
{
|
{
|
||||||
Dbg2() << __PRETTY_FUNCTION__ << std::endl;
|
if(mAndroidWifiMulticastLock)
|
||||||
|
|
||||||
constexpr auto fname = __PRETTY_FUNCTION__;
|
|
||||||
const auto failure = [&](const std::string& err)
|
|
||||||
{
|
{
|
||||||
RsErr() << fname << " " << err << std::endl;
|
RS_ERR("Android multicast lock is already initialized");
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
if(mWifiMulticastLock.isValid())
|
|
||||||
return failure("mWifiMulticastLock is already initialized");
|
|
||||||
|
|
||||||
QAndroidJniObject context = QtAndroid::androidContext();
|
|
||||||
if(!context.isValid())
|
|
||||||
return failure("Cannot retrieve Android context");
|
|
||||||
|
|
||||||
QAndroidJniObject WIFI_SERVICE = QAndroidJniObject::getStaticObjectField(
|
|
||||||
"android.content.Context", "WIFI_SERVICE", "Ljava/lang/String;");
|
|
||||||
if(!WIFI_SERVICE.isValid())
|
|
||||||
return failure("Cannot retrieve Context.WIFI_SERVICE value");
|
|
||||||
|
|
||||||
QAndroidJniObject wifiManager = context.callObjectMethod(
|
|
||||||
"getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;",
|
|
||||||
WIFI_SERVICE.object<jstring>() );
|
|
||||||
if(!wifiManager.isValid())
|
|
||||||
return failure("Cannot retrieve Android Wifi Manager");
|
|
||||||
|
|
||||||
mWifiMulticastLock = wifiManager.callObjectMethod(
|
|
||||||
"createMulticastLock",
|
|
||||||
"(Ljava/lang/String;)Landroid/net/wifi/WifiManager$MulticastLock;",
|
|
||||||
QAndroidJniObject::fromString(fname).object<jstring>() );
|
|
||||||
if(!mWifiMulticastLock.isValid())
|
|
||||||
return failure("Cannot create WifiManager.MulticastLock");
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BroadcastDiscoveryService::assertMulticastLockIsvalid()
|
|
||||||
{
|
|
||||||
if(!mWifiMulticastLock.isValid())
|
|
||||||
{
|
|
||||||
RsErr() << __PRETTY_FUNCTION__ << " mWifiMulticastLock is invalid!"
|
|
||||||
<< std::endl;
|
|
||||||
print_stacktrace();
|
print_stacktrace();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto uenv = jni::GetAttachedEnv(RsJni::getVM());
|
||||||
|
JNIEnv& env = *uenv;
|
||||||
|
|
||||||
|
using AContextTag = RetroShareServiceAndroid::Context;
|
||||||
|
using AContext = jni::Class<AContextTag>;
|
||||||
|
static auto& contextClass = AContext::Singleton(env);
|
||||||
|
|
||||||
|
auto wifiServiceField = jni::StaticField<AContextTag, jni::String>(
|
||||||
|
env, contextClass, "WIFI_SERVICE");
|
||||||
|
|
||||||
|
jni::Local<jni::String> WIFI_SERVICE = contextClass.Get(
|
||||||
|
env, wifiServiceField );
|
||||||
|
|
||||||
|
auto androidContext = RetroShareServiceAndroid::getAndroidContext(env);
|
||||||
|
|
||||||
|
auto getSystemService =
|
||||||
|
contextClass.GetMethod<jni::Object<jni::ObjectTag> (jni::String)>(
|
||||||
|
env, "getSystemService" );
|
||||||
|
|
||||||
|
struct WifiManager
|
||||||
|
{ static constexpr auto Name() { return "android/net/wifi/WifiManager"; } };
|
||||||
|
|
||||||
|
auto& wifiManagerClass = jni::Class<WifiManager>::Singleton(env);
|
||||||
|
|
||||||
|
auto wifiManager = jni::Cast<WifiManager>(
|
||||||
|
env, wifiManagerClass,
|
||||||
|
androidContext.Call(env, getSystemService, WIFI_SERVICE) );
|
||||||
|
|
||||||
|
auto createMulticastLock =
|
||||||
|
wifiManagerClass.GetMethod<jni::Object<AndroidMulticastLock>(jni::String)>(
|
||||||
|
env, "createMulticastLock" );
|
||||||
|
|
||||||
|
mAndroidWifiMulticastLock = jni::NewGlobal(
|
||||||
|
env, wifiManager.Call(
|
||||||
|
env, createMulticastLock,
|
||||||
|
jni::Make<jni::String>(
|
||||||
|
env, "RetroShare BroadcastDiscoveryService" ) ) );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // def __ANDROID__
|
#endif // def __ANDROID__
|
||||||
|
|
||||||
RsBroadcastDiscovery::~RsBroadcastDiscovery() = default;
|
RsBroadcastDiscovery::~RsBroadcastDiscovery() = default;
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* RetroShare Broadcast Domain Discovery *
|
* RetroShare Broadcast Domain Discovery *
|
||||||
* *
|
* *
|
||||||
* Copyright (C) 2019 Gioacchino Mazzurco <gio@altermundi.net> *
|
* Copyright (C) 2019-2021 Gioacchino Mazzurco <gio@altermundi.net> *
|
||||||
|
* Copyright (C) 2019-2021 Asociación Civil Altermundi <info@altermundi.net> *
|
||||||
* *
|
* *
|
||||||
* This program is free software: you can redistribute it and/or modify *
|
* This program is free software: you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU Lesser General Public License as *
|
* it under the terms of the GNU Lesser General Public License as *
|
||||||
@ -27,14 +28,16 @@
|
|||||||
|
|
||||||
#include <udp_discovery_peer.hpp>
|
#include <udp_discovery_peer.hpp>
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
|
||||||
# include <QtAndroidExtras/QAndroidJniObject>
|
|
||||||
#endif // def __ANDROID__
|
|
||||||
|
|
||||||
#include "retroshare/rsbroadcastdiscovery.h"
|
#include "retroshare/rsbroadcastdiscovery.h"
|
||||||
#include "util/rsthreads.h"
|
#include "util/rsthreads.h"
|
||||||
#include "util/rsdebug.h"
|
#include "util/rsdebug.h"
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
# include <jni/jni.hpp>
|
||||||
|
# include "rs_android/rsjni.hpp"
|
||||||
|
#endif // def __ANDROID__
|
||||||
|
|
||||||
|
|
||||||
namespace UDC = udpdiscovery;
|
namespace UDC = udpdiscovery;
|
||||||
class RsPeers;
|
class RsPeers;
|
||||||
|
|
||||||
@ -42,7 +45,7 @@ class BroadcastDiscoveryService :
|
|||||||
public RsBroadcastDiscovery, public RsTickingThread
|
public RsBroadcastDiscovery, public RsTickingThread
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BroadcastDiscoveryService(RsPeers& pRsPeers);
|
explicit BroadcastDiscoveryService(RsPeers& pRsPeers);
|
||||||
~BroadcastDiscoveryService() override;
|
~BroadcastDiscoveryService() override;
|
||||||
|
|
||||||
/// @see RsBroadcastDiscovery
|
/// @see RsBroadcastDiscovery
|
||||||
@ -71,26 +74,27 @@ protected:
|
|||||||
std::map<UDC::IpPort, std::string> mDiscoveredData;
|
std::map<UDC::IpPort, std::string> mDiscoveredData;
|
||||||
RsMutex mDiscoveredDataMutex;
|
RsMutex mDiscoveredDataMutex;
|
||||||
|
|
||||||
RsPeers& mRsPeers; // TODO: std::shared_ptr<RsPeers> mRsPeers;
|
RsPeers& mRsPeers;
|
||||||
|
|
||||||
RsBroadcastDiscoveryResult createResult(
|
RsBroadcastDiscoveryResult createResult(
|
||||||
const UDC::IpPort& ipp, const std::string& uData );
|
const UDC::IpPort& ipp, const std::string& uData );
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
/** Android WifiManager.MulticastLock */
|
struct AndroidMulticastLock
|
||||||
QAndroidJniObject mWifiMulticastLock;
|
{
|
||||||
|
static constexpr auto Name()
|
||||||
|
{ return "android/net/wifi/WifiManager$MulticastLock"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
jni::Global<jni::Object<AndroidMulticastLock>> mAndroidWifiMulticastLock;
|
||||||
|
|
||||||
/** Initialize the wifi multicast lock without acquiring it
|
/** Initialize the wifi multicast lock without acquiring it
|
||||||
* Needed to enable multicast listening in Android, for RetroShare broadcast
|
* Needed to enable multicast listening in Android, for RetroShare broadcast
|
||||||
* discovery inspired by:
|
* discovery inspired by:
|
||||||
* https://github.com/flutter/flutter/issues/16335#issuecomment-420547860
|
* https://github.com/flutter/flutter/issues/16335#issuecomment-420547860
|
||||||
*/
|
*/
|
||||||
bool createMulticastLock();
|
bool createAndroidMulticastLock();
|
||||||
|
#endif
|
||||||
/** Return false if mWifiMulticastLock is invalid and print error messages */
|
|
||||||
bool assertMulticastLockIsvalid();
|
|
||||||
|
|
||||||
#endif // def __ANDROID__
|
|
||||||
|
|
||||||
RS_SET_CONTEXT_DEBUG_LEVEL(3)
|
RS_SET_CONTEXT_DEBUG_LEVEL(3)
|
||||||
};
|
};
|
||||||
|
@ -111,14 +111,7 @@ PRE_TARGETDEPS += $$pretargetStaticLibs(sLibs)
|
|||||||
LIBS += $$linkDynamicLibs(dLibs)
|
LIBS += $$linkDynamicLibs(dLibs)
|
||||||
|
|
||||||
android-* {
|
android-* {
|
||||||
CONFIG *= qt
|
INCLUDEPATH *= $$clean_path($${RS_SRC_PATH}/supportlibs/jni.hpp/include/)
|
||||||
|
|
||||||
lessThan(ANDROID_API_VERSION, 24) {
|
|
||||||
## @See: android_ifaddrs/README.adoc
|
|
||||||
contains(DEFINES, LIBRETROSHARE_ANDROID_IFADDRS_QT) {
|
|
||||||
QT *= network
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
################################### Pkg-Config Stuff #############################
|
################################### Pkg-Config Stuff #############################
|
||||||
|
@ -2,9 +2,9 @@
|
|||||||
<manifest
|
<manifest
|
||||||
package="org.retroshare.service"
|
package="org.retroshare.service"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:versionName="0.6.4" android:versionCode="1"
|
android:versionName="0.6.6" android:versionCode="1"
|
||||||
android:installLocation="auto">
|
android:installLocation="auto">
|
||||||
<application android:name="org.qtproject.qt5.android.bindings.QtApplication" android:hardwareAccelerated="true" android:label="RetroShare" android:icon="@drawable/retroshare_service_128x128">
|
<application android:label="RetroShare" android:icon="@drawable/retroshare_service_128x128">
|
||||||
<activity
|
<activity
|
||||||
android:name=".RetroShareServiceControlActivity"
|
android:name=".RetroShareServiceControlActivity"
|
||||||
android:label="RetroShare" >
|
android:label="RetroShare" >
|
||||||
@ -14,59 +14,81 @@
|
|||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<receiver android:name=".BootCompletedReceiver" android:enabled="true">
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.BOOT_COMPLETED"/>
|
|
||||||
</intent-filter>
|
|
||||||
</receiver>
|
|
||||||
|
|
||||||
<receiver android:name=".AppUpdatedReceiver" android:enabled="true">
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.MY_PACKAGE_REPLACED"/>
|
|
||||||
</intent-filter>
|
|
||||||
</receiver>
|
|
||||||
|
|
||||||
<!-- For adding service(s) please check:
|
|
||||||
++ https://wiki.qt.io/AndroidServices -->
|
|
||||||
<service android:name=".RetroShareServiceAndroid" android:process=":rs" android:label="RetroShare Service" android:exported="true">
|
<service android:name=".RetroShareServiceAndroid" android:process=":rs" android:label="RetroShare Service" android:exported="true">
|
||||||
<!-- android:exported="true" Added to be able to run the service
|
<!-- android:exported="true" Added to be able to run the service
|
||||||
++ from adb shell
|
++ from adb shell
|
||||||
++ android:process=":rs" is needed to force the service to run on
|
++ android:process=":rs" is needed to force the service to run on
|
||||||
++ a separate process than the Activity -->
|
++ a separate process than the Activity -->
|
||||||
|
|
||||||
|
<!-- Background running -->
|
||||||
|
<meta-data android:name="android.app.background_running" android:value="true"/>
|
||||||
|
<!-- Background running -->
|
||||||
|
|
||||||
|
<![CDATA[
|
||||||
<!-- Qt Application to launch -->
|
<!-- Qt Application to launch -->
|
||||||
<meta-data android:name="android.app.lib_name" android:value="retroshare-service"/>
|
<!-- <meta-data android:name="android.app.lib_name" android:value="retroshare-service"/> -->
|
||||||
|
|
||||||
<!-- Ministro -->
|
<!-- Ministro -->
|
||||||
<meta-data android:name="android.app.qt_sources_resource_id" android:resource="@array/qt_sources"/>
|
<meta-data android:name="android.app.qt_sources_resource_id" android:resource="@array/qt_sources"/>
|
||||||
<meta-data android:name="android.app.repository" android:value="default"/>
|
<meta-data android:name="android.app.repository" android:value="default"/>
|
||||||
<meta-data android:name="android.app.qt_libs_resource_id" android:resource="@array/qt_libs"/>
|
<meta-data android:name="android.app.qt_libs_resource_id" android:resource="@array/qt_libs"/>
|
||||||
<meta-data android:name="android.app.bundled_libs_resource_id" android:resource="@array/bundled_libs"/>
|
<meta-data android:name="android.app.bundled_libs_resource_id" android:resource="@array/bundled_libs"/>
|
||||||
|
|
||||||
<!-- Deploy Qt libs as part of package -->
|
<!-- Deploy Qt libs as part of package -->
|
||||||
<meta-data android:name="android.app.bundle_local_qt_libs" android:value="-- %%BUNDLE_LOCAL_QT_LIBS%% --"/>
|
<meta-data android:name="android.app.bundle_local_qt_libs" android:value="-- %%BUNDLE_LOCAL_QT_LIBS%% --"/>
|
||||||
<meta-data android:name="android.app.bundled_in_lib_resource_id" android:resource="@array/bundled_in_lib"/>
|
<meta-data android:name="android.app.bundled_in_lib_resource_id" android:resource="@array/bundled_in_lib"/>
|
||||||
<meta-data android:name="android.app.bundled_in_assets_resource_id" android:resource="@array/bundled_in_assets"/>
|
<meta-data android:name="android.app.bundled_in_assets_resource_id" android:resource="@array/bundled_in_assets"/>
|
||||||
|
|
||||||
<!-- Run with local libs -->
|
<!-- Run with local libs -->
|
||||||
<meta-data android:name="android.app.use_local_qt_libs" android:value="-- %%USE_LOCAL_QT_LIBS%% --"/>
|
<meta-data android:name="android.app.use_local_qt_libs" android:value="-- %%USE_LOCAL_QT_LIBS%% --"/>
|
||||||
<meta-data android:name="android.app.libs_prefix" android:value="/data/local/tmp/qt/"/>
|
<meta-data android:name="android.app.libs_prefix" android:value="/data/local/tmp/qt/"/>
|
||||||
<meta-data android:name="android.app.load_local_libs" android:value="-- %%INSERT_LOCAL_LIBS%% --"/>
|
<meta-data android:name="android.app.load_local_libs" android:value="-- %%INSERT_LOCAL_LIBS%% --"/>
|
||||||
<meta-data android:name="android.app.load_local_jars" android:value="-- %%INSERT_LOCAL_JARS%% --"/>
|
<meta-data android:name="android.app.load_local_jars" android:value="-- %%INSERT_LOCAL_JARS%% --"/>
|
||||||
<meta-data android:name="android.app.static_init_classes" android:value="-- %%INSERT_INIT_CLASSES%% --"/>
|
<meta-data android:name="android.app.static_init_classes" android:value="-- %%INSERT_INIT_CLASSES%% --"/>
|
||||||
|
|
||||||
<!-- Messages maps -->
|
<!-- Messages maps -->
|
||||||
<meta-data android:value="@string/ministro_not_found_msg" android:name="android.app.ministro_not_found_msg"/>
|
<meta-data android:value="@string/ministro_not_found_msg" android:name="android.app.ministro_not_found_msg"/>
|
||||||
<meta-data android:value="@string/ministro_needed_msg" android:name="android.app.ministro_needed_msg"/>
|
<meta-data android:value="@string/ministro_needed_msg" android:name="android.app.ministro_needed_msg"/>
|
||||||
<meta-data android:value="@string/fatal_error_msg" android:name="android.app.fatal_error_msg"/>
|
<meta-data android:value="@string/fatal_error_msg" android:name="android.app.fatal_error_msg"/>
|
||||||
<!-- Messages maps -->
|
<!-- Messages maps -->
|
||||||
|
]]>
|
||||||
<!-- Background running -->
|
|
||||||
<meta-data android:name="android.app.background_running" android:value="true"/>
|
|
||||||
<!-- Background running -->
|
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
|
<![CDATA[
|
||||||
|
<!-- G10h4ck: Example on how to start the service at boot -->
|
||||||
|
<receiver android:name=".BootCompletedReceiver" android:enabled="true">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.BOOT_COMPLETED"/>
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
|
|
||||||
|
<!-- G10h4ck: Example on how to restart the service on update -->
|
||||||
|
<receiver android:name=".AppUpdatedReceiver" android:enabled="true">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MY_PACKAGE_REPLACED"/>
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
|
|
||||||
|
]]>
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="18"/>
|
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="18"/>
|
||||||
<supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
|
<supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
|
||||||
|
|
||||||
|
<!-- Added by G10h4ck: Needed permission for network usage -->
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
|
|
||||||
|
<!-- Added by G10h4ck: Needed to listen for multicast packets, needed for
|
||||||
|
! broadcast discovery -->
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
|
||||||
|
|
||||||
|
<!-- Added by Angesoc: used to access files shared by other apps -->
|
||||||
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||||
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||||
|
|
||||||
|
<![CDATA[
|
||||||
<!-- The following comment will be replaced upon deployment with default
|
<!-- The following comment will be replaced upon deployment with default
|
||||||
++ permissions based on the dependencies of the application.
|
++ permissions based on the dependencies of the application.
|
||||||
++ Remove the comment if you do not require these default permissions. -->
|
++ Remove the comment if you do not require these default permissions. -->
|
||||||
@ -76,17 +98,11 @@
|
|||||||
++ features based on the dependencies of the application.
|
++ features based on the dependencies of the application.
|
||||||
++ Remove the comment if you do not require these default features. -->
|
++ Remove the comment if you do not require these default features. -->
|
||||||
<!-- %%INSERT_FEATURES -->
|
<!-- %%INSERT_FEATURES -->
|
||||||
|
]]>
|
||||||
|
|
||||||
<!-- Added by G10h4ck: Needed permission for autostart at boot -->
|
<![CDATA[
|
||||||
|
<!-- Added by G10h4ck: Needed permission for autostart at boot example
|
||||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
||||||
<!-- Added by Angesoc: used to access files shared by other apps -->
|
-->
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
]]>
|
||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
|
||||||
<!-- Added by G10h4ck: Needed permission for network usage -->
|
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
|
||||||
<!-- Added by G10h4ck: Needed to listen for multicast packets, needed for
|
|
||||||
! broadcast discovery -->
|
|
||||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
|
||||||
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
package org.retroshare.service;
|
package org.retroshare.service;
|
||||||
|
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
@ -36,3 +37,4 @@ public class AppUpdatedReceiver extends BroadcastReceiver
|
|||||||
RetroShareServiceAndroid.start(context);
|
RetroShareServiceAndroid.start(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
@ -0,0 +1 @@
|
|||||||
|
../../../../../../../libretroshare/src/rs_android/org/retroshare/service/AssetHelper.java
|
@ -19,6 +19,7 @@
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
package org.retroshare.service;
|
package org.retroshare.service;
|
||||||
|
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
@ -35,3 +36,4 @@ public class BootCompletedReceiver extends BroadcastReceiver
|
|||||||
RetroShareServiceAndroid.start(context);
|
RetroShareServiceAndroid.start(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
@ -0,0 +1 @@
|
|||||||
|
../../../../../../../libretroshare/src/rs_android/org/retroshare/service/ErrorConditionWrap.java
|
@ -1,50 +0,0 @@
|
|||||||
/*
|
|
||||||
* RetroShare
|
|
||||||
* Copyright (C) 2016-2018 Gioacchino Mazzurco <gio@eigenlab.org>
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as
|
|
||||||
* published by the Free Software Foundation, either version 3 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* SPDX-FileCopyrightText: Retroshare Team <contact@retroshare.cc>
|
|
||||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.retroshare.service;
|
|
||||||
|
|
||||||
import android.app.ActivityManager;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
|
|
||||||
import org.qtproject.qt5.android.bindings.QtService;
|
|
||||||
|
|
||||||
public class RetroShareServiceAndroid extends QtService
|
|
||||||
{
|
|
||||||
public static void start(Context ctx)
|
|
||||||
{
|
|
||||||
ctx.startService(new Intent(ctx, RetroShareServiceAndroid.class));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void stop(Context ctx)
|
|
||||||
{
|
|
||||||
ctx.stopService(new Intent(ctx, RetroShareServiceAndroid.class));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isRunning(Context ctx)
|
|
||||||
{
|
|
||||||
ActivityManager manager = (ActivityManager) ctx.getSystemService(Context.ACTIVITY_SERVICE);
|
|
||||||
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE))
|
|
||||||
if (RetroShareServiceAndroid.class.getName().equals(service.service.getClassName()))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1 @@
|
|||||||
|
../../../../../../../libretroshare/src/rs_android/org/retroshare/service/RetroShareServiceAndroid.java
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* RetroShare
|
* RetroShare
|
||||||
* Copyright (C) 2016-2018 Gioacchino Mazzurco <gio@altermundi.net>
|
* Copyright (C) 2016-2021 Gioacchino Mazzurco <gio@altermundi.net>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Affero General Public License as
|
* it under the terms of the GNU Affero General Public License as
|
||||||
@ -50,7 +50,11 @@ public class RetroShareServiceControlActivity extends Activity
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
button.setText("Starting...");
|
button.setText("Starting...");
|
||||||
RetroShareServiceAndroid.start(RetroShareServiceControlActivity.this);
|
RetroShareServiceAndroid.start(
|
||||||
|
RetroShareServiceControlActivity.this,
|
||||||
|
RetroShareServiceAndroid.DEFAULT_JSON_API_PORT,
|
||||||
|
RetroShareServiceAndroid.DEFAULT_JSON_API_BINDING_ADDRESS
|
||||||
|
);
|
||||||
serviceStarting = true;
|
serviceStarting = true;
|
||||||
serviceStopping = false;
|
serviceStopping = false;
|
||||||
}
|
}
|
||||||
|
29
retroshare-service/src/retroshare-service-android.cc
Normal file
29
retroshare-service/src/retroshare-service-android.cc
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* RetroShare Service Android
|
||||||
|
* Copyright (C) 2021 Gioacchino Mazzurco <gio@eigenlab.org>
|
||||||
|
* Copyright (C) 2021 Asociación Civil Altermundi <info@altermundi.net>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* SPDX-FileCopyrightText: Retroshare Team <contact@retroshare.cc>
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "rs_android/rsjni.hpp"
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* _reserved)
|
||||||
|
{
|
||||||
|
RS_DBG(vm);
|
||||||
|
return JNI_OnLoad_retroshare(vm, _reserved);
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* RetroShare Service
|
* RetroShare Service
|
||||||
* Copyright (C) 2016-2019 Gioacchino Mazzurco <gio@eigenlab.org>
|
* Copyright (C) 2016-2021 Gioacchino Mazzurco <gio@eigenlab.org>
|
||||||
|
* Copyright (C) 2021 Asociación Civil Altermundi <info@altermundi.net>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Affero General Public License as
|
* it under the terms of the GNU Affero General Public License as
|
||||||
@ -19,39 +20,31 @@
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "util/stacktrace.h"
|
|
||||||
#include "util/argstream.h"
|
|
||||||
#include "util/rskbdinput.h"
|
|
||||||
#include "retroshare/rsinit.h"
|
|
||||||
|
|
||||||
#ifdef RS_JSONAPI
|
|
||||||
#include "retroshare/rsjsonapi.h"
|
|
||||||
|
|
||||||
#ifdef RS_WEBUI
|
|
||||||
#include "retroshare/rswebui.h"
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static CrashStackTrace gCrashStackTrace;
|
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <csignal>
|
#include <csignal>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
#include "util/stacktrace.h"
|
||||||
# include <QAndroidService>
|
#include "util/argstream.h"
|
||||||
# include <QCoreApplication>
|
#include "util/rskbdinput.h"
|
||||||
# include <QObject>
|
#include "retroshare/rsinit.h"
|
||||||
# include <QStringList>
|
|
||||||
|
|
||||||
# include "util/androiddebug.h"
|
|
||||||
#endif // def __ANDROID__
|
|
||||||
|
|
||||||
#include "retroshare/rsinit.h"
|
#include "retroshare/rsinit.h"
|
||||||
#include "retroshare/rsiface.h"
|
#include "retroshare/rsiface.h"
|
||||||
#include "util/rsdebug.h"
|
#include "util/rsdebug.h"
|
||||||
|
|
||||||
|
#ifdef RS_JSONAPI
|
||||||
|
# include "retroshare/rsjsonapi.h"
|
||||||
|
|
||||||
|
# ifdef RS_WEBUI
|
||||||
|
# include "retroshare/rswebui.h"
|
||||||
|
# endif // def RS_WEBUI
|
||||||
|
#endif // def RS_JSONAPI
|
||||||
|
|
||||||
|
static CrashStackTrace gCrashStackTrace;
|
||||||
|
|
||||||
|
|
||||||
#ifdef RS_SERVICE_TERMINAL_LOGIN
|
#ifdef RS_SERVICE_TERMINAL_LOGIN
|
||||||
class RsServiceNotify: public NotifyClient
|
class RsServiceNotify: public NotifyClient
|
||||||
{
|
{
|
||||||
@ -74,9 +67,6 @@ public:
|
|||||||
};
|
};
|
||||||
#endif // def RS_SERVICE_TERMINAL_LOGIN
|
#endif // def RS_SERVICE_TERMINAL_LOGIN
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
|
||||||
void signalHandler(int /*signal*/) { QCoreApplication::exit(0); }
|
|
||||||
#else
|
|
||||||
static std::atomic<bool> keepRunning(true);
|
static std::atomic<bool> keepRunning(true);
|
||||||
static int receivedSignal = 0;
|
static int receivedSignal = 0;
|
||||||
|
|
||||||
@ -87,16 +77,10 @@ void signalHandler(int signal)
|
|||||||
receivedSignal = signal;
|
receivedSignal = signal;
|
||||||
keepRunning = false;
|
keepRunning = false;
|
||||||
}
|
}
|
||||||
#endif // def __ANDROID__
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
#ifdef __ANDROID__
|
|
||||||
AndroidStdIOCatcher dbg; (void) dbg;
|
|
||||||
QAndroidService app(argc, argv);
|
|
||||||
#endif // def __ANDROID__
|
|
||||||
|
|
||||||
signal(SIGINT, signalHandler);
|
signal(SIGINT, signalHandler);
|
||||||
signal(SIGTERM, signalHandler);
|
signal(SIGTERM, signalHandler);
|
||||||
#ifdef SIGBREAK
|
#ifdef SIGBREAK
|
||||||
@ -128,7 +112,7 @@ int main(int argc, char* argv[])
|
|||||||
RsConfigOptions conf;
|
RsConfigOptions conf;
|
||||||
|
|
||||||
#ifdef RS_JSONAPI
|
#ifdef RS_JSONAPI
|
||||||
conf.jsonApiPort = RsJsonApi::DEFAULT_PORT; // enable JSonAPI by default
|
conf.jsonApiPort = RsJsonApi::DEFAULT_PORT; // enable JSON API by default
|
||||||
#ifdef RS_WEBUI
|
#ifdef RS_WEBUI
|
||||||
std::string webui_base_directory = RsWebUi::DEFAULT_BASE_DIRECTORY;
|
std::string webui_base_directory = RsWebUi::DEFAULT_BASE_DIRECTORY;
|
||||||
#endif
|
#endif
|
||||||
@ -323,22 +307,10 @@ int main(int argc, char* argv[])
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
|
||||||
rsControl->setShutdownCallback(QCoreApplication::exit);
|
|
||||||
|
|
||||||
QObject::connect(
|
|
||||||
&app, &QCoreApplication::aboutToQuit,
|
|
||||||
[](){
|
|
||||||
if(RsControl::instance()->isReady())
|
|
||||||
RsControl::instance()->rsGlobalShutDown(); } );
|
|
||||||
|
|
||||||
return app.exec();
|
|
||||||
#else // def __ANDROID__
|
|
||||||
rsControl->setShutdownCallback([&](int){keepRunning = false;});
|
rsControl->setShutdownCallback([&](int){keepRunning = false;});
|
||||||
|
|
||||||
while(keepRunning)
|
while(keepRunning)
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# RetroShare service qmake build script
|
# RetroShare service qmake build script
|
||||||
#
|
#
|
||||||
# Copyright (C) 2018-2019, Gioacchino Mazzurco <gio@eigenlab.org>
|
# Copyright (C) 2018-2021, Gioacchino Mazzurco <gio@eigenlab.org>
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it under
|
# This program is free software: you can redistribute it and/or modify it under
|
||||||
# the terms of the GNU Affero General Public License as published by the
|
# the terms of the GNU Affero General Public License as published by the
|
||||||
@ -22,8 +22,7 @@
|
|||||||
|
|
||||||
TARGET = retroshare-service
|
TARGET = retroshare-service
|
||||||
|
|
||||||
QT += core
|
CONFIG -= qt
|
||||||
QT -= gui
|
|
||||||
|
|
||||||
!include("../../libretroshare/src/use_libretroshare.pri"):error("Including")
|
!include("../../libretroshare/src/use_libretroshare.pri"):error("Including")
|
||||||
|
|
||||||
@ -32,8 +31,6 @@ SOURCES += retroshare-service.cc
|
|||||||
################################# Linux ##########################################
|
################################# Linux ##########################################
|
||||||
|
|
||||||
android-* {
|
android-* {
|
||||||
QT += androidextras
|
|
||||||
|
|
||||||
ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android
|
ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android
|
||||||
|
|
||||||
DISTFILES += android/AndroidManifest.xml \
|
DISTFILES += android/AndroidManifest.xml \
|
||||||
@ -45,6 +42,9 @@ android-* {
|
|||||||
android/build.gradle \
|
android/build.gradle \
|
||||||
android/gradle/wrapper/gradle-wrapper.properties \
|
android/gradle/wrapper/gradle-wrapper.properties \
|
||||||
android/gradlew.bat
|
android/gradlew.bat
|
||||||
|
|
||||||
|
SOURCES -= retroshare-service.cc
|
||||||
|
SOURCES += retroshare-service-android.cc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
1
supportlibs/jni.hpp
Submodule
1
supportlibs/jni.hpp
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 66f73a6aa82367d6ba23e7e842f95dfb33c451d6
|
Loading…
Reference in New Issue
Block a user