mirror of
https://github.com/ArcaneChat/android.git
synced 2026-07-03 14:05:24 +02:00
+1
-1
@@ -90,7 +90,7 @@ android {
|
||||
|
||||
defaultConfig {
|
||||
versionCode 582
|
||||
versionName "1.8.1"
|
||||
versionName "1.9.2"
|
||||
|
||||
applicationId "com.b44t.messenger"
|
||||
multiDexEnabled true
|
||||
|
||||
+100
-154
@@ -173,14 +173,6 @@ static uint32_t* jintArray2uint32Pointer(JNIEnv* env, jintArray ja, int* ret_icn
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
typedef struct dc_jnicontext_t {
|
||||
JavaVM* jvm; // JNIEnv cannot be shared between threads, so we share the JavaVM object
|
||||
jclass cls;
|
||||
jobject obj;
|
||||
jmethodID methodId;
|
||||
} dc_jnicontext_t;
|
||||
|
||||
|
||||
static dc_context_t* get_dc_context(JNIEnv *env, jobject obj)
|
||||
{
|
||||
static jfieldID fid = 0;
|
||||
@@ -195,48 +187,18 @@ static dc_context_t* get_dc_context(JNIEnv *env, jobject obj)
|
||||
}
|
||||
|
||||
|
||||
static uintptr_t s_context_callback_(dc_context_t* context, int event, uintptr_t data1, uintptr_t data2)
|
||||
JNIEXPORT jlong Java_com_b44t_messenger_DcContext_createContextCPtr(JNIEnv *env, jobject obj, jstring osname, jstring dbfile)
|
||||
{
|
||||
jlong l;
|
||||
JNIEnv* env;
|
||||
dc_jnicontext_t* jnicontext = dc_get_userdata(context);
|
||||
|
||||
if (jnicontext==NULL || jnicontext->jvm==NULL || jnicontext->cls==NULL || jnicontext->obj==NULL || jnicontext->methodId==NULL) {
|
||||
return 0; /* may happen on startup */
|
||||
}
|
||||
|
||||
(*jnicontext->jvm)->GetEnv(jnicontext->jvm, (void**)&env, JNI_VERSION_1_6); // as this function may be called from _any_ thread, we cannot use a static pointer to JNIEnv
|
||||
if (env==NULL) {
|
||||
return 0; /* may happen on startup */
|
||||
}
|
||||
|
||||
l = (*env)->CallLongMethod(env, jnicontext->obj, jnicontext->methodId, (jint)event, (jlong)data1, (jlong)data2);
|
||||
return (uintptr_t)l;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jlong Java_com_b44t_messenger_DcContext_createContextCPtr(JNIEnv *env, jobject obj, jstring osname)
|
||||
{
|
||||
jclass cls = (*env)->GetObjectClass(env, obj);
|
||||
|
||||
dc_jnicontext_t* jnicontext = calloc(1, sizeof(dc_jnicontext_t));
|
||||
if (cls==NULL || jnicontext==NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
(*env)->GetJavaVM(env, &jnicontext->jvm);
|
||||
jnicontext->cls = (*env)->NewGlobalRef(env, cls);
|
||||
jnicontext->obj = (*env)->NewGlobalRef(env, obj);
|
||||
jnicontext->methodId = (*env)->GetMethodID(env, jnicontext->cls, "handleEvent","(IJJ)J" /*signature as "(param)ret" with I=int, J=long*/);
|
||||
|
||||
CHAR_REF(osname);
|
||||
jlong contextCPtr = (jlong)dc_context_new(s_context_callback_, jnicontext, osnamePtr);
|
||||
CHAR_REF(dbfile)
|
||||
jlong contextCPtr = (jlong)dc_context_new(osnamePtr, dbfilePtr, NULL);
|
||||
CHAR_UNREF(dbfile)
|
||||
CHAR_UNREF(osname);
|
||||
return contextCPtr;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_DcContact_unrefContextCPtr(JNIEnv *env, jobject obj)
|
||||
JNIEXPORT void Java_com_b44t_messenger_DcContext_unrefContextCPtr(JNIEnv *env, jobject obj)
|
||||
{
|
||||
dc_context_unref(get_dc_context(env, obj));
|
||||
}
|
||||
@@ -244,21 +206,6 @@ JNIEXPORT void Java_com_b44t_messenger_DcContact_unrefContextCPtr(JNIEnv *env, j
|
||||
|
||||
/* DcContext - open/configure/connect/fetch */
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_DcContext_open(JNIEnv *env, jobject obj, jstring dbfile)
|
||||
{
|
||||
CHAR_REF(dbfile);
|
||||
jint ret = dc_open(get_dc_context(env, obj), dbfilePtr, NULL);
|
||||
CHAR_UNREF(dbfile)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_DcContext_close(JNIEnv *env, jobject obj)
|
||||
{
|
||||
dc_close(get_dc_context(env, obj));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_DcContext_setStockTranslation(JNIEnv *env, jobject obj, jint stock_id, jstring translation)
|
||||
{
|
||||
CHAR_REF(translation);
|
||||
@@ -303,93 +250,21 @@ JNIEXPORT jint Java_com_b44t_messenger_DcContext_isConfigured(JNIEnv *env, jobje
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_DcContext_performImapJobs(JNIEnv *env, jobject obj)
|
||||
JNIEXPORT void Java_com_b44t_messenger_DcContext_startIo(JNIEnv *env, jobject obj)
|
||||
{
|
||||
dc_perform_imap_jobs(get_dc_context(env, obj));
|
||||
dc_start_io(get_dc_context(env, obj));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_DcContext_performImapIdle(JNIEnv *env, jobject obj)
|
||||
JNIEXPORT void Java_com_b44t_messenger_DcContext_stopIo(JNIEnv *env, jobject obj)
|
||||
{
|
||||
dc_perform_imap_idle(get_dc_context(env, obj));
|
||||
dc_stop_io(get_dc_context(env, obj));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_DcContext_performImapFetch(JNIEnv *env, jobject obj)
|
||||
JNIEXPORT jboolean Java_com_b44t_messenger_DcContext_isIoRunning(JNIEnv *env, jobject obj)
|
||||
{
|
||||
dc_perform_imap_fetch(get_dc_context(env, obj));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_DcContext_interruptImapIdle(JNIEnv *env, jobject obj)
|
||||
{
|
||||
dc_interrupt_imap_idle(get_dc_context(env, obj));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_DcContext_performSentboxJobs(JNIEnv *env, jobject obj)
|
||||
{
|
||||
dc_perform_sentbox_jobs(get_dc_context(env, obj));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_DcContext_performSentboxFetch(JNIEnv *env, jobject obj)
|
||||
{
|
||||
dc_perform_sentbox_fetch(get_dc_context(env, obj));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_DcContext_performSentboxIdle(JNIEnv *env, jobject obj)
|
||||
{
|
||||
dc_perform_sentbox_idle(get_dc_context(env, obj));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_DcContext_interruptSentboxIdle(JNIEnv *env, jobject obj)
|
||||
{
|
||||
dc_interrupt_sentbox_idle(get_dc_context(env, obj));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_DcContext_performMvboxJobs(JNIEnv *env, jobject obj)
|
||||
{
|
||||
dc_perform_mvbox_jobs(get_dc_context(env, obj));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_DcContext_performMvboxFetch(JNIEnv *env, jobject obj)
|
||||
{
|
||||
dc_perform_mvbox_fetch(get_dc_context(env, obj));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_DcContext_performMvboxIdle(JNIEnv *env, jobject obj)
|
||||
{
|
||||
dc_perform_mvbox_idle(get_dc_context(env, obj));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_DcContext_interruptMvboxIdle(JNIEnv *env, jobject obj)
|
||||
{
|
||||
dc_interrupt_mvbox_idle(get_dc_context(env, obj));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_DcContext_performSmtpJobs(JNIEnv *env, jobject obj)
|
||||
{
|
||||
dc_perform_smtp_jobs(get_dc_context(env, obj));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_DcContext_performSmtpIdle(JNIEnv *env, jobject obj)
|
||||
{
|
||||
dc_perform_smtp_idle(get_dc_context(env, obj));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_DcContext_interruptSmtpIdle(JNIEnv *env, jobject obj)
|
||||
{
|
||||
dc_interrupt_smtp_idle(get_dc_context(env, obj));
|
||||
return dc_is_io_running(get_dc_context(env, obj)) != 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -398,6 +273,11 @@ JNIEXPORT void Java_com_b44t_messenger_DcContext_maybeNetwork(JNIEnv *env, jobje
|
||||
dc_maybe_network(get_dc_context(env, obj));
|
||||
}
|
||||
|
||||
JNIEXPORT jlong Java_com_b44t_messenger_DcContext_getEventEmitterCPtr(JNIEnv *env, jobject obj)
|
||||
{
|
||||
return (jlong)dc_get_event_emitter(get_dc_context(env, obj));
|
||||
}
|
||||
|
||||
|
||||
/* DcContext - handle contacts */
|
||||
|
||||
@@ -890,6 +770,89 @@ JNIEXPORT jlong Java_com_b44t_messenger_DcContext_getProviderFromEmailCPtr(JNIEn
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* DcEventEmitter
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
static dc_event_emitter_t* get_dc_event_emitter(JNIEnv *env, jobject obj)
|
||||
{
|
||||
static jfieldID fid = 0;
|
||||
if (fid==0) {
|
||||
jclass cls = (*env)->GetObjectClass(env, obj);
|
||||
fid = (*env)->GetFieldID(env, cls, "eventEmitterCPtr", "J" /*Signature, J=long*/);
|
||||
}
|
||||
if (fid) {
|
||||
return (dc_event_emitter_t*)(*env)->GetLongField(env, obj, fid);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_DcEventEmitter_unrefEventEmitterCPtr(JNIEnv *env, jobject obj)
|
||||
{
|
||||
dc_event_emitter_unref(get_dc_event_emitter(env, obj));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jlong Java_com_b44t_messenger_DcEventEmitter_getNextEventCPtr(JNIEnv *env, jobject obj)
|
||||
{
|
||||
return (jlong)dc_get_next_event(get_dc_event_emitter(env, obj));
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* DcEvent
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
static dc_event_t* get_dc_event(JNIEnv *env, jobject obj)
|
||||
{
|
||||
static jfieldID fid = 0;
|
||||
if (fid==0) {
|
||||
jclass cls = (*env)->GetObjectClass(env, obj);
|
||||
fid = (*env)->GetFieldID(env, cls, "eventCPtr", "J" /*Signature, J=long*/);
|
||||
}
|
||||
if (fid) {
|
||||
return (dc_event_t*)(*env)->GetLongField(env, obj, fid);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_DcEvent_unrefEventCPtr(JNIEnv *env, jobject obj)
|
||||
{
|
||||
dc_event_unref(get_dc_event(env, obj));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_DcEvent_getId(JNIEnv *env, jobject obj)
|
||||
{
|
||||
return dc_event_get_id(get_dc_event(env, obj));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_DcEvent_getData1Int(JNIEnv *env, jobject obj)
|
||||
{
|
||||
return dc_event_get_data1_int(get_dc_event(env, obj));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_DcEvent_getData2Int(JNIEnv *env, jobject obj)
|
||||
{
|
||||
return dc_event_get_data2_int(get_dc_event(env, obj));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jstring Java_com_b44t_messenger_DcEvent_getData2Str(JNIEnv *env, jobject obj)
|
||||
{
|
||||
char* temp = dc_event_get_data2_str(get_dc_event(env, obj));
|
||||
jstring ret = JSTRING_NEW(temp);
|
||||
dc_str_unref(temp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* DcArray
|
||||
******************************************************************************/
|
||||
@@ -1653,29 +1616,12 @@ JNIEXPORT jstring Java_com_b44t_messenger_DcProvider_getOverviewPage(JNIEnv *env
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Tools
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
JNIEXPORT jboolean Java_com_b44t_messenger_DcContext_data1IsString(JNIEnv *env, jclass cls, jint event)
|
||||
{
|
||||
return DC_EVENT_DATA1_IS_STRING(event);
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jboolean Java_com_b44t_messenger_DcContext_data2IsString(JNIEnv *env, jclass cls, jint event)
|
||||
{
|
||||
return DC_EVENT_DATA2_IS_STRING(event);
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jstring Java_com_b44t_messenger_DcContext_dataToString(JNIEnv *env, jclass cls, jlong data)
|
||||
{
|
||||
/* the callback may return a long that represents a pointer to a C-String; this function creates a Java-string from such values. */
|
||||
if (data==0) {
|
||||
return NULL;
|
||||
}
|
||||
const char* cstring = (const char*)data;
|
||||
return JSTRING_NEW(cstring);
|
||||
}
|
||||
@@ -72,44 +72,37 @@ public class DcContext {
|
||||
public final static int DC_EMPTY_MVBOX = 0x01;
|
||||
public final static int DC_EMPTY_INBOX = 0x02;
|
||||
|
||||
public DcContext(String osName) {
|
||||
handleEvent(0,0,0); // call handleEvent() to make sure it is not optimized away and JNI won't find it
|
||||
contextCPtr = createContextCPtr(osName);
|
||||
public DcContext(String osName, String dbfile) {
|
||||
contextCPtr = createContextCPtr(osName, dbfile);
|
||||
}
|
||||
|
||||
public boolean isOk() {
|
||||
return contextCPtr != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
super.finalize();
|
||||
unrefContextCPtr();
|
||||
contextCPtr = 0;
|
||||
unref();
|
||||
}
|
||||
|
||||
public native int open (String dbfile);
|
||||
public native void close ();
|
||||
public void unref() {
|
||||
if (contextCPtr != 0) {
|
||||
unrefContextCPtr();
|
||||
contextCPtr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public DcEventEmitter getEventEmitter () { return new DcEventEmitter(getEventEmitterCPtr()); }
|
||||
public native void setStockTranslation (int stockId, String translation);
|
||||
public native String getBlobdir ();
|
||||
public native void configure ();
|
||||
public native void stopOngoingProcess ();
|
||||
public native int isConfigured ();
|
||||
|
||||
public native void performImapJobs ();
|
||||
public native void performImapFetch ();
|
||||
public native void performImapIdle ();
|
||||
public native void interruptImapIdle ();
|
||||
|
||||
public native void performMvboxJobs ();
|
||||
public native void performMvboxFetch ();
|
||||
public native void performMvboxIdle ();
|
||||
public native void interruptMvboxIdle ();
|
||||
|
||||
public native void performSentboxJobs ();
|
||||
public native void performSentboxFetch ();
|
||||
public native void performSentboxIdle ();
|
||||
public native void interruptSentboxIdle ();
|
||||
|
||||
public native void performSmtpJobs ();
|
||||
public native void performSmtpIdle ();
|
||||
public native void interruptSmtpIdle ();
|
||||
public native void startIo ();
|
||||
public native void stopIo ();
|
||||
public native boolean isIoRunning ();
|
||||
|
||||
public native void maybeNetwork ();
|
||||
public native void setConfig (String key, String value);
|
||||
@@ -189,20 +182,14 @@ public class DcContext {
|
||||
*/
|
||||
public native boolean setLocation (float latitude, float longitude, float accuracy);
|
||||
|
||||
// event handling - you should @Override this function in derived classes
|
||||
public long handleEvent(int event, long data1, long data2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// helper to get/return strings from/to handleEvent()
|
||||
public native static boolean data1IsString(int event);
|
||||
public native static boolean data2IsString(int event);
|
||||
public native static String dataToString (long data);
|
||||
|
||||
// working with raw c-data
|
||||
private long contextCPtr; // CAVE: the name is referenced in the JNI
|
||||
private native long createContextCPtr(String osName);
|
||||
private native long createContextCPtr(String osName, String dbfile);
|
||||
private native void unrefContextCPtr ();
|
||||
private native long getEventEmitterCPtr();
|
||||
public native long createMsgCPtr (int viewtype);
|
||||
private native long getChatlistCPtr (int listflags, String query, int queryId);
|
||||
private native long getChatCPtr (int chat_id);
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.b44t.messenger;
|
||||
|
||||
public class DcEvent {
|
||||
|
||||
public DcEvent(long eventCPtr) {
|
||||
this.eventCPtr = eventCPtr;
|
||||
}
|
||||
|
||||
@Override protected void finalize() throws Throwable {
|
||||
super.finalize();
|
||||
unrefEventCPtr();
|
||||
eventCPtr = 0;
|
||||
}
|
||||
|
||||
public native int getId ();
|
||||
public native int getData1Int ();
|
||||
public native int getData2Int ();
|
||||
public native String getData2Str ();
|
||||
|
||||
// working with raw c-data
|
||||
private long eventCPtr; // CAVE: the name is referenced in the JNI
|
||||
private native void unrefEventCPtr();
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.b44t.messenger;
|
||||
|
||||
public class DcEventEmitter {
|
||||
|
||||
public DcEventEmitter(long eventEmitterCPtr) {
|
||||
this.eventEmitterCPtr = eventEmitterCPtr;
|
||||
}
|
||||
|
||||
@Override protected void finalize() throws Throwable {
|
||||
super.finalize();
|
||||
unrefEventEmitterCPtr();
|
||||
eventEmitterCPtr = 0;
|
||||
}
|
||||
|
||||
public DcEvent getNextEvent () {
|
||||
long eventCPtr = getNextEventCPtr();
|
||||
return eventCPtr == 0 ? null : new DcEvent(eventCPtr);
|
||||
}
|
||||
|
||||
// working with raw c-data
|
||||
private long eventEmitterCPtr; // CAVE: the name is referenced in the JNI
|
||||
private native long getNextEventCPtr ();
|
||||
private native void unrefEventEmitterCPtr();
|
||||
}
|
||||
@@ -511,8 +511,10 @@ public class RegistrationActivity extends BaseActionBarActivity implements DcEve
|
||||
|
||||
// calling configure() results in
|
||||
// receiving multiple DC_EVENT_CONFIGURE_PROGRESS events
|
||||
DcHelper.getContext(this).captureNextError();
|
||||
DcHelper.getContext(this).configure();
|
||||
ApplicationDcContext dcContext = DcHelper.getContext(this);
|
||||
dcContext.stopIo();
|
||||
dcContext.captureNextError();
|
||||
dcContext.configure();
|
||||
}
|
||||
|
||||
private void setConfig(@IdRes int viewId, String configTarget, boolean doTrim) {
|
||||
@@ -534,6 +536,7 @@ public class RegistrationActivity extends BaseActionBarActivity implements DcEve
|
||||
ApplicationDcContext dcContext = DcHelper.getContext(this);
|
||||
long progress = (Long)data1;
|
||||
if (progress==0/*error/aborted*/) {
|
||||
dcContext.maybeStartIo(); // start-io is also needed on errors to make previous config work in case of changes
|
||||
dcContext.endCaptureNextError();
|
||||
progressDialog.dismiss();
|
||||
if (dcContext.hasCapturedError()) {
|
||||
@@ -555,6 +558,7 @@ public class RegistrationActivity extends BaseActionBarActivity implements DcEve
|
||||
progressDialog.setMessage(getResources().getString(R.string.one_moment)+String.format(" %d%%", percent));
|
||||
}
|
||||
else if (progress==1000/*done*/) {
|
||||
dcContext.maybeStartIo();
|
||||
dcContext.endCaptureNextError();
|
||||
progressDialog.dismiss();
|
||||
Intent conversationList = new Intent(getApplicationContext(), ConversationListActivity.class);
|
||||
|
||||
@@ -147,6 +147,7 @@ public class WelcomeActivity extends BaseActionBarActivity implements DcEventCen
|
||||
|
||||
// calling configure() results in
|
||||
// receiving multiple DC_EVENT_CONFIGURE_PROGRESS events
|
||||
dcContext.stopIo();
|
||||
dcContext.configure();
|
||||
}
|
||||
|
||||
@@ -192,12 +193,14 @@ public class WelcomeActivity extends BaseActionBarActivity implements DcEventCen
|
||||
progressUpdate((int)progress);
|
||||
}
|
||||
else if (progress==1000/*done*/) {
|
||||
dcContext.maybeStartIo();
|
||||
progressSuccess(false);
|
||||
}
|
||||
}
|
||||
else if (manualConfigure && eventId==DcContext.DC_EVENT_CONFIGURE_PROGRESS) {
|
||||
long progress = (Long)data1;
|
||||
if (progress==1000/*done*/) {
|
||||
dcContext.maybeStartIo();
|
||||
finish(); // remove ourself from the activity stack (finishAffinity is available in API 16, we're targeting API 14)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,8 +65,8 @@ public class AccountManager {
|
||||
private @Nullable Account maybeGetAccount(File file) {
|
||||
try {
|
||||
if (!file.isDirectory() && file.getName().endsWith(".db")) {
|
||||
DcContext testContext = new DcContext(null);
|
||||
if (testContext.open(file.getAbsolutePath()) != 0) {
|
||||
DcContext testContext = new DcContext(null, file.getAbsolutePath());
|
||||
if (testContext.isOk()) {
|
||||
Account ret = new Account();
|
||||
ret.dbName = file.getName();
|
||||
ret.displayname = testContext.getConfig("displayname");
|
||||
@@ -98,8 +98,9 @@ public class AccountManager {
|
||||
// create an empty DcContext object - this will be set up then, starting with
|
||||
// getSelectedAccount()
|
||||
ApplicationContext appContext = (ApplicationContext)context.getApplicationContext();
|
||||
appContext.dcContext.stopThreads();
|
||||
appContext.dcContext.close();
|
||||
appContext.dcContext.notificationCenter.removeAllNotifiations();
|
||||
appContext.dcContext.stopIo();
|
||||
appContext.dcContext.unref();
|
||||
appContext.dcContext = new ApplicationDcContext(context);
|
||||
}
|
||||
|
||||
@@ -243,10 +244,10 @@ public class AccountManager {
|
||||
if (deleteDbName!=null) {
|
||||
// used to delete the previous account, however, as a resilience check, make sure,
|
||||
// we do not delete already configured accounts (just in case sth. changes the flow of activities)
|
||||
DcContext testContext = new DcContext(null);
|
||||
if (testContext.open(new File(activity.getFilesDir(), deleteDbName).getAbsolutePath()) != 0) {
|
||||
DcContext testContext = new DcContext(null, new File(activity.getFilesDir(), deleteDbName).getAbsolutePath());
|
||||
if (testContext.isOk()) {
|
||||
if (testContext.isConfigured() == 0) {
|
||||
testContext.close();
|
||||
testContext.unref();
|
||||
AccountManager.getInstance().deleteAccount(activity, deleteDbName);
|
||||
PreferenceManager.getDefaultSharedPreferences(activity)
|
||||
.edit().putString("prev_account_db_name", "").apply();
|
||||
|
||||
@@ -9,7 +9,6 @@ import android.net.NetworkInfo;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Environment;
|
||||
import android.os.PowerManager;
|
||||
import androidx.annotation.IntDef;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.content.FileProvider;
|
||||
@@ -20,10 +19,11 @@ import android.webkit.MimeTypeMap;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.b44t.messenger.DcChat;
|
||||
import com.b44t.messenger.DcChatlist;
|
||||
import com.b44t.messenger.DcContact;
|
||||
import com.b44t.messenger.DcContext;
|
||||
import com.b44t.messenger.DcEvent;
|
||||
import com.b44t.messenger.DcEventCenter;
|
||||
import com.b44t.messenger.DcEventEmitter;
|
||||
import com.b44t.messenger.DcLot;
|
||||
import com.b44t.messenger.DcMsg;
|
||||
|
||||
@@ -38,7 +38,6 @@ import org.thoughtcrime.securesms.util.Util;
|
||||
import java.io.File;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class ApplicationDcContext extends DcContext {
|
||||
@@ -56,12 +55,9 @@ public class ApplicationDcContext extends DcContext {
|
||||
public NotificationCenter notificationCenter;
|
||||
|
||||
public ApplicationDcContext(Context context) {
|
||||
super("Android "+BuildConfig.VERSION_NAME);
|
||||
super("Android "+BuildConfig.VERSION_NAME, AccountManager.getInstance().getSelectedAccount(context).getAbsolutePath());
|
||||
this.context = context;
|
||||
|
||||
File dbfile = AccountManager.getInstance().getSelectedAccount(context);
|
||||
open(dbfile.getAbsolutePath());
|
||||
|
||||
// migration, can be removed after some versions (added 5/2020)
|
||||
// (this will convert only for one account, but that is fine, multi-account is experimental anyway)
|
||||
try {
|
||||
@@ -103,27 +99,26 @@ public class ApplicationDcContext extends DcContext {
|
||||
}
|
||||
// /migration
|
||||
|
||||
try {
|
||||
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
|
||||
|
||||
imapWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "imapWakeLock");
|
||||
imapWakeLock.setReferenceCounted(false); // if the idle-thread is killed for any reasons, it is better not to rely on reference counting
|
||||
|
||||
mvboxWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "mvboxWakeLock");
|
||||
mvboxWakeLock.setReferenceCounted(false); // if the idle-thread is killed for any reasons, it is better not to rely on reference counting
|
||||
|
||||
sentboxWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "sentboxWakeLock");
|
||||
sentboxWakeLock.setReferenceCounted(false); // if the idle-thread is killed for any reasons, it is better not to rely on reference counting
|
||||
|
||||
smtpWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "smtpWakeLock");
|
||||
smtpWakeLock.setReferenceCounted(false); // if the idle-thread is killed for any reasons, it is better not to rely on reference counting
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Cannot create wakeLocks");
|
||||
}
|
||||
new Thread(() -> {
|
||||
DcEventEmitter emitter = getEventEmitter();
|
||||
while (true) {
|
||||
DcEvent event = emitter.getNextEvent();
|
||||
if (event==null) {
|
||||
break;
|
||||
}
|
||||
handleEvent(event);
|
||||
}
|
||||
Log.i(TAG, "shutting down event handler");
|
||||
}, "eventThread").start();
|
||||
|
||||
notificationCenter = new NotificationCenter(this);
|
||||
startThreads(0);
|
||||
maybeStartIo();
|
||||
}
|
||||
|
||||
public void maybeStartIo() {
|
||||
if (isConfigured()!=0) {
|
||||
startIo();
|
||||
}
|
||||
}
|
||||
|
||||
public void setStockTranslations() {
|
||||
@@ -313,166 +308,6 @@ public class ApplicationDcContext extends DcContext {
|
||||
chat.getVisibility(), verified, chat.isSendingLocations(), chat.isMuted(), summary);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* Working Threads
|
||||
**********************************************************************************************/
|
||||
|
||||
private final Object threadsCritical = new Object();
|
||||
private final Object incLoopsCritical= new Object();
|
||||
|
||||
public Thread imapThread = null;
|
||||
private PowerManager.WakeLock imapWakeLock = null;
|
||||
private int inboxLoops = 0;
|
||||
|
||||
public Thread mvboxThread = null;
|
||||
private PowerManager.WakeLock mvboxWakeLock = null;
|
||||
private int mvboxLoops = 0;
|
||||
|
||||
public Thread sentboxThread = null;
|
||||
private PowerManager.WakeLock sentboxWakeLock = null;
|
||||
|
||||
public Thread smtpThread = null;
|
||||
private PowerManager.WakeLock smtpWakeLock = null;
|
||||
private int smtpLoops = 0;
|
||||
|
||||
public final static int INTERRUPT_IDLE = 0x01; // interrupt idle if the thread is already running
|
||||
|
||||
public boolean run = true;
|
||||
|
||||
public void startThreads(int flags) {
|
||||
synchronized (threadsCritical) {
|
||||
|
||||
if (imapThread == null || !imapThread.isAlive()) {
|
||||
|
||||
imapThread = new Thread(() -> {
|
||||
Log.i(TAG, "###################### IMAP-Thread started. ######################");
|
||||
while (run) {
|
||||
imapWakeLock.acquire();
|
||||
performImapJobs();
|
||||
performImapFetch();
|
||||
imapWakeLock.release();
|
||||
synchronized (incLoopsCritical) {
|
||||
inboxLoops++;
|
||||
}
|
||||
performImapIdle();
|
||||
}
|
||||
Log.i(TAG, "!!!!!!!!!!!! IMAP-Thread stopped");
|
||||
}, "imapThread");
|
||||
imapThread.setPriority(Thread.NORM_PRIORITY);
|
||||
imapThread.start();
|
||||
} else {
|
||||
if ((flags & INTERRUPT_IDLE) != 0) {
|
||||
interruptImapIdle();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (mvboxThread == null || !mvboxThread.isAlive()) {
|
||||
|
||||
mvboxThread = new Thread(() -> {
|
||||
Log.i(TAG, "###################### MVBOX-Thread started. ######################");
|
||||
while (run) {
|
||||
mvboxWakeLock.acquire();
|
||||
performMvboxJobs();
|
||||
performMvboxFetch();
|
||||
mvboxWakeLock.release();
|
||||
synchronized (incLoopsCritical) {
|
||||
mvboxLoops++;
|
||||
}
|
||||
performMvboxIdle();
|
||||
}
|
||||
Log.i(TAG, "!!!!!!!!!!!! MVBOX-Thread stopped");
|
||||
}, "mvboxThread");
|
||||
mvboxThread.setPriority(Thread.NORM_PRIORITY);
|
||||
mvboxThread.start();
|
||||
} else {
|
||||
if ((flags & INTERRUPT_IDLE) != 0) {
|
||||
interruptMvboxIdle();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (sentboxThread == null || !sentboxThread.isAlive()) {
|
||||
|
||||
sentboxThread = new Thread(() -> {
|
||||
Log.i(TAG, "###################### SENTBOX-Thread started. ######################");
|
||||
while (run) {
|
||||
sentboxWakeLock.acquire();
|
||||
performSentboxJobs();
|
||||
performSentboxFetch();
|
||||
sentboxWakeLock.release();
|
||||
performSentboxIdle();
|
||||
}
|
||||
Log.i(TAG, "!!!!!!!!!!!! SENTBOX-Thread stopped");
|
||||
}, "sentboxThread");
|
||||
sentboxThread.setPriority(Thread.NORM_PRIORITY-1);
|
||||
sentboxThread.start();
|
||||
} else {
|
||||
if ((flags & INTERRUPT_IDLE) != 0) {
|
||||
interruptSentboxIdle();
|
||||
}
|
||||
}
|
||||
|
||||
if (smtpThread == null || !smtpThread.isAlive()) {
|
||||
smtpThread = new Thread(() -> {
|
||||
Log.i(TAG, "###################### SMTP-Thread started. ######################");
|
||||
while (run) {
|
||||
smtpWakeLock.acquire();
|
||||
performSmtpJobs();
|
||||
smtpWakeLock.release();
|
||||
synchronized (incLoopsCritical) {
|
||||
smtpLoops++;
|
||||
}
|
||||
performSmtpIdle();
|
||||
}
|
||||
Log.i(TAG, "!!!!!!!!!!!! SMTP-Thread stopped");
|
||||
}, "smtpThread");
|
||||
smtpThread.setPriority(Thread.MAX_PRIORITY);
|
||||
smtpThread.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void waitForThreadsExecutedOnce() {
|
||||
while(true) {
|
||||
synchronized (incLoopsCritical) {
|
||||
if(inboxLoops>0 && mvboxLoops>0 && smtpLoops>0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Util.sleep(500);
|
||||
}
|
||||
}
|
||||
|
||||
public void stopThreads() {
|
||||
notificationCenter.removeAllNotifiations();
|
||||
run = false;
|
||||
synchronized (threadsCritical) {
|
||||
while (true) {
|
||||
|
||||
// in theory, interrupting once outside the loop should be sufficient,
|
||||
// but there are some corner cases, see https://github.com/deltachat/deltachat-core-rust/issues/925
|
||||
Log.i(TAG, "!!!!!!!!!!!! Stopping threads ...");
|
||||
if (imapThread!=null && imapThread.isAlive()) { interruptImapIdle(); }
|
||||
if (mvboxThread!=null && mvboxThread.isAlive()) { interruptMvboxIdle(); }
|
||||
if (sentboxThread!=null && sentboxThread.isAlive()) { interruptSentboxIdle(); }
|
||||
if (smtpThread!=null && smtpThread.isAlive()) { interruptSmtpIdle(); }
|
||||
|
||||
Util.sleep(300);
|
||||
|
||||
if ( (imapThread==null || !imapThread.isAlive())
|
||||
&& (mvboxThread==null || !mvboxThread.isAlive())
|
||||
&& (sentboxThread==null || !sentboxThread.isAlive())
|
||||
&& (smtpThread==null || !smtpThread.isAlive())) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Log.i(TAG, "!!!!!!!!!!!! threads stopped");
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* Tools
|
||||
**********************************************************************************************/
|
||||
@@ -557,41 +392,41 @@ public class ApplicationDcContext extends DcContext {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public long handleEvent(final int event, long data1, long data2) {
|
||||
switch (event) {
|
||||
public long handleEvent(DcEvent event) {
|
||||
int id = event.getId();
|
||||
switch (id) {
|
||||
case DC_EVENT_INFO:
|
||||
Log.i(TAG, dataToString(data2));
|
||||
Log.i(TAG, event.getData2Str());
|
||||
break;
|
||||
|
||||
case DC_EVENT_WARNING:
|
||||
Log.w(TAG, dataToString(data2));
|
||||
Log.w(TAG, event.getData2Str());
|
||||
break;
|
||||
|
||||
case DC_EVENT_ERROR:
|
||||
handleError(event, true, dataToString(data2));
|
||||
handleError(id, true, event.getData2Str());
|
||||
break;
|
||||
|
||||
case DC_EVENT_ERROR_NETWORK:
|
||||
handleError(event, data1 != 0, dataToString(data2));
|
||||
handleError(id, event.getData1Int() != 0, event.getData2Str());
|
||||
break;
|
||||
|
||||
case DC_EVENT_ERROR_SELF_NOT_IN_GROUP:
|
||||
handleError(event, true, dataToString(data2));
|
||||
handleError(id, true, event.getData2Str());
|
||||
break;
|
||||
|
||||
case DC_EVENT_INCOMING_MSG:
|
||||
notificationCenter.addNotification((int) data1, (int) data2);
|
||||
notificationCenter.addNotification(event.getData1Int(), event.getData2Int());
|
||||
if (eventCenter != null) {
|
||||
eventCenter.sendToObservers(event, data1, data2); // Other parts of the code are also interested in this event
|
||||
eventCenter.sendToObservers(id, (long)event.getData1Int(), (long)event.getData2Int());
|
||||
}
|
||||
break;
|
||||
|
||||
default: {
|
||||
final Object data1obj = data1IsString(event) ? dataToString(data1) : data1;
|
||||
final Object data2obj = data2IsString(event) ? dataToString(data2) : data2;
|
||||
final Object data1obj = (long)event.getData1Int();
|
||||
final Object data2obj = data2IsString(id) ? event.getData2Str() : (long)event.getData2Int();
|
||||
if (eventCenter != null) {
|
||||
eventCenter.sendToObservers(event, data1obj, data2obj);
|
||||
eventCenter.sendToObservers(id, data1obj, data2obj);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -7,6 +7,8 @@ import androidx.annotation.NonNull;
|
||||
import androidx.work.Worker;
|
||||
import androidx.work.WorkerParameters;
|
||||
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
|
||||
public class FetchWorker extends Worker {
|
||||
private @NonNull Context context;
|
||||
|
||||
@@ -17,19 +19,24 @@ public class FetchWorker extends Worker {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
// doWork() is called in a background thread;
|
||||
// once we return, Worker is considered to have finished and will be destroyed,
|
||||
// this does not necessarily mean, that the app is killed, we may or may not keep running,
|
||||
// therefore we do not stopIo() here.
|
||||
@Override
|
||||
public @NonNull Result doWork() {
|
||||
// MAYBE TODO:
|
||||
// - when no threads are running: fetch-inbox, maybe fetch-mvbox, do smtp-jobs.
|
||||
// fetch-sendbox is not needed as these messages shall not be notified.
|
||||
// - when threads are running: interrupt-all-idle
|
||||
|
||||
Log.i("DeltaChat", "-------------------- FetchWorker.doWork() started --------------------");
|
||||
ApplicationDcContext dcContext = DcHelper.getContext(context);
|
||||
dcContext.startThreads(ApplicationDcContext.INTERRUPT_IDLE);
|
||||
dcContext.waitForThreadsExecutedOnce();
|
||||
Log.i("DeltaChat", "-------------------- FetchWorker.doWork() done --------------------");
|
||||
dcContext.maybeStartIo();
|
||||
|
||||
return Result.success(); // when returning, the os may terminate the app again
|
||||
// as we do not know when startIo() has done it's work or if is even doable in one step,
|
||||
// we go the easy way and just wait for some amount of time.
|
||||
// the core has to handle interrupts at any point anyway,
|
||||
// and work also maybe continued when doWork() returns.
|
||||
// however, we should not wait too long here to avoid getting bad battery ratings.
|
||||
Util.sleep(60 * 1000);
|
||||
|
||||
Log.i("DeltaChat", "-------------------- FetchWorker.doWork() done --------------------");
|
||||
return Result.success();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ public class ForegroundDetector implements Application.ActivityLifecycleCallback
|
||||
public void onActivityStarted(Activity activity) {
|
||||
refs++;
|
||||
|
||||
application.dcContext.startThreads(0);
|
||||
application.dcContext.maybeStartIo();
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user