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"]
|
||||
path = supportlibs/libsam3
|
||||
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 RS_SRC_DIR "$(realpath $(dirname $BASH_SOURCE)/../../)"
|
||||
|
||||
|
||||
cArch=""
|
||||
eABI=""
|
||||
cmakeABI=""
|
||||
@ -829,6 +832,15 @@ build_phash()
|
||||
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
|
||||
build_mvptree()
|
||||
{
|
||||
@ -862,6 +874,7 @@ build_default_toolchain()
|
||||
task_run build_xapian || return $?
|
||||
task_run build_miniupnpc || return $?
|
||||
task_run build_phash || return $?
|
||||
task_run fetch_jni_hpp || return $?
|
||||
task_run deduplicate_includes || return $?
|
||||
task_run get_native_libs_toolchain_path || return $?
|
||||
}
|
||||
|
@ -796,8 +796,9 @@ void JsonApiServer::run()
|
||||
}
|
||||
catch(std::exception& e)
|
||||
{
|
||||
RsErr() << __PRETTY_FUNCTION__ << " Failure starting JSON API server: "
|
||||
<< e.what() << std::endl;
|
||||
/* TODO: find a way to report back programmatically if failed listening
|
||||
* port */
|
||||
RS_ERR("Failure starting JSON API server: ", e.what());
|
||||
print_stacktrace();
|
||||
return;
|
||||
}
|
||||
|
@ -1101,13 +1101,11 @@ android-* {
|
||||
DEFINES *= "fseeko64=fseeko"
|
||||
DEFINES *= "ftello64=ftello"
|
||||
|
||||
## @See: android_ifaddrs/README.adoc
|
||||
!contains(DEFINES, LIBRETROSHARE_ANDROID_IFADDRS_QT) {
|
||||
HEADERS += \
|
||||
android_ifaddrs/ifaddrs-android.h \
|
||||
android_ifaddrs/LocalArray.h \
|
||||
android_ifaddrs/ScopedFd.h
|
||||
}
|
||||
## @See: rs_android/README-ifaddrs-android.adoc
|
||||
HEADERS += \
|
||||
rs_android/ifaddrs-android.h \
|
||||
rs_android/LocalArray.h \
|
||||
rs_android/ScopedFd.h
|
||||
}
|
||||
|
||||
## Static library are very susceptible to order in command line
|
||||
@ -1116,6 +1114,13 @@ android-* {
|
||||
LIBS += $$linkStaticLibs(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_ipv6_to_ipv4(extAddr);
|
||||
|
||||
//#ifdef PEER_DEBUG
|
||||
#ifdef PEER_DEBUG
|
||||
std::cerr << "p3PeerMgrIMPL::UpdateOwnAddress("
|
||||
<< sockaddr_storage_tostring(localAddr) << ", "
|
||||
<< sockaddr_storage_tostring(extAddr) << ")" << std::endl;
|
||||
//#endif
|
||||
#endif
|
||||
|
||||
if( rsBanList &&
|
||||
!rsBanList->isAddressAccepted(localAddr,
|
||||
|
@ -21,16 +21,6 @@
|
||||
* 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 <iostream>
|
||||
@ -44,6 +34,28 @@
|
||||
#include "util/rsnet.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"};
|
||||
#define pqinetzone &pqinetzoneInfo
|
||||
|
||||
@ -51,21 +63,6 @@ static struct RsLog::logInfo pqinetzoneInfo = {RsLog::Default, "pqinet"};
|
||||
* #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 ******************/
|
||||
#ifndef WINDOWS_SYS
|
||||
|
||||
@ -271,24 +268,16 @@ int inet_aton(const char *name, struct in_addr *addr)
|
||||
#endif
|
||||
/********************************** WINDOWS/UNIX SPECIFIC PART ******************/
|
||||
|
||||
|
||||
#include "util/cxx17retrocompat.h"
|
||||
#include <sys/types.h>
|
||||
#ifdef WINDOWS_SYS
|
||||
# include <winsock2.h>
|
||||
# include <iphlpapi.h>
|
||||
# pragma comment(lib, "IPHLPAPI.lib")
|
||||
#elif defined(__ANDROID__) && __ANDROID_API__ < 24 && \
|
||||
defined(LIBRETROSHARE_ANDROID_IFADDRS_QT)
|
||||
#elif defined(__ANDROID__) && __ANDROID_API__ < 24
|
||||
/// @See: android_ifaddrs/README.adoc
|
||||
# include <string>
|
||||
# include <QString>
|
||||
# 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 "rs_android/ifaddrs-android.h"
|
||||
#else // not WINDOWS => Linux and other unixes
|
||||
# include <ifaddrs.h>
|
||||
# include <net/if.h>
|
||||
#endif // WINDOWS_SYS
|
||||
@ -331,17 +320,7 @@ bool getLocalAddresses(std::vector<sockaddr_storage>& addrs)
|
||||
}
|
||||
}
|
||||
free(adapter_addresses);
|
||||
#elif defined(__ANDROID__) && __ANDROID_API__ < 24 && \
|
||||
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
|
||||
#else // not WINDOWS_SYS => Linux and other unixes
|
||||
struct ifaddrs *ifsaddrs, *ifa;
|
||||
if(getifaddrs(&ifsaddrs) != 0)
|
||||
{
|
||||
@ -355,18 +334,19 @@ bool getLocalAddresses(std::vector<sockaddr_storage>& addrs)
|
||||
{
|
||||
sockaddr_storage 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);
|
||||
}
|
||||
freeifaddrs(ifsaddrs);
|
||||
#endif // WINDOWS_SYS
|
||||
|
||||
#ifdef NET_DEBUG
|
||||
std::list<sockaddr_storage>::iterator it;
|
||||
std::cout << "getLocalAddresses(...) returning: <" ;
|
||||
for(it = addrs.begin(); it != addrs.end(); ++it)
|
||||
std::cout << sockaddr_storage_iptostring(*it) << ", ";
|
||||
std::cout << ">" << std::endl;
|
||||
auto&& dbg = RS_DBG("returning: [");
|
||||
for(auto& addr: std::as_const(addrs))
|
||||
dbg << sockaddr_storage_iptostring(addr) << ", ";
|
||||
dbg << "]" << std::endl;
|
||||
#endif
|
||||
|
||||
return !addrs.empty();
|
||||
|
@ -4,7 +4,8 @@
|
||||
* libretroshare: retroshare core library *
|
||||
* *
|
||||
* 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 *
|
||||
* 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/>. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
#ifndef MRK_PQI_NETWORKING_HEADER
|
||||
#define MRK_PQI_NETWORKING_HEADER
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
@ -86,9 +86,13 @@ extern int errno; /* Define extern errno, to duplicate unix behaviour */
|
||||
#include <string>
|
||||
#include <list>
|
||||
|
||||
#include "util/rsdeprecate.h"
|
||||
|
||||
// Same def - different functions...
|
||||
RS_DEPRECATED_FOR("use std::error_condition instead")
|
||||
void showSocketError(std::string &out);
|
||||
|
||||
RS_DEPRECATED_FOR("use std::error_condition instead")
|
||||
std::string socket_errorType(int err);
|
||||
|
||||
bool getLocalAddresses(std::vector<sockaddr_storage> & addrs);
|
||||
@ -103,10 +107,6 @@ int unix_getsockopt_error(int sockfd, int *err);
|
||||
|
||||
#ifdef WINDOWS_SYS // WINDOWS
|
||||
/******************* WINDOWS SPECIFIC PART ******************/
|
||||
RS_DEPRECATED_FOR("use std::error_condition instead")
|
||||
int WinToUnixError(int error);
|
||||
#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
|
||||
https://bugreports.qt.io/browse/QTBUG-86394
|
||||
|
||||
This solution is the first working we implemented in our code it is disabled by
|
||||
default but can be enabled passing `DEFINES+=LIBRETROSHARE_ANDROID_IFADDRS_QT`
|
||||
when running `qmake` command.
|
||||
This solution was the first working we implemented in our code it has been
|
||||
removed to avoid dependency on Qt, as lighter alternatives are possible.
|
||||
|
||||
|
||||
== 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.
|
||||
|
||||
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 *
|
||||
* *
|
||||
* 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 *
|
||||
* 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
|
||||
* stderr) on logcat output.
|
||||
*/
|
||||
class AndroidStdIOCatcher
|
||||
class AndroidCoutCerrCatcher
|
||||
{
|
||||
public:
|
||||
AndroidStdIOCatcher(const std::string& dTag = "RetroShare",
|
||||
AndroidCoutCerrCatcher(const std::string& dTag = "RetroShare",
|
||||
android_LogPriority stdout_pri = ANDROID_LOG_INFO,
|
||||
android_LogPriority stderr_pri = ANDROID_LOG_ERROR) :
|
||||
tag(dTag), cout_pri(stdout_pri), cerr_pri(stderr_pri), should_stop(false)
|
||||
@ -63,10 +63,10 @@ public:
|
||||
pthread_detach(thr);
|
||||
}
|
||||
|
||||
~AndroidStdIOCatcher()
|
||||
~AndroidCoutCerrCatcher()
|
||||
{
|
||||
should_stop = true;
|
||||
pthread_join(thr, NULL);
|
||||
pthread_join(thr, nullptr);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -79,11 +79,13 @@ private:
|
||||
pthread_t thr;
|
||||
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 err_buf;
|
||||
@ -113,9 +115,11 @@ private:
|
||||
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/stat.h>
|
||||
|
||||
#include <system_error>
|
||||
#include <iostream>
|
||||
|
||||
#include "retroshare/rsinit.h"
|
||||
#include "rsaccounts.h"
|
||||
|
||||
#include "util/rsdebug.h"
|
||||
#include "util/rsdir.h"
|
||||
#include "util/rsstring.h"
|
||||
#include "util/folderiterator.h"
|
||||
@ -48,6 +48,11 @@
|
||||
|
||||
#include <openssl/ssl.h>
|
||||
|
||||
#ifdef __ANDROID__
|
||||
# include "rs_android/rsjni.hpp"
|
||||
# include "rs_android/retroshareserviceandroid.hpp"
|
||||
#endif
|
||||
|
||||
// Global singleton declaration of data.
|
||||
RsAccountsDetail* RsAccounts::rsAccountsDetails = nullptr;
|
||||
|
||||
@ -328,22 +333,7 @@ bool RsAccountsDetail::defaultBaseDirectory()
|
||||
{
|
||||
std::string basedir;
|
||||
|
||||
/******************************** WINDOWS/UNIX SPECIFIC PART ******************/
|
||||
#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
|
||||
#ifdef WINDOWS_SYS
|
||||
if (RsInit::isPortable())
|
||||
{
|
||||
// use directory "Data" in portable version
|
||||
@ -375,13 +365,53 @@ bool RsAccountsDetail::defaultBaseDirectory()
|
||||
}
|
||||
basedir += "\\RetroShare";
|
||||
}
|
||||
#endif
|
||||
/******************************** WINDOWS/UNIX SPECIFIC PART ******************/
|
||||
#elif defined (__ANDROID__) // def WINDOWS_SYS
|
||||
|
||||
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 */
|
||||
mBaseDirectory = basedir;
|
||||
std::cerr << "defaultBaseDirectory() = " << mBaseDirectory;
|
||||
std::cerr << std::endl;
|
||||
|
||||
RS_INFO(mBaseDirectory);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -941,6 +971,11 @@ bool RsAccountsDetail::exportIdentityToString(
|
||||
|
||||
bool RsAccountsDetail::copyGnuPGKeyrings()
|
||||
{
|
||||
#ifdef __ANDROID__
|
||||
RS_ERR(std::errc::not_supported);
|
||||
print_stacktrace();
|
||||
return false;
|
||||
#else
|
||||
std::string pgp_dir = PathPGPDirectory() ;
|
||||
|
||||
if(!RsDirUtil::checkCreateDirectory(pgp_dir))
|
||||
@ -992,6 +1027,7 @@ bool RsAccountsDetail::copyGnuPGKeyrings()
|
||||
}
|
||||
|
||||
return true ;
|
||||
#endif // def __ANDROID__
|
||||
}
|
||||
|
||||
|
||||
|
@ -32,8 +32,9 @@
|
||||
#endif
|
||||
|
||||
#ifdef __ANDROID__
|
||||
# include <QFile> // To install bdboot.txt
|
||||
# include <QString> // for QString::fromStdString(...)
|
||||
# include <jni/jni.hpp>
|
||||
# include "rs_android/rsjni.hpp"
|
||||
# include "rs_android/retroshareserviceandroid.hpp"
|
||||
#endif
|
||||
|
||||
#include "util/argstream.h"
|
||||
@ -194,7 +195,7 @@ static const int SSLPWD_LEN = 64;
|
||||
|
||||
void RsInit::InitRsConfig()
|
||||
{
|
||||
RsInfo() << " libretroshare version: " << RS_HUMAN_READABLE_VERSION
|
||||
RsInfo() << "libretroshare version: " << RS_HUMAN_READABLE_VERSION
|
||||
<< std::endl;
|
||||
|
||||
rsInitConfig = new RsInitConfig;
|
||||
@ -1011,32 +1012,32 @@ int RsServer::StartupRetroShare()
|
||||
uint64_t tmp_size ;
|
||||
if (!RsDirUtil::checkFile(bootstrapfile,tmp_size,true))
|
||||
{
|
||||
std::cerr << "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;
|
||||
}
|
||||
RS_INFO("DHT bootstrap file not in ConfigDir: ", bootstrapfile);
|
||||
|
||||
bdbootRF.close();
|
||||
}
|
||||
#else
|
||||
#ifdef __ANDROID__
|
||||
auto uenv = jni::GetAttachedEnv(RsJni::getVM());
|
||||
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;
|
||||
if ((installfile != "") && (RsDirUtil::checkFile(installfile,tmp_size)))
|
||||
{
|
||||
|
@ -1,7 +1,8 @@
|
||||
/*******************************************************************************
|
||||
* 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 *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
@ -25,16 +26,17 @@
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
#ifdef __ANDROID__
|
||||
# include <QtAndroid>
|
||||
#endif // def __ANDROID__
|
||||
|
||||
#include "services/broadcastdiscoveryservice.h"
|
||||
#include "retroshare/rspeers.h"
|
||||
#include "serialiser/rsserializable.h"
|
||||
#include "serialiser/rsserializer.h"
|
||||
#include "retroshare/rsevents.h"
|
||||
|
||||
#ifdef __ANDROID__
|
||||
# include "rs_android/retroshareserviceandroid.hpp"
|
||||
#endif // def __ANDROID__
|
||||
|
||||
|
||||
/*extern*/ RsBroadcastDiscovery* rsBroadcastDiscovery = nullptr;
|
||||
|
||||
struct BroadcastDiscoveryPack : RsSerializable
|
||||
@ -99,7 +101,7 @@ BroadcastDiscoveryService::BroadcastDiscoveryService(
|
||||
if(mRsPeers.isHiddenNode(mRsPeers.getOwnId())) return;
|
||||
|
||||
#ifdef __ANDROID__
|
||||
createMulticastLock();
|
||||
createAndroidMulticastLock();
|
||||
#endif // def __ANDROID__
|
||||
|
||||
enableMulticastListening();
|
||||
@ -228,19 +230,47 @@ RsBroadcastDiscoveryResult BroadcastDiscoveryService::createResult(
|
||||
bool BroadcastDiscoveryService::isMulticastListeningEnabled()
|
||||
{
|
||||
#ifdef __ANDROID__
|
||||
return assertMulticastLockIsvalid() &&
|
||||
mWifiMulticastLock.callMethod<jboolean>("isHeld");
|
||||
#endif // def __ANDROID__
|
||||
if(!mAndroidWifiMulticastLock)
|
||||
{
|
||||
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;
|
||||
#endif // def __ANDROID__
|
||||
}
|
||||
|
||||
bool BroadcastDiscoveryService::enableMulticastListening()
|
||||
{
|
||||
#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;
|
||||
}
|
||||
#endif // def __ANDROID__
|
||||
@ -251,9 +281,24 @@ bool BroadcastDiscoveryService::enableMulticastListening()
|
||||
bool BroadcastDiscoveryService::disableMulticastListening()
|
||||
{
|
||||
#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;
|
||||
}
|
||||
#endif // def __ANDROID__
|
||||
@ -262,56 +307,57 @@ bool BroadcastDiscoveryService::disableMulticastListening()
|
||||
}
|
||||
|
||||
#ifdef __ANDROID__
|
||||
bool BroadcastDiscoveryService::createMulticastLock()
|
||||
|
||||
bool BroadcastDiscoveryService::createAndroidMulticastLock()
|
||||
{
|
||||
Dbg2() << __PRETTY_FUNCTION__ << std::endl;
|
||||
|
||||
constexpr auto fname = __PRETTY_FUNCTION__;
|
||||
const auto failure = [&](const std::string& err)
|
||||
if(mAndroidWifiMulticastLock)
|
||||
{
|
||||
RsErr() << fname << " " << err << std::endl;
|
||||
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;
|
||||
RS_ERR("Android multicast lock is already initialized");
|
||||
print_stacktrace();
|
||||
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;
|
||||
}
|
||||
|
||||
#endif // def __ANDROID__
|
||||
|
||||
RsBroadcastDiscovery::~RsBroadcastDiscovery() = default;
|
||||
|
@ -1,7 +1,8 @@
|
||||
/*******************************************************************************
|
||||
* 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 *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
@ -27,14 +28,16 @@
|
||||
|
||||
#include <udp_discovery_peer.hpp>
|
||||
|
||||
#ifdef __ANDROID__
|
||||
# include <QtAndroidExtras/QAndroidJniObject>
|
||||
#endif // def __ANDROID__
|
||||
|
||||
#include "retroshare/rsbroadcastdiscovery.h"
|
||||
#include "util/rsthreads.h"
|
||||
#include "util/rsdebug.h"
|
||||
|
||||
#ifdef __ANDROID__
|
||||
# include <jni/jni.hpp>
|
||||
# include "rs_android/rsjni.hpp"
|
||||
#endif // def __ANDROID__
|
||||
|
||||
|
||||
namespace UDC = udpdiscovery;
|
||||
class RsPeers;
|
||||
|
||||
@ -42,7 +45,7 @@ class BroadcastDiscoveryService :
|
||||
public RsBroadcastDiscovery, public RsTickingThread
|
||||
{
|
||||
public:
|
||||
BroadcastDiscoveryService(RsPeers& pRsPeers);
|
||||
explicit BroadcastDiscoveryService(RsPeers& pRsPeers);
|
||||
~BroadcastDiscoveryService() override;
|
||||
|
||||
/// @see RsBroadcastDiscovery
|
||||
@ -71,26 +74,27 @@ protected:
|
||||
std::map<UDC::IpPort, std::string> mDiscoveredData;
|
||||
RsMutex mDiscoveredDataMutex;
|
||||
|
||||
RsPeers& mRsPeers; // TODO: std::shared_ptr<RsPeers> mRsPeers;
|
||||
RsPeers& mRsPeers;
|
||||
|
||||
RsBroadcastDiscoveryResult createResult(
|
||||
const UDC::IpPort& ipp, const std::string& uData );
|
||||
|
||||
#ifdef __ANDROID__
|
||||
/** Android WifiManager.MulticastLock */
|
||||
QAndroidJniObject mWifiMulticastLock;
|
||||
struct AndroidMulticastLock
|
||||
{
|
||||
static constexpr auto Name()
|
||||
{ return "android/net/wifi/WifiManager$MulticastLock"; }
|
||||
};
|
||||
|
||||
jni::Global<jni::Object<AndroidMulticastLock>> mAndroidWifiMulticastLock;
|
||||
|
||||
/** Initialize the wifi multicast lock without acquiring it
|
||||
* Needed to enable multicast listening in Android, for RetroShare broadcast
|
||||
* discovery inspired by:
|
||||
* https://github.com/flutter/flutter/issues/16335#issuecomment-420547860
|
||||
*/
|
||||
bool createMulticastLock();
|
||||
|
||||
/** Return false if mWifiMulticastLock is invalid and print error messages */
|
||||
bool assertMulticastLockIsvalid();
|
||||
|
||||
#endif // def __ANDROID__
|
||||
bool createAndroidMulticastLock();
|
||||
#endif
|
||||
|
||||
RS_SET_CONTEXT_DEBUG_LEVEL(3)
|
||||
};
|
||||
|
@ -111,14 +111,7 @@ PRE_TARGETDEPS += $$pretargetStaticLibs(sLibs)
|
||||
LIBS += $$linkDynamicLibs(dLibs)
|
||||
|
||||
android-* {
|
||||
CONFIG *= qt
|
||||
|
||||
lessThan(ANDROID_API_VERSION, 24) {
|
||||
## @See: android_ifaddrs/README.adoc
|
||||
contains(DEFINES, LIBRETROSHARE_ANDROID_IFADDRS_QT) {
|
||||
QT *= network
|
||||
}
|
||||
}
|
||||
INCLUDEPATH *= $$clean_path($${RS_SRC_PATH}/supportlibs/jni.hpp/include/)
|
||||
}
|
||||
|
||||
################################### Pkg-Config Stuff #############################
|
||||
|
@ -2,9 +2,9 @@
|
||||
<manifest
|
||||
package="org.retroshare.service"
|
||||
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">
|
||||
<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
|
||||
android:name=".RetroShareServiceControlActivity"
|
||||
android:label="RetroShare" >
|
||||
@ -14,59 +14,81 @@
|
||||
</intent-filter>
|
||||
</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">
|
||||
<!-- android:exported="true" Added to be able to run the service
|
||||
++ from adb shell
|
||||
++ android:process=":rs" is needed to force the service to run on
|
||||
++ 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 -->
|
||||
<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 -->
|
||||
<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.qt_libs_resource_id" android:resource="@array/qt_libs"/>
|
||||
<meta-data android:name="android.app.bundled_libs_resource_id" android:resource="@array/bundled_libs"/>
|
||||
|
||||
<!-- 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.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"/>
|
||||
|
||||
<!-- 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.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_jars" android:value="-- %%INSERT_LOCAL_JARS%% --"/>
|
||||
<meta-data android:name="android.app.static_init_classes" android:value="-- %%INSERT_INIT_CLASSES%% --"/>
|
||||
|
||||
<!-- 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_needed_msg" android:name="android.app.ministro_needed_msg"/>
|
||||
<meta-data android:value="@string/fatal_error_msg" android:name="android.app.fatal_error_msg"/>
|
||||
<!-- Messages maps -->
|
||||
|
||||
<!-- Background running -->
|
||||
<meta-data android:name="android.app.background_running" android:value="true"/>
|
||||
<!-- Background running -->
|
||||
]]>
|
||||
</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>
|
||||
|
||||
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="18"/>
|
||||
<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
|
||||
++ permissions based on the dependencies of the application.
|
||||
++ Remove the comment if you do not require these default permissions. -->
|
||||
@ -76,17 +98,11 @@
|
||||
++ features based on the dependencies of the application.
|
||||
++ Remove the comment if you do not require these default 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"/>
|
||||
<!-- 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>
|
||||
|
@ -19,6 +19,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
/*
|
||||
package org.retroshare.service;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
@ -36,3 +37,4 @@ public class AppUpdatedReceiver extends BroadcastReceiver
|
||||
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
|
||||
*/
|
||||
|
||||
/*
|
||||
package org.retroshare.service;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
@ -35,3 +36,4 @@ public class BootCompletedReceiver extends BroadcastReceiver
|
||||
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
|
||||
* 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
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
@ -50,7 +50,11 @@ public class RetroShareServiceControlActivity extends Activity
|
||||
else
|
||||
{
|
||||
button.setText("Starting...");
|
||||
RetroShareServiceAndroid.start(RetroShareServiceControlActivity.this);
|
||||
RetroShareServiceAndroid.start(
|
||||
RetroShareServiceControlActivity.this,
|
||||
RetroShareServiceAndroid.DEFAULT_JSON_API_PORT,
|
||||
RetroShareServiceAndroid.DEFAULT_JSON_API_BINDING_ADDRESS
|
||||
);
|
||||
serviceStarting = true;
|
||||
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
|
||||
* 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
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
@ -19,39 +20,31 @@
|
||||
* 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 <csignal>
|
||||
#include <iomanip>
|
||||
#include <atomic>
|
||||
|
||||
#ifdef __ANDROID__
|
||||
# include <QAndroidService>
|
||||
# include <QCoreApplication>
|
||||
# include <QObject>
|
||||
# include <QStringList>
|
||||
|
||||
# include "util/androiddebug.h"
|
||||
#endif // def __ANDROID__
|
||||
|
||||
#include "util/stacktrace.h"
|
||||
#include "util/argstream.h"
|
||||
#include "util/rskbdinput.h"
|
||||
#include "retroshare/rsinit.h"
|
||||
#include "retroshare/rsinit.h"
|
||||
#include "retroshare/rsiface.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
|
||||
class RsServiceNotify: public NotifyClient
|
||||
{
|
||||
@ -74,9 +67,6 @@ public:
|
||||
};
|
||||
#endif // def RS_SERVICE_TERMINAL_LOGIN
|
||||
|
||||
#ifdef __ANDROID__
|
||||
void signalHandler(int /*signal*/) { QCoreApplication::exit(0); }
|
||||
#else
|
||||
static std::atomic<bool> keepRunning(true);
|
||||
static int receivedSignal = 0;
|
||||
|
||||
@ -87,16 +77,10 @@ void signalHandler(int signal)
|
||||
receivedSignal = signal;
|
||||
keepRunning = false;
|
||||
}
|
||||
#endif // def __ANDROID__
|
||||
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
#ifdef __ANDROID__
|
||||
AndroidStdIOCatcher dbg; (void) dbg;
|
||||
QAndroidService app(argc, argv);
|
||||
#endif // def __ANDROID__
|
||||
|
||||
signal(SIGINT, signalHandler);
|
||||
signal(SIGTERM, signalHandler);
|
||||
#ifdef SIGBREAK
|
||||
@ -128,7 +112,7 @@ int main(int argc, char* argv[])
|
||||
RsConfigOptions conf;
|
||||
|
||||
#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
|
||||
std::string webui_base_directory = RsWebUi::DEFAULT_BASE_DIRECTORY;
|
||||
#endif
|
||||
@ -323,22 +307,10 @@ int main(int argc, char* argv[])
|
||||
}
|
||||
#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;});
|
||||
|
||||
while(keepRunning)
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
# 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
|
||||
# the terms of the GNU Affero General Public License as published by the
|
||||
@ -22,8 +22,7 @@
|
||||
|
||||
TARGET = retroshare-service
|
||||
|
||||
QT += core
|
||||
QT -= gui
|
||||
CONFIG -= qt
|
||||
|
||||
!include("../../libretroshare/src/use_libretroshare.pri"):error("Including")
|
||||
|
||||
@ -32,8 +31,6 @@ SOURCES += retroshare-service.cc
|
||||
################################# Linux ##########################################
|
||||
|
||||
android-* {
|
||||
QT += androidextras
|
||||
|
||||
ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android
|
||||
|
||||
DISTFILES += android/AndroidManifest.xml \
|
||||
@ -45,6 +42,9 @@ android-* {
|
||||
android/build.gradle \
|
||||
android/gradle/wrapper/gradle-wrapper.properties \
|
||||
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