mirror of
https://github.com/nerzhul/ownCloud-SMS-App.git
synced 2025-06-07 16:06:18 +00:00
Replace C++ with Cmake with GoLang gomobile
* Add ncsmsgo.arr which is the GoLang gomobile part See: https://gitlab.com/nerzhul/ncsmsgo * Android-NDK is not needed anymore * Android app getVersion() now uses the Golang part * Use the next getLastHTTPStatus() call in getVersion() * Android app pushSms() now uses the Golang part * JNI SmsBuffer has been replaced with GoLang aar bindings -> This permits to remove some java code & increase performance * Prepare a insecure switch flag to the Golang client
This commit is contained in:
parent
5317dc4fd9
commit
d57810b5d8
10
.travis.yml
10
.travis.yml
@ -11,6 +11,9 @@ cache:
|
|||||||
jdk:
|
jdk:
|
||||||
- oraclejdk8
|
- oraclejdk8
|
||||||
|
|
||||||
|
before_install:
|
||||||
|
- yes | sdkmanager "platforms;android-27"
|
||||||
|
|
||||||
android:
|
android:
|
||||||
components:
|
components:
|
||||||
- tools
|
- tools
|
||||||
@ -23,10 +26,3 @@ android:
|
|||||||
- 'google-gdk-license-.+'
|
- 'google-gdk-license-.+'
|
||||||
- 'android-sdk-preview-license-.+'
|
- 'android-sdk-preview-license-.+'
|
||||||
- 'android-.*'
|
- 'android-.*'
|
||||||
|
|
||||||
before_install:
|
|
||||||
- wget https://dl.google.com/android/repository/android-ndk-r16-linux-x86_64.zip > /dev/null
|
|
||||||
- mkdir -p /usr/local/android-sdk/ndk-bundle
|
|
||||||
- unzip android-ndk-r16-linux-x86_64.zip -d /usr/local/android-sdk/ndk-bundle > /dev/null
|
|
||||||
- export ANDROID_NDK_HOME="/usr/local/android-sdk/ndk-bundle/android-ndk-r16"
|
|
||||||
- rm -Rf "${ANDROID_HOME}/cmake"
|
|
@ -1,14 +0,0 @@
|
|||||||
cmake_minimum_required(VERSION 3.5.0)
|
|
||||||
|
|
||||||
set (SRC_FILES
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/main/cpp/httpclient.cpp
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/main/cpp/json.cpp
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/main/cpp/nativesms.cpp
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/main/cpp/smsbuffer.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
find_library(LOGGING_LIBRARY log)
|
|
||||||
|
|
||||||
add_library(nativesms SHARED ${SRC_FILES})
|
|
||||||
|
|
||||||
target_link_libraries(nativesms ${LOGGING_LIBRARY})
|
|
@ -2,6 +2,7 @@ buildscript {
|
|||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
jcenter()
|
jcenter()
|
||||||
|
google()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:3.0.1'
|
classpath 'com.android.tools.build:gradle:3.0.1'
|
||||||
@ -47,11 +48,6 @@ android {
|
|||||||
packagingOptions {
|
packagingOptions {
|
||||||
exclude 'META-INF/LICENSE.txt'
|
exclude 'META-INF/LICENSE.txt'
|
||||||
}
|
}
|
||||||
externalNativeBuild {
|
|
||||||
cmake {
|
|
||||||
path 'CMakeLists.txt'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
@ -69,4 +65,5 @@ dependencies {
|
|||||||
compile 'in.srain.cube:ultra-ptr:1.0.11'
|
compile 'in.srain.cube:ultra-ptr:1.0.11'
|
||||||
compile 'com.github.dmytrodanylyk.android-process-button:library:1.0.4'
|
compile 'com.github.dmytrodanylyk.android-process-button:library:1.0.4'
|
||||||
compile 'com.android.support:support-v4:27.0.2'
|
compile 'com.android.support:support-v4:27.0.2'
|
||||||
|
implementation project(':ncsmsgo')
|
||||||
}
|
}
|
||||||
|
2
ncsmsgo/build.gradle
Normal file
2
ncsmsgo/build.gradle
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
configurations.maybeCreate("default")
|
||||||
|
artifacts.add("default", file('ncsmsgo.aar'))
|
BIN
ncsmsgo/ncsmsgo.aar
Normal file
BIN
ncsmsgo/ncsmsgo.aar
Normal file
Binary file not shown.
25
ncsmsgo/ncsmsgo.iml
Normal file
25
ncsmsgo/ncsmsgo.iml
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module external.linked.project.id=":ncsmsgo" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" type="JAVA_MODULE" version="4">
|
||||||
|
<component name="FacetManager">
|
||||||
|
<facet type="android-gradle" name="Android-Gradle">
|
||||||
|
<configuration>
|
||||||
|
<option name="GRADLE_PROJECT_PATH" value=":ncsmsgo" />
|
||||||
|
</configuration>
|
||||||
|
</facet>
|
||||||
|
<facet type="java-gradle" name="Java-Gradle">
|
||||||
|
<configuration>
|
||||||
|
<option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" />
|
||||||
|
<option name="BUILDABLE" value="false" />
|
||||||
|
</configuration>
|
||||||
|
</facet>
|
||||||
|
</component>
|
||||||
|
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="true">
|
||||||
|
<exclude-output />
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/.gradle" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
1
settings.gradle
Normal file
1
settings.gradle
Normal file
@ -0,0 +1 @@
|
|||||||
|
include ':ncsmsgo'
|
@ -1,56 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2017, Loic Blot <loic.blot@unix-experience.fr>
|
|
||||||
*
|
|
||||||
* 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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "httpclient.h"
|
|
||||||
|
|
||||||
const char *HTTPClient::classPathName = "fr/unix_experience/owncloud_sms/engine/OCHttpClient";
|
|
||||||
|
|
||||||
// See https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/types.html
|
|
||||||
JNINativeMethod HTTPClient::methods[] =
|
|
||||||
{
|
|
||||||
DECL_JNIMETHOD(getAllSmsIdsCall, "()Ljava/lang/String;")
|
|
||||||
DECL_JNIMETHOD(getLastMsgTimestamp, "()Ljava/lang/String;")
|
|
||||||
DECL_JNIMETHOD(getPushRoute, "()Ljava/lang/String;")
|
|
||||||
DECL_JNIMETHOD(getVersionCall, "()Ljava/lang/String;")
|
|
||||||
};
|
|
||||||
DECL_METHODSIZE(HTTPClient)
|
|
||||||
|
|
||||||
// APIv1 calls
|
|
||||||
#define RCALL_GET_VERSION "/index.php/apps/ocsms/get/apiversion?format=json"
|
|
||||||
#define RCALL_GET_ALL_SMS_IDS "/index.php/apps/ocsms/get/smsidlist?format=json"
|
|
||||||
#define RCALL_GET_LAST_MSG_TIMESTAMP "/index.php/apps/ocsms/get/lastmsgtime?format=json"
|
|
||||||
#define RCALL_PUSH_ROUTE "/index.php/apps/ocsms/push?format=json"
|
|
||||||
|
|
||||||
jstring HTTPClient::getVersionCall(JNIEnv *env, jobject)
|
|
||||||
{
|
|
||||||
return env->NewStringUTF(RCALL_GET_VERSION);
|
|
||||||
}
|
|
||||||
|
|
||||||
jstring HTTPClient::getAllSmsIdsCall(JNIEnv *env, jobject)
|
|
||||||
{
|
|
||||||
return env->NewStringUTF(RCALL_GET_ALL_SMS_IDS);
|
|
||||||
}
|
|
||||||
|
|
||||||
jstring HTTPClient::getLastMsgTimestamp(JNIEnv *env, jobject)
|
|
||||||
{
|
|
||||||
return env->NewStringUTF(RCALL_GET_LAST_MSG_TIMESTAMP);
|
|
||||||
}
|
|
||||||
|
|
||||||
jstring HTTPClient::getPushRoute(JNIEnv *env, jobject)
|
|
||||||
{
|
|
||||||
return env->NewStringUTF(RCALL_PUSH_ROUTE);
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2017, Loic Blot <loic.blot@unix-experience.fr>
|
|
||||||
*
|
|
||||||
* 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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <jni.h>
|
|
||||||
#include "macro_helpers.h"
|
|
||||||
|
|
||||||
class HTTPClient
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
JNIEXPORT static jstring JNICALL getVersionCall(JNIEnv *env, jobject);
|
|
||||||
JNIEXPORT static jstring JNICALL getAllSmsIdsCall(JNIEnv *env, jobject);
|
|
||||||
JNIEXPORT static jstring JNICALL getLastMsgTimestamp(JNIEnv *env, jobject);
|
|
||||||
JNIEXPORT static jstring JNICALL getPushRoute(JNIEnv *env, jobject);
|
|
||||||
|
|
||||||
DECL_JNICLASSATTRS
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
@ -1,73 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2017, Loic Blot <loic.blot@unix-experience.fr>
|
|
||||||
*
|
|
||||||
* 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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "json.h"
|
|
||||||
#include <iomanip>
|
|
||||||
#include <sstream>
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
namespace json {
|
|
||||||
|
|
||||||
std::string escape_string(const char *str)
|
|
||||||
{
|
|
||||||
if (!str) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string result;
|
|
||||||
// Create a sufficient buffer to escape all chars
|
|
||||||
result.reserve(strlen(str) * 2 + 3);
|
|
||||||
result += "\"";
|
|
||||||
for (const char *c = str; *c != 0; ++c) {
|
|
||||||
switch (*c) {
|
|
||||||
case '\"':
|
|
||||||
result += "\\\"";
|
|
||||||
break;
|
|
||||||
case '\\':
|
|
||||||
result += "\\\\";
|
|
||||||
break;
|
|
||||||
case '\b':
|
|
||||||
result += "\\b";
|
|
||||||
break;
|
|
||||||
case '\t':
|
|
||||||
result += "\\t";
|
|
||||||
break;
|
|
||||||
case '\n':
|
|
||||||
result += "\\n";
|
|
||||||
break;
|
|
||||||
case '\f':
|
|
||||||
result += "\\f";
|
|
||||||
break;
|
|
||||||
case '\r':
|
|
||||||
result += "\\r";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (is_control_character(*c)) {
|
|
||||||
std::stringstream oss;
|
|
||||||
oss << "\\u" << std::hex << std::uppercase << std::setfill('0')
|
|
||||||
<< std::setw(4) << static_cast<int>(*c);
|
|
||||||
result += oss.str();
|
|
||||||
} else {
|
|
||||||
result += *c;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result += "\"";
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2017, Loic Blot <loic.blot@unix-experience.fr>
|
|
||||||
*
|
|
||||||
* 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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace json {
|
|
||||||
|
|
||||||
static inline bool is_control_character(char ch)
|
|
||||||
{ return ch > 0 && ch <= 0x1F; }
|
|
||||||
|
|
||||||
std::string escape_string(const char *str);
|
|
||||||
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2017, Loic Blot <loic.blot@unix-experience.fr>
|
|
||||||
*
|
|
||||||
* 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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#define DECL_JNIMETHOD(name, type) \
|
|
||||||
{#name, type, (void*) &name },
|
|
||||||
|
|
||||||
#define DECL_METHODSIZE(T) \
|
|
||||||
int T::methods_size = sizeof(T::methods) / sizeof(T::methods[0]);
|
|
||||||
|
|
||||||
#define DECL_JNICLASSATTRS \
|
|
||||||
static const char *classPathName; \
|
|
||||||
static JNINativeMethod methods[]; \
|
|
||||||
static int methods_size;
|
|
@ -1,76 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2014-2017, Loic Blot <loic.blot@unix-experience.fr>
|
|
||||||
*
|
|
||||||
* 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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <jni.h>
|
|
||||||
#include <android/log.h>
|
|
||||||
#include "httpclient.h"
|
|
||||||
#include "smsbuffer.h"
|
|
||||||
|
|
||||||
#define LOG_TAG "nativesms.cpp"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Register several native methods for one class.
|
|
||||||
*/
|
|
||||||
static int registerNativeMethods(JNIEnv* env, const char* className,
|
|
||||||
JNINativeMethod* gMethods, int numMethods)
|
|
||||||
{
|
|
||||||
jclass clazz;
|
|
||||||
clazz = env->FindClass(className);
|
|
||||||
__android_log_print(ANDROID_LOG_INFO, LOG_TAG, "Registering class '%s'", className);
|
|
||||||
if (clazz == NULL) {
|
|
||||||
__android_log_print(ANDROID_LOG_FATAL, LOG_TAG, "Native registration unable to find class %s", className);
|
|
||||||
return JNI_FALSE;
|
|
||||||
}
|
|
||||||
if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) {
|
|
||||||
__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "RegisterNatives failed for %s", className);
|
|
||||||
return JNI_FALSE;
|
|
||||||
}
|
|
||||||
return JNI_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int registerNatives(JNIEnv* env)
|
|
||||||
{
|
|
||||||
if (!registerNativeMethods(env,
|
|
||||||
HTTPClient::classPathName,
|
|
||||||
HTTPClient::methods,
|
|
||||||
HTTPClient::methods_size)) {
|
|
||||||
return JNI_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!registerNativeMethods(env,
|
|
||||||
SmsBuffer::classPathName,
|
|
||||||
SmsBuffer::methods,
|
|
||||||
SmsBuffer::methods_size)) {
|
|
||||||
return JNI_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return JNI_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
jint JNI_OnLoad(JavaVM* vm, void* reserved)
|
|
||||||
{
|
|
||||||
__android_log_print(ANDROID_LOG_INFO, LOG_TAG, "NativeSMS library loading...");
|
|
||||||
JNIEnv* env;
|
|
||||||
if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
registerNatives(env);
|
|
||||||
|
|
||||||
__android_log_print(ANDROID_LOG_INFO, LOG_TAG, "NativeSMS library loaded.");
|
|
||||||
return JNI_VERSION_1_6;
|
|
||||||
}
|
|
@ -1,162 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2017, Loic Blot <loic.blot@unix-experience.fr>
|
|
||||||
*
|
|
||||||
* 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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <android/log.h>
|
|
||||||
#include <cassert>
|
|
||||||
#include <iomanip>
|
|
||||||
#include "smsbuffer.h"
|
|
||||||
#include "json.h"
|
|
||||||
|
|
||||||
#define LOG_TAG "SmsBuffer"
|
|
||||||
const char *SmsBuffer::classPathName = "fr/unix_experience/owncloud_sms/jni/SmsBuffer";
|
|
||||||
|
|
||||||
// See https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/types.html
|
|
||||||
JNINativeMethod SmsBuffer::methods[] =
|
|
||||||
{
|
|
||||||
DECL_JNIMETHOD(createNativeObject, "()J")
|
|
||||||
DECL_JNIMETHOD(deleteNativeObject, "()V")
|
|
||||||
DECL_JNIMETHOD(empty, "()Z")
|
|
||||||
DECL_JNIMETHOD(asRawJsonString, "()Ljava/lang/String;")
|
|
||||||
DECL_JNIMETHOD(getLastMessageDate, "()J")
|
|
||||||
DECL_JNIMETHOD(push,
|
|
||||||
"(IIIJLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V")
|
|
||||||
DECL_JNIMETHOD(print, "()V")
|
|
||||||
};
|
|
||||||
DECL_METHODSIZE(SmsBuffer)
|
|
||||||
|
|
||||||
#define SMSBUFFER_CAST \
|
|
||||||
if (!SmsBuffer::gJava_inited) { \
|
|
||||||
SmsBuffer::gJava_inited = true; \
|
|
||||||
SmsBuffer::gJava_mHandle = env->GetFieldID(env->GetObjectClass(self), "mHandle", "J"); \
|
|
||||||
} \
|
|
||||||
long ptr = env->GetLongField(self, SmsBuffer::gJava_mHandle); \
|
|
||||||
SmsBuffer *me = reinterpret_cast<SmsBuffer *>(ptr); \
|
|
||||||
if (!me) { \
|
|
||||||
__android_log_print(ANDROID_LOG_FATAL, LOG_TAG, "It's not a SmsBuffer!"); \
|
|
||||||
assert(false); \
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SmsBuffer::gJava_inited = false;
|
|
||||||
jfieldID SmsBuffer::gJava_mHandle{};
|
|
||||||
|
|
||||||
jlong SmsBuffer::createNativeObject(JNIEnv *env, jobject self)
|
|
||||||
{
|
|
||||||
return reinterpret_cast<jlong>(new SmsBuffer());
|
|
||||||
}
|
|
||||||
|
|
||||||
void SmsBuffer::deleteNativeObject(JNIEnv *env, jobject self)
|
|
||||||
{
|
|
||||||
SMSBUFFER_CAST
|
|
||||||
__android_log_print(ANDROID_LOG_INFO, LOG_TAG, "deleteNativeObject 0x%li", ptr);
|
|
||||||
delete reinterpret_cast<SmsBuffer *>(ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SmsBuffer::reset_buffer()
|
|
||||||
{
|
|
||||||
m_buffer.clear();
|
|
||||||
m_buffer_empty = true;
|
|
||||||
m_sms_count = 0;
|
|
||||||
m_last_message_date = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SmsBuffer::push(JNIEnv *env, jobject self, jint msg_id, jint mailbox_id, jint type,
|
|
||||||
jlong date, jstring address, jstring body, jstring read, jstring seen)
|
|
||||||
{
|
|
||||||
SMSBUFFER_CAST
|
|
||||||
me->_push(msg_id, mailbox_id, type, date, env->GetStringUTFChars(address, NULL),
|
|
||||||
env->GetStringUTFChars(body, NULL), env->GetStringUTFChars(read, NULL),
|
|
||||||
env->GetStringUTFChars(seen, NULL));
|
|
||||||
}
|
|
||||||
|
|
||||||
void SmsBuffer::_push(int msg_id, int mailbox_id, int type,
|
|
||||||
long long date, const char *address, const char *body, const char *read,
|
|
||||||
const char *seen)
|
|
||||||
{
|
|
||||||
// If buffer is not empty, we are joining messages
|
|
||||||
if (!m_buffer_empty) {
|
|
||||||
m_buffer << ",";
|
|
||||||
}
|
|
||||||
// Else, we are starting array
|
|
||||||
else {
|
|
||||||
m_buffer << "[";
|
|
||||||
m_buffer_empty = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_buffer << "{\"_id\":" << msg_id << ","
|
|
||||||
<< "\"mbox\":" << mailbox_id << ","
|
|
||||||
<< "\"type\":" << type << ","
|
|
||||||
<< "\"date\":" << date << ","
|
|
||||||
<< "\"body\":" << json::escape_string(body) << ","
|
|
||||||
<< "\"address\":" << json::escape_string(address) << ","
|
|
||||||
<< "\"read\":" << json::escape_string(read) << ","
|
|
||||||
<< "\"seen\":" << json::escape_string(seen)
|
|
||||||
<< "}";
|
|
||||||
|
|
||||||
if (date > m_last_message_date) {
|
|
||||||
m_last_message_date = date;
|
|
||||||
}
|
|
||||||
m_sms_count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
jboolean SmsBuffer::empty(JNIEnv *env, jobject self)
|
|
||||||
{
|
|
||||||
SMSBUFFER_CAST
|
|
||||||
return (jboolean) (me->_empty() ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SmsBuffer::_empty() const
|
|
||||||
{
|
|
||||||
return m_buffer_empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SmsBuffer::print(JNIEnv *env, jobject self)
|
|
||||||
{
|
|
||||||
SMSBUFFER_CAST
|
|
||||||
me->_print();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SmsBuffer::_print()
|
|
||||||
{
|
|
||||||
__android_log_print(ANDROID_LOG_INFO, LOG_TAG, "SmsBuffer content: '%s'",
|
|
||||||
m_buffer.str().c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
jstring SmsBuffer::asRawJsonString(JNIEnv *env, jobject self)
|
|
||||||
{
|
|
||||||
SMSBUFFER_CAST
|
|
||||||
std::string result;
|
|
||||||
me->as_raw_json_string(result);
|
|
||||||
return env->NewStringUTF(result.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
void SmsBuffer::as_raw_json_string(std::string &result)
|
|
||||||
{
|
|
||||||
std::stringstream ss;
|
|
||||||
ss << "{\"smsCount\": " << m_sms_count << ", \"smsDatas\": " << m_buffer.str() << "]}";
|
|
||||||
result = ss.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
jlong SmsBuffer::getLastMessageDate(JNIEnv *env, jobject self)
|
|
||||||
{
|
|
||||||
SMSBUFFER_CAST
|
|
||||||
return me->_get_last_message_date();
|
|
||||||
}
|
|
||||||
|
|
||||||
long long SmsBuffer::_get_last_message_date() const
|
|
||||||
{
|
|
||||||
return m_last_message_date;
|
|
||||||
}
|
|
@ -1,80 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2017, Loic Blot <loic.blot@unix-experience.fr>
|
|
||||||
*
|
|
||||||
* 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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <jni.h>
|
|
||||||
#include <sstream>
|
|
||||||
#include "macro_helpers.h"
|
|
||||||
|
|
||||||
class SmsBuffer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SmsBuffer() = default;
|
|
||||||
~SmsBuffer() = default;
|
|
||||||
|
|
||||||
JNIEXPORT static jlong JNICALL createNativeObject(JNIEnv *env, jobject self);
|
|
||||||
JNIEXPORT static void JNICALL deleteNativeObject(JNIEnv *env, jobject self);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* push method
|
|
||||||
*/
|
|
||||||
JNIEXPORT static void JNICALL push(JNIEnv *env, jobject self, jint msg_id,
|
|
||||||
jint mailbox_id, jint type, jlong date, jstring address,
|
|
||||||
jstring body, jstring read, jstring seen);
|
|
||||||
void _push(int msg_id, int mailbox_id, int type,
|
|
||||||
long long date, const char *address, const char *body, const char *read,
|
|
||||||
const char *seen);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* empty method
|
|
||||||
*/
|
|
||||||
|
|
||||||
JNIEXPORT static jboolean JNICALL empty(JNIEnv *env, jobject self);
|
|
||||||
bool _empty() const;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* print method
|
|
||||||
*/
|
|
||||||
JNIEXPORT static void JNICALL print(JNIEnv *env, jobject self);
|
|
||||||
void _print();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* asRawJsonString method
|
|
||||||
*/
|
|
||||||
JNIEXPORT static jstring JNICALL asRawJsonString(JNIEnv *env, jobject self);
|
|
||||||
void as_raw_json_string(std::string &result);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* getLastMessageDate method
|
|
||||||
*/
|
|
||||||
|
|
||||||
JNIEXPORT static jlong JNICALL getLastMessageDate(JNIEnv *env, jobject self);
|
|
||||||
long long _get_last_message_date() const;
|
|
||||||
|
|
||||||
DECL_JNICLASSATTRS
|
|
||||||
|
|
||||||
private:
|
|
||||||
void reset_buffer();
|
|
||||||
std::stringstream m_buffer;
|
|
||||||
uint32_t m_sms_count{0};
|
|
||||||
bool m_buffer_empty{true};
|
|
||||||
long long m_last_message_date{0};
|
|
||||||
|
|
||||||
static bool gJava_inited;
|
|
||||||
static jfieldID gJava_mHandle;
|
|
||||||
};
|
|
@ -208,7 +208,7 @@ public class AppCompatListActivity extends AppCompatActivity {
|
|||||||
super.onContentChanged();
|
super.onContentChanged();
|
||||||
|
|
||||||
View emptyView = findViewById(R.id.empty);
|
View emptyView = findViewById(R.id.empty);
|
||||||
mList = (ListView)findViewById(R.id.list);
|
mList = findViewById(R.id.list);
|
||||||
if (mList == null) {
|
if (mList == null) {
|
||||||
throw new RuntimeException(
|
throw new RuntimeException(
|
||||||
"Your content must have a ListView whose id attribute is " +
|
"Your content must have a ListView whose id attribute is " +
|
||||||
|
@ -44,8 +44,6 @@ import android.widget.TextView;
|
|||||||
|
|
||||||
import com.dd.processbutton.iml.ActionProcessButton;
|
import com.dd.processbutton.iml.ActionProcessButton;
|
||||||
|
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
|
||||||
@ -85,11 +83,11 @@ public class LoginActivity extends AppCompatActivity {
|
|||||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||||
|
|
||||||
// Set up the login form.
|
// Set up the login form.
|
||||||
_protocolView = (Spinner) findViewById(R.id.oc_protocol);
|
_protocolView = findViewById(R.id.oc_protocol);
|
||||||
_serverView = (EditText) findViewById(R.id.oc_server);
|
_serverView = findViewById(R.id.oc_server);
|
||||||
_loginView = (EditText) findViewById(R.id.oc_login);
|
_loginView = findViewById(R.id.oc_login);
|
||||||
|
|
||||||
_passwordView = (EditText) findViewById(R.id.oc_password);
|
_passwordView = findViewById(R.id.oc_password);
|
||||||
_passwordView
|
_passwordView
|
||||||
.setOnEditorActionListener(new TextView.OnEditorActionListener() {
|
.setOnEditorActionListener(new TextView.OnEditorActionListener() {
|
||||||
@Override
|
@Override
|
||||||
@ -103,7 +101,7 @@ public class LoginActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
_signInButton = (ActionProcessButton) findViewById(R.id.oc_signin_button);
|
_signInButton = findViewById(R.id.oc_signin_button);
|
||||||
_signInButton.setOnClickListener(new OnClickListener() {
|
_signInButton.setOnClickListener(new OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
@ -270,8 +268,8 @@ public class LoginActivity extends AppCompatActivity {
|
|||||||
_returnCode = 0;
|
_returnCode = 0;
|
||||||
OCHttpClient http = new OCHttpClient(getBaseContext(), _serverURL, _login, _password);
|
OCHttpClient http = new OCHttpClient(getBaseContext(), _serverURL, _login, _password);
|
||||||
try {
|
try {
|
||||||
Pair<Integer, JSONObject> response = http.getVersion();
|
Pair<Integer, Integer> vPair = http.getVersion();
|
||||||
_returnCode = response.first;
|
_returnCode = vPair.first;
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
Log.w(TAG, "Failed to getVersion, IllegalArgumentException occured: " + e.getMessage());
|
Log.w(TAG, "Failed to getVersion, IllegalArgumentException occured: " + e.getMessage());
|
||||||
_returnCode = 597;
|
_returnCode = 597;
|
||||||
|
@ -76,7 +76,7 @@ public class MainActivity extends AppCompatActivity
|
|||||||
getSupportActionBar().setHomeButtonEnabled(true);
|
getSupportActionBar().setHomeButtonEnabled(true);
|
||||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||||
|
|
||||||
drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
|
drawer = findViewById(R.id.drawer_layout);
|
||||||
setupDrawer();
|
setupDrawer();
|
||||||
drawer.openDrawer(GravityCompat.START);
|
drawer.openDrawer(GravityCompat.START);
|
||||||
}
|
}
|
||||||
@ -93,7 +93,7 @@ public class MainActivity extends AppCompatActivity
|
|||||||
toggle.syncState();
|
toggle.syncState();
|
||||||
toggle.setDrawerIndicatorEnabled(true);
|
toggle.setDrawerIndicatorEnabled(true);
|
||||||
|
|
||||||
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
|
NavigationView navigationView = findViewById(R.id.nav_view);
|
||||||
assert navigationView != null;
|
assert navigationView != null;
|
||||||
navigationView.setNavigationItemSelectedListener(this);
|
navigationView.setNavigationItemSelectedListener(this);
|
||||||
}
|
}
|
||||||
|
@ -55,12 +55,12 @@ public class ContactListActivity extends AppCompatActivity implements ASyncConta
|
|||||||
mObjects = new ArrayList<>();
|
mObjects = new ArrayList<>();
|
||||||
setContentView(R.layout.restore_activity_contactlist);
|
setContentView(R.layout.restore_activity_contactlist);
|
||||||
|
|
||||||
mLayout = (SwipeRefreshLayout) findViewById(R.id.contactlist_swipe_container);
|
mLayout = findViewById(R.id.contactlist_swipe_container);
|
||||||
|
|
||||||
mAdapter = new ContactListAdapter(getBaseContext(), mObjects);
|
mAdapter = new ContactListAdapter(getBaseContext(), mObjects);
|
||||||
|
|
||||||
mContactInfos = (LinearLayout) findViewById(R.id.contactinfos_layout);
|
mContactInfos = findViewById(R.id.contactinfos_layout);
|
||||||
ListView contactPhoneListView = (ListView) findViewById(R.id.contact_phonelistView);
|
ListView contactPhoneListView = findViewById(R.id.contact_phonelistView);
|
||||||
mContactPhoneListAdapter = new RecoveryPhoneNumberListViewAdapter(getBaseContext());
|
mContactPhoneListAdapter = new RecoveryPhoneNumberListViewAdapter(getBaseContext());
|
||||||
assert contactPhoneListView != null;
|
assert contactPhoneListView != null;
|
||||||
contactPhoneListView.setAdapter(mContactPhoneListAdapter);
|
contactPhoneListView.setAdapter(mContactPhoneListAdapter);
|
||||||
@ -72,7 +72,7 @@ public class ContactListActivity extends AppCompatActivity implements ASyncConta
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void createAccountList() {
|
private void createAccountList() {
|
||||||
final ProgressBar contactProgressBar = (ProgressBar) findViewById(R.id.contactlist_pgbar);
|
final ProgressBar contactProgressBar = findViewById(R.id.contactlist_pgbar);
|
||||||
assert contactProgressBar != null;
|
assert contactProgressBar != null;
|
||||||
|
|
||||||
String accountName = getIntent().getExtras().getString("account");
|
String accountName = getIntent().getExtras().getString("account");
|
||||||
@ -112,7 +112,7 @@ public class ContactListActivity extends AppCompatActivity implements ASyncConta
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void initSpinner() {
|
private void initSpinner() {
|
||||||
final Spinner sp = (Spinner) findViewById(R.id.contact_spinner);
|
final Spinner sp = findViewById(R.id.contact_spinner);
|
||||||
assert sp != null;
|
assert sp != null;
|
||||||
sp.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
sp.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -73,9 +73,9 @@ public class RestoreMessagesActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
initInterface();
|
initInterface();
|
||||||
Button fix_button = (Button) findViewById(R.id.button_fix_permissions);
|
Button fix_button = findViewById(R.id.button_fix_permissions);
|
||||||
final Button launch_restore = (Button) findViewById(R.id.button_launch_restore);
|
final Button launch_restore = findViewById(R.id.button_launch_restore);
|
||||||
final ProgressBar pb = (ProgressBar) findViewById(R.id.progressbar_restore);
|
final ProgressBar pb = findViewById(R.id.progressbar_restore);
|
||||||
|
|
||||||
final RestoreMessagesActivity me = this;
|
final RestoreMessagesActivity me = this;
|
||||||
fix_button.setOnClickListener(new View.OnClickListener() {
|
fix_button.setOnClickListener(new View.OnClickListener() {
|
||||||
@ -130,13 +130,13 @@ public class RestoreMessagesActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void initInterface() {
|
private void initInterface() {
|
||||||
TextView tv_error = (TextView) findViewById(R.id.tv_error_default_smsapp);
|
TextView tv_error = findViewById(R.id.tv_error_default_smsapp);
|
||||||
tv_error.setText(R.string.error_make_default_sms_app);
|
tv_error.setText(R.string.error_make_default_sms_app);
|
||||||
findViewById(R.id.tv_restore_finished).setVisibility(View.INVISIBLE);
|
findViewById(R.id.tv_restore_finished).setVisibility(View.INVISIBLE);
|
||||||
findViewById(R.id.tv_progress_value).setVisibility(View.INVISIBLE);
|
findViewById(R.id.tv_progress_value).setVisibility(View.INVISIBLE);
|
||||||
Button fix_button = (Button) findViewById(R.id.button_fix_permissions);
|
Button fix_button = findViewById(R.id.button_fix_permissions);
|
||||||
Button launch_restore = (Button) findViewById(R.id.button_launch_restore);
|
Button launch_restore = findViewById(R.id.button_launch_restore);
|
||||||
ProgressBar pb = (ProgressBar) findViewById(R.id.progressbar_restore);
|
ProgressBar pb = findViewById(R.id.progressbar_restore);
|
||||||
pb.setVisibility(View.INVISIBLE);
|
pb.setVisibility(View.INVISIBLE);
|
||||||
|
|
||||||
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.KITKAT) {
|
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.KITKAT) {
|
||||||
@ -158,10 +158,10 @@ public class RestoreMessagesActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void errorNotification(int err) {
|
private void errorNotification(int err) {
|
||||||
TextView tv = (TextView) findViewById(R.id.tv_error_default_smsapp);
|
TextView tv = findViewById(R.id.tv_error_default_smsapp);
|
||||||
Button fix_button = (Button) findViewById(R.id.button_fix_permissions);
|
Button fix_button = findViewById(R.id.button_fix_permissions);
|
||||||
Button launch_restore = (Button) findViewById(R.id.button_launch_restore);
|
Button launch_restore = findViewById(R.id.button_launch_restore);
|
||||||
ProgressBar pb = (ProgressBar) findViewById(R.id.progressbar_restore);
|
ProgressBar pb = findViewById(R.id.progressbar_restore);
|
||||||
tv.setText(err);
|
tv.setText(err);
|
||||||
tv.setVisibility(View.VISIBLE);
|
tv.setVisibility(View.VISIBLE);
|
||||||
fix_button.setVisibility(View.INVISIBLE);
|
fix_button.setVisibility(View.INVISIBLE);
|
||||||
@ -182,9 +182,9 @@ public class RestoreMessagesActivity extends AppCompatActivity {
|
|||||||
switch (requestCode) {
|
switch (requestCode) {
|
||||||
case RestoreMessagesActivity.REQUEST_DEFAULT_SMSAPP:
|
case RestoreMessagesActivity.REQUEST_DEFAULT_SMSAPP:
|
||||||
if (resultCode == Activity.RESULT_OK) {
|
if (resultCode == Activity.RESULT_OK) {
|
||||||
TextView tv = (TextView) findViewById(R.id.tv_error_default_smsapp);
|
TextView tv = findViewById(R.id.tv_error_default_smsapp);
|
||||||
Button fix_button = (Button) findViewById(R.id.button_fix_permissions);
|
Button fix_button = findViewById(R.id.button_fix_permissions);
|
||||||
Button launch_restore = (Button) findViewById(R.id.button_launch_restore);
|
Button launch_restore = findViewById(R.id.button_launch_restore);
|
||||||
tv.setVisibility(View.INVISIBLE);
|
tv.setVisibility(View.INVISIBLE);
|
||||||
fix_button.setVisibility(View.INVISIBLE);
|
fix_button.setVisibility(View.INVISIBLE);
|
||||||
launch_restore.setVisibility(View.VISIBLE);
|
launch_restore.setVisibility(View.VISIBLE);
|
||||||
@ -225,7 +225,7 @@ public class RestoreMessagesActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void onProgressUpdate(Integer value) {
|
public void onProgressUpdate(Integer value) {
|
||||||
TextView tv_progress = (TextView) findViewById(R.id.tv_progress_value);
|
TextView tv_progress = findViewById(R.id.tv_progress_value);
|
||||||
if (tv_progress.getVisibility() == View.INVISIBLE) {
|
if (tv_progress.getVisibility() == View.INVISIBLE) {
|
||||||
tv_progress.setVisibility(View.VISIBLE);
|
tv_progress.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ public class AndroidAccountAdapter extends ArrayAdapter<Account> {
|
|||||||
final Account account = _accounts.get(position);
|
final Account account = _accounts.get(position);
|
||||||
|
|
||||||
if (account != null) {
|
if (account != null) {
|
||||||
TextView label = (TextView) v.findViewById(AndroidAccountAdapter._accountFieldId);
|
TextView label = v.findViewById(AndroidAccountAdapter._accountFieldId);
|
||||||
if (label != null) {
|
if (label != null) {
|
||||||
label.setText(account.name + " >");
|
label.setText(account.name + " >");
|
||||||
v.setOnClickListener(new OnClickListener() {
|
v.setOnClickListener(new OnClickListener() {
|
||||||
|
@ -39,7 +39,7 @@ public class ContactListAdapter extends ArrayAdapter<String> {
|
|||||||
String element = _objects.get(position);
|
String element = _objects.get(position);
|
||||||
|
|
||||||
if (element != null) {
|
if (element != null) {
|
||||||
TextView label = (TextView) v.findViewById(ContactListAdapter._fieldId);
|
TextView label = v.findViewById(ContactListAdapter._fieldId);
|
||||||
if (label != null) {
|
if (label != null) {
|
||||||
label.setText(element);
|
label.setText(element);
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ public class RecoveryPhoneNumberListViewAdapter extends ArrayAdapter<String> {
|
|||||||
v = inflater.inflate(RecoveryPhoneNumberListViewAdapter._itemLayout, null);
|
v = inflater.inflate(RecoveryPhoneNumberListViewAdapter._itemLayout, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
TextView label = (TextView) v.findViewById(RecoveryPhoneNumberListViewAdapter._fieldId);
|
TextView label = v.findViewById(RecoveryPhoneNumberListViewAdapter._fieldId);
|
||||||
if (label != null) {
|
if (label != null) {
|
||||||
final String l = getItem(position).toString();
|
final String l = getItem(position).toString();
|
||||||
label.setText(getItem(position).toString());
|
label.setText(getItem(position).toString());
|
||||||
|
@ -32,9 +32,9 @@ import fr.unix_experience.owncloud_sms.engine.ASyncSMSSync;
|
|||||||
import fr.unix_experience.owncloud_sms.engine.AndroidSmsFetcher;
|
import fr.unix_experience.owncloud_sms.engine.AndroidSmsFetcher;
|
||||||
import fr.unix_experience.owncloud_sms.engine.ConnectivityMonitor;
|
import fr.unix_experience.owncloud_sms.engine.ConnectivityMonitor;
|
||||||
import fr.unix_experience.owncloud_sms.enums.PermissionID;
|
import fr.unix_experience.owncloud_sms.enums.PermissionID;
|
||||||
import fr.unix_experience.owncloud_sms.jni.SmsBuffer;
|
|
||||||
import fr.unix_experience.owncloud_sms.prefs.OCSMSSharedPrefs;
|
import fr.unix_experience.owncloud_sms.prefs.OCSMSSharedPrefs;
|
||||||
import fr.unix_experience.owncloud_sms.prefs.PermissionChecker;
|
import fr.unix_experience.owncloud_sms.prefs.PermissionChecker;
|
||||||
|
import ncsmsgo.SmsBuffer;
|
||||||
|
|
||||||
public class ConnectivityChanged extends BroadcastReceiver implements ASyncSMSSync {
|
public class ConnectivityChanged extends BroadcastReceiver implements ASyncSMSSync {
|
||||||
|
|
||||||
|
@ -28,9 +28,9 @@ import android.widget.Toast;
|
|||||||
import fr.unix_experience.owncloud_sms.R;
|
import fr.unix_experience.owncloud_sms.R;
|
||||||
import fr.unix_experience.owncloud_sms.enums.OCSMSNotificationType;
|
import fr.unix_experience.owncloud_sms.enums.OCSMSNotificationType;
|
||||||
import fr.unix_experience.owncloud_sms.exceptions.OCSyncException;
|
import fr.unix_experience.owncloud_sms.exceptions.OCSyncException;
|
||||||
import fr.unix_experience.owncloud_sms.jni.SmsBuffer;
|
|
||||||
import fr.unix_experience.owncloud_sms.notifications.OCSMSNotificationUI;
|
import fr.unix_experience.owncloud_sms.notifications.OCSMSNotificationUI;
|
||||||
import fr.unix_experience.owncloud_sms.prefs.OCSMSSharedPrefs;
|
import fr.unix_experience.owncloud_sms.prefs.OCSMSSharedPrefs;
|
||||||
|
import ncsmsgo.SmsBuffer;
|
||||||
|
|
||||||
public interface ASyncSMSSync {
|
public interface ASyncSMSSync {
|
||||||
class SyncTask extends AsyncTask<Void, Void, Void> {
|
class SyncTask extends AsyncTask<Void, Void, Void> {
|
||||||
|
@ -25,8 +25,8 @@ import org.json.JSONArray;
|
|||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
|
|
||||||
import fr.unix_experience.owncloud_sms.enums.MailboxID;
|
import fr.unix_experience.owncloud_sms.enums.MailboxID;
|
||||||
import fr.unix_experience.owncloud_sms.jni.SmsBuffer;
|
|
||||||
import fr.unix_experience.owncloud_sms.providers.SmsDataProvider;
|
import fr.unix_experience.owncloud_sms.providers.SmsDataProvider;
|
||||||
|
import ncsmsgo.SmsBuffer;
|
||||||
|
|
||||||
public class AndroidSmsFetcher {
|
public class AndroidSmsFetcher {
|
||||||
public AndroidSmsFetcher(Context ct) {
|
public AndroidSmsFetcher(Context ct) {
|
||||||
@ -53,7 +53,14 @@ public class AndroidSmsFetcher {
|
|||||||
|
|
||||||
// Mailbox ID is required by server
|
// Mailbox ID is required by server
|
||||||
entry.mailboxId = mbID.ordinal();
|
entry.mailboxId = mbID.ordinal();
|
||||||
smsBuffer.push(mbID, entry);
|
smsBuffer.push(entry.id,
|
||||||
|
mbID.ordinal(),
|
||||||
|
entry.type,
|
||||||
|
entry.date,
|
||||||
|
entry.address,
|
||||||
|
entry.body,
|
||||||
|
entry.read ? "true" : "false",
|
||||||
|
entry.seen ? "true" : "false");
|
||||||
}
|
}
|
||||||
while (c.moveToNext());
|
while (c.moveToNext());
|
||||||
}
|
}
|
||||||
@ -114,7 +121,14 @@ public class AndroidSmsFetcher {
|
|||||||
* aren't indexed in the same mean
|
* aren't indexed in the same mean
|
||||||
*/
|
*/
|
||||||
entry.mailboxId = mboxId - 1;
|
entry.mailboxId = mboxId - 1;
|
||||||
results.push(mbID, entry);
|
results.push(entry.id,
|
||||||
|
mbID.ordinal(),
|
||||||
|
entry.type,
|
||||||
|
entry.date,
|
||||||
|
entry.address,
|
||||||
|
entry.body,
|
||||||
|
entry.read ? "true" : "false",
|
||||||
|
entry.seen ? "true" : "false");
|
||||||
|
|
||||||
c.close();
|
c.close();
|
||||||
|
|
||||||
|
@ -45,16 +45,12 @@ import fr.unix_experience.owncloud_sms.R;
|
|||||||
import fr.unix_experience.owncloud_sms.enums.OCSyncErrorType;
|
import fr.unix_experience.owncloud_sms.enums.OCSyncErrorType;
|
||||||
import fr.unix_experience.owncloud_sms.exceptions.OCSyncException;
|
import fr.unix_experience.owncloud_sms.exceptions.OCSyncException;
|
||||||
import fr.unix_experience.owncloud_sms.providers.AndroidVersionProvider;
|
import fr.unix_experience.owncloud_sms.providers.AndroidVersionProvider;
|
||||||
|
import ncsmsgo.SmsBuffer;
|
||||||
|
import ncsmsgo.SmsHTTPClient;
|
||||||
|
import ncsmsgo.SmsPushResponse;
|
||||||
|
|
||||||
public class OCHttpClient {
|
public class OCHttpClient {
|
||||||
static {
|
private SmsHTTPClient _smsHttpClient;
|
||||||
System.loadLibrary("nativesms");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static native String getAllSmsIdsCall();
|
|
||||||
public static native String getLastMsgTimestamp();
|
|
||||||
public static native String getPushRoute();
|
|
||||||
public static native String getVersionCall();
|
|
||||||
|
|
||||||
private static final String TAG = OCHttpClient.class.getCanonicalName();
|
private static final String TAG = OCHttpClient.class.getCanonicalName();
|
||||||
private static final String PARAM_PROTOCOL_VERSION = "http.protocol.version";
|
private static final String PARAM_PROTOCOL_VERSION = "http.protocol.version";
|
||||||
@ -63,12 +59,6 @@ public class OCHttpClient {
|
|||||||
private final String _username;
|
private final String _username;
|
||||||
private final String _password;
|
private final String _password;
|
||||||
|
|
||||||
// API v2 calls
|
|
||||||
private static final String OC_V2_GET_PHONELIST = "/index.php/apps/ocsms/api/v2/phones/list?format=json";
|
|
||||||
private static final String OC_V2_GET_MESSAGES ="/index.php/apps/ocsms/api/v2/messages/[START]/[LIMIT]?format=json";
|
|
||||||
private static final String OC_V2_GET_MESSAGES_PHONE ="/index.php/apps/ocsms/api/v2/messages/[PHONENUMBER]/[START]/[LIMIT]?format=json";
|
|
||||||
private static final String OC_V2_GET_MESSAGES_SENDQUEUE = "/index.php/apps/ocsms/api/v2/messages/sendqueue?format=json";
|
|
||||||
|
|
||||||
public OCHttpClient(Context context, URL serverURL, String accountName, String accountPassword) {
|
public OCHttpClient(Context context, URL serverURL, String accountName, String accountPassword) {
|
||||||
// Create a trust manager that does not validate certificate chains
|
// Create a trust manager that does not validate certificate chains
|
||||||
TrustManager[] trustAllCerts = new TrustManager[]{
|
TrustManager[] trustAllCerts = new TrustManager[]{
|
||||||
@ -97,6 +87,11 @@ public class OCHttpClient {
|
|||||||
_username = accountName;
|
_username = accountName;
|
||||||
_password = accountPassword;
|
_password = accountPassword;
|
||||||
|
|
||||||
|
_smsHttpClient = new SmsHTTPClient();
|
||||||
|
// @TODO: at a point add a flag to permit insecure connections somewhere instead of trusting them
|
||||||
|
_smsHttpClient.init(_url.toString(), new AndroidVersionProvider(context).getVersionCode(),
|
||||||
|
_username, _password, false);
|
||||||
|
|
||||||
_userAgent = "nextcloud-phonesync (" + new AndroidVersionProvider(context).getVersionCode() + ")";
|
_userAgent = "nextcloud-phonesync (" + new AndroidVersionProvider(context).getVersionCode() + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,23 +122,46 @@ public class OCHttpClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Pair<Integer, JSONObject> getAllSmsIds() throws OCSyncException {
|
Pair<Integer, JSONObject> getAllSmsIds() throws OCSyncException {
|
||||||
return get(OCHttpClient.getAllSmsIdsCall(), false);
|
return get(_smsHttpClient.getAllSmsIdsCall(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Pair<Integer, JSONObject> getVersion() throws OCSyncException {
|
// Perform the GoLang doVersionCall and handle return
|
||||||
return get(OCHttpClient.getVersionCall(), true);
|
public Pair<Integer, Integer> getVersion() throws OCSyncException {
|
||||||
|
Integer serverAPIVersion = (int) _smsHttpClient.doVersionCall();
|
||||||
|
int httpStatus = (int) _smsHttpClient.getLastHTTPStatus();
|
||||||
|
|
||||||
|
// If last status is not 200, send the wrong status now
|
||||||
|
if (httpStatus != 200) {
|
||||||
|
return new Pair<>(httpStatus, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Pair<Integer, JSONObject> pushSms(String smsBuf) throws OCSyncException {
|
if (serverAPIVersion > 0) {
|
||||||
return post(OCHttpClient.getPushRoute(), smsBuf);
|
return new Pair<>(200, serverAPIVersion);
|
||||||
|
}
|
||||||
|
else if (serverAPIVersion == 0) {
|
||||||
|
// Return default version
|
||||||
|
return new Pair<>(200, 1);
|
||||||
|
}
|
||||||
|
else if (serverAPIVersion == -1) {
|
||||||
|
// This return code from API means I/O error
|
||||||
|
throw new OCSyncException(R.string.err_sync_http_request_ioexception, OCSyncErrorType.IO);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new OCSyncException(R.string.err_sync_http_request_returncode_unhandled, OCSyncErrorType.SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Pair<Integer, SmsPushResponse> pushSms(SmsBuffer smsBuf) throws OCSyncException {
|
||||||
|
SmsPushResponse spr = _smsHttpClient.doPushCall(smsBuf);
|
||||||
|
return new Pair<>((int) _smsHttpClient.getLastHTTPStatus(), spr);
|
||||||
}
|
}
|
||||||
|
|
||||||
Pair<Integer, JSONObject> getPhoneList() throws OCSyncException {
|
Pair<Integer, JSONObject> getPhoneList() throws OCSyncException {
|
||||||
return get(OCHttpClient.OC_V2_GET_PHONELIST, true);
|
return get(_smsHttpClient.getPhoneListCall(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Pair<Integer, JSONObject> getMessages(Long start, Integer limit) throws OCSyncException {
|
Pair<Integer, JSONObject> getMessages(Long start, Integer limit) throws OCSyncException {
|
||||||
return get(OCHttpClient.OC_V2_GET_MESSAGES
|
return get(_smsHttpClient.getMessagesCall()
|
||||||
.replace("[START]", start.toString())
|
.replace("[START]", start.toString())
|
||||||
.replace("[LIMIT]", limit.toString()), false);
|
.replace("[LIMIT]", limit.toString()), false);
|
||||||
}
|
}
|
||||||
|
@ -33,8 +33,9 @@ import java.net.URL;
|
|||||||
import fr.unix_experience.owncloud_sms.R;
|
import fr.unix_experience.owncloud_sms.R;
|
||||||
import fr.unix_experience.owncloud_sms.enums.OCSyncErrorType;
|
import fr.unix_experience.owncloud_sms.enums.OCSyncErrorType;
|
||||||
import fr.unix_experience.owncloud_sms.exceptions.OCSyncException;
|
import fr.unix_experience.owncloud_sms.exceptions.OCSyncException;
|
||||||
import fr.unix_experience.owncloud_sms.jni.SmsBuffer;
|
|
||||||
import fr.unix_experience.owncloud_sms.prefs.OCSMSSharedPrefs;
|
import fr.unix_experience.owncloud_sms.prefs.OCSMSSharedPrefs;
|
||||||
|
import ncsmsgo.SmsBuffer;
|
||||||
|
import ncsmsgo.SmsPushResponse;
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
public class OCSMSOwnCloudClient {
|
public class OCSMSOwnCloudClient {
|
||||||
@ -56,6 +57,7 @@ public class OCSMSOwnCloudClient {
|
|||||||
_http = new OCHttpClient(context,
|
_http = new OCHttpClient(context,
|
||||||
serverURL, accountManager.getUserData(account, "ocLogin"),
|
serverURL, accountManager.getUserData(account, "ocLogin"),
|
||||||
accountManager.getPassword(account));
|
accountManager.getPassword(account));
|
||||||
|
|
||||||
_connectivityMonitor = new ConnectivityMonitor(_context);
|
_connectivityMonitor = new ConnectivityMonitor(_context);
|
||||||
} catch (MalformedURLException e) {
|
} catch (MalformedURLException e) {
|
||||||
throw new IllegalStateException(context.getString(R.string.err_sync_account_unparsable));
|
throw new IllegalStateException(context.getString(R.string.err_sync_account_unparsable));
|
||||||
@ -63,23 +65,15 @@ public class OCSMSOwnCloudClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Integer getServerAPIVersion() throws OCSyncException {
|
public Integer getServerAPIVersion() throws OCSyncException {
|
||||||
Pair<Integer, JSONObject> response = _http.getVersion();
|
Pair<Integer, Integer> vPair = _http.getVersion();
|
||||||
if (response.second == null) {
|
_serverAPIVersion = vPair.second;
|
||||||
// Return default version
|
if (vPair.first == 200 && _serverAPIVersion > 0) {
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
_serverAPIVersion = response.second.getInt("version");
|
|
||||||
}
|
|
||||||
catch (JSONException e) {
|
|
||||||
Log.e(OCSMSOwnCloudClient.TAG, "No version received from server, assuming version 1", e);
|
|
||||||
_serverAPIVersion = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _serverAPIVersion;
|
return _serverAPIVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
JSONArray getServerPhoneNumbers() throws OCSyncException {
|
JSONArray getServerPhoneNumbers() throws OCSyncException {
|
||||||
Pair<Integer, JSONObject> response = _http.getPhoneList();
|
Pair<Integer, JSONObject> response = _http.getPhoneList();
|
||||||
if (response.second == null) {
|
if (response.second == null) {
|
||||||
@ -111,7 +105,7 @@ public class OCSMSOwnCloudClient {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create new JSONArray to get results
|
// Create new SmsBuffer to get results
|
||||||
smsBuffer = new SmsBuffer();
|
smsBuffer = new SmsBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,28 +114,18 @@ public class OCSMSOwnCloudClient {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Pair<Integer, JSONObject> response = _http.pushSms(smsBuffer.asRawJsonString());
|
Pair<Integer, SmsPushResponse> response = _http.pushSms(smsBuffer);
|
||||||
|
|
||||||
if (response.second == null) {
|
if (response.second == null) {
|
||||||
Log.e(OCSMSOwnCloudClient.TAG,"Request failed. It doesn't return a valid JSON Object");
|
Log.e(OCSMSOwnCloudClient.TAG,"Push request failed. GoLang response is empty.");
|
||||||
throw new OCSyncException(R.string.err_sync_push_request, OCSyncErrorType.IO);
|
throw new OCSyncException(R.string.err_sync_push_request, OCSyncErrorType.IO);
|
||||||
}
|
}
|
||||||
|
|
||||||
Boolean pushStatus;
|
|
||||||
String pushMessage;
|
|
||||||
try {
|
|
||||||
pushStatus = response.second.getBoolean("status");
|
|
||||||
pushMessage = response.second.getString("msg");
|
|
||||||
}
|
|
||||||
catch (JSONException e) {
|
|
||||||
Log.e(OCSMSOwnCloudClient.TAG, "Invalid datas received from server", e);
|
|
||||||
throw new OCSyncException(R.string.err_sync_push_request_resp, OCSyncErrorType.PARSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Push was OK, we can save the lastMessageDate which was saved to server
|
// Push was OK, we can save the lastMessageDate which was saved to server
|
||||||
(new OCSMSSharedPrefs(_context)).setLastMessageDate(smsBuffer.getLastMessageDate());
|
(new OCSMSSharedPrefs(_context)).setLastMessageDate(smsBuffer.getLastMessageDate());
|
||||||
|
|
||||||
Log.i(OCSMSOwnCloudClient.TAG, "SMS Push request said: status " + pushStatus + " - " + pushMessage);
|
Log.i(OCSMSOwnCloudClient.TAG, "SMS Push request said: status " +
|
||||||
|
response.second.getStatus() + " - " + response.second.getMessage());
|
||||||
Log.i(OCSMSOwnCloudClient.TAG, "LastMessageDate set to: " + smsBuffer.getLastMessageDate());
|
Log.i(OCSMSOwnCloudClient.TAG, "LastMessageDate set to: " + smsBuffer.getLastMessageDate());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,69 +0,0 @@
|
|||||||
package fr.unix_experience.owncloud_sms.jni;
|
|
||||||
|
|
||||||
import fr.unix_experience.owncloud_sms.engine.SmsEntry;
|
|
||||||
import fr.unix_experience.owncloud_sms.enums.MailboxID;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copyright (c) 2014-2017, Loic Blot <loic.blot@unix-experience.fr>
|
|
||||||
*
|
|
||||||
* 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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class SmsBuffer {
|
|
||||||
static {
|
|
||||||
System.loadLibrary("nativesms");
|
|
||||||
}
|
|
||||||
|
|
||||||
private long mHandle;
|
|
||||||
|
|
||||||
String TAG = SmsBuffer.class.getSimpleName();
|
|
||||||
|
|
||||||
public SmsBuffer() {
|
|
||||||
mHandle = SmsBuffer.createNativeObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void finalize() throws Throwable {
|
|
||||||
clear();
|
|
||||||
super.finalize();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static native long createNativeObject();
|
|
||||||
private native void deleteNativeObject();
|
|
||||||
public native void push(int id, int mbid, int type, long date, String address,
|
|
||||||
String body, String read, String seen);
|
|
||||||
public native boolean empty();
|
|
||||||
public native void print();
|
|
||||||
public native String asRawJsonString();
|
|
||||||
public native long getLastMessageDate();
|
|
||||||
|
|
||||||
public void push(MailboxID mbid, SmsEntry smsEntry) {
|
|
||||||
push(smsEntry.id,
|
|
||||||
mbid.ordinal(),
|
|
||||||
smsEntry.type,
|
|
||||||
smsEntry.date,
|
|
||||||
smsEntry.address,
|
|
||||||
smsEntry.body,
|
|
||||||
smsEntry.read ? "true" : "false",
|
|
||||||
smsEntry.seen ? "true" : "false");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clear() {
|
|
||||||
if (mHandle == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
deleteNativeObject();
|
|
||||||
mHandle = 0;
|
|
||||||
}
|
|
||||||
}
|
|
@ -32,8 +32,8 @@ import fr.unix_experience.owncloud_sms.engine.ConnectivityMonitor;
|
|||||||
import fr.unix_experience.owncloud_sms.engine.OCSMSOwnCloudClient;
|
import fr.unix_experience.owncloud_sms.engine.OCSMSOwnCloudClient;
|
||||||
import fr.unix_experience.owncloud_sms.enums.MailboxID;
|
import fr.unix_experience.owncloud_sms.enums.MailboxID;
|
||||||
import fr.unix_experience.owncloud_sms.enums.PermissionID;
|
import fr.unix_experience.owncloud_sms.enums.PermissionID;
|
||||||
import fr.unix_experience.owncloud_sms.jni.SmsBuffer;
|
|
||||||
import fr.unix_experience.owncloud_sms.prefs.PermissionChecker;
|
import fr.unix_experience.owncloud_sms.prefs.PermissionChecker;
|
||||||
|
import ncsmsgo.SmsBuffer;
|
||||||
|
|
||||||
public class SmsObserver extends ContentObserver implements ASyncSMSSync {
|
public class SmsObserver extends ContentObserver implements ASyncSMSSync {
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user