Propagate Regist Events to Java

This commit is contained in:
Florian Märkl 2019-10-14 18:10:14 +02:00
commit c1bbf89553
No known key found for this signature in database
GPG key ID: 125BC8A5A6A1E857
7 changed files with 110 additions and 11 deletions

View file

@ -96,6 +96,23 @@ static jobject jnistr_from_ascii(JNIEnv *env, const char *str)
return r;
}
static jobject get_kotlin_global_object(JNIEnv *env, const char *id)
{
size_t idlen = strlen(id);
char *sig = malloc(idlen + 3);
if(!sig)
return NULL;
sig[0] = 'L';
memcpy(sig + 1, id, idlen);
sig[1 + idlen] = ';';
sig[1 + idlen + 1] = '\0';
jclass cls = E->FindClass(env, id);
jfieldID field_id = E->GetStaticFieldID(env, cls, "INSTANCE", sig);
jobject r = E->GetStaticObjectField(env, cls, field_id);
free(sig);
return r;
}
static ChiakiLog global_log;
static JavaVM *global_vm;
@ -609,13 +626,52 @@ JNIEXPORT void JNICALL JNI_FCN(discoveryServiceFree)(JNIEnv *env, jobject obj, j
typedef struct android_chiaki_regist_t
{
AndroidChiakiLog log;
jobject java_regist;
ChiakiRegist regist;
jobject java_regist;
jmethodID java_regist_event_meth;
jobject java_regist_event_canceled;
jobject java_regist_event_failed;
jclass java_regist_event_success_class;
jmethodID java_regist_event_success_ctor;
} AndroidChiakiRegist;
static void android_chiaki_regist_cb(ChiakiRegistEvent *event, void *user)
{
// TODO
AndroidChiakiRegist *regist = user;
JNIEnv *env = attach_thread_jni();
if(!env)
return;
jobject java_event = NULL;
switch(event->type)
{
case CHIAKI_REGIST_EVENT_TYPE_FINISHED_CANCELED:
java_event = regist->java_regist_event_canceled;
break;
case CHIAKI_REGIST_EVENT_TYPE_FINISHED_FAILED:
java_event = regist->java_regist_event_failed;
break;
case CHIAKI_REGIST_EVENT_TYPE_FINISHED_SUCCESS:
java_event = E->NewObject(env, regist->java_regist_event_success_class, regist->java_regist_event_success_ctor, NULL /* TODO: RegistHost */);
break;
}
if(java_event)
E->CallVoidMethod(env, regist->java_regist, regist->java_regist_event_meth, java_event);
(*global_vm)->DetachCurrentThread(global_vm);
}
static void android_chiaki_regist_fini_partial(JNIEnv *env, AndroidChiakiRegist *regist)
{
android_chiaki_log_fini(&regist->log, env);
E->DeleteGlobalRef(env, regist->java_regist);
E->DeleteGlobalRef(env, regist->java_regist_event_canceled);
E->DeleteGlobalRef(env, regist->java_regist_event_failed);
E->DeleteGlobalRef(env, regist->java_regist_event_success_class);
}
JNIEXPORT void JNICALL JNI_FCN(registStart)(JNIEnv *env, jobject obj, jobject result, jobject regist_info_obj, jobject log_obj, jobject java_regist)
@ -632,6 +688,12 @@ JNIEXPORT void JNICALL JNI_FCN(registStart)(JNIEnv *env, jobject obj, jobject re
android_chiaki_log_init(&regist->log, env, log_obj);
regist->java_regist = E->NewGlobalRef(env, java_regist);
regist->java_regist_event_meth = E->GetMethodID(env, E->GetObjectClass(env, regist->java_regist), "event", "(L"BASE_PACKAGE"/RegistEvent;)V");
regist->java_regist_event_canceled = E->NewGlobalRef(env, get_kotlin_global_object(env, BASE_PACKAGE"/RegistEventCanceled"));
regist->java_regist_event_failed = E->NewGlobalRef(env, get_kotlin_global_object(env, BASE_PACKAGE"/RegistEventFailed"));
regist->java_regist_event_success_class = E->NewGlobalRef(env, E->FindClass(env, BASE_PACKAGE"/RegistEventSuccess"));
regist->java_regist_event_success_ctor = E->GetMethodID(env, regist->java_regist_event_success_class, "<init>", "(L"BASE_PACKAGE"/RegistHost;)V");
jclass regist_info_class = E->GetObjectClass(env, regist_info_obj);
jstring host_string = E->GetObjectField(env, regist_info_obj, E->GetFieldID(env, regist_info_class, "host", "Ljava/lang/String;"));
@ -652,8 +714,7 @@ JNIEXPORT void JNICALL JNI_FCN(registStart)(JNIEnv *env, jobject obj, jobject re
if(err != CHIAKI_ERR_SUCCESS)
{
android_chiaki_log_fini(&regist->log, env);
E->DeleteGlobalRef(env, regist->java_regist);
android_chiaki_regist_fini_partial(env, regist);
free(regist);
regist = NULL;
}
@ -673,7 +734,6 @@ JNIEXPORT void JNICALL JNI_FCN(registFree)(JNIEnv *env, jobject obj, jlong ptr)
{
AndroidChiakiRegist *regist = (AndroidChiakiRegist *)ptr;
chiaki_regist_fini(&regist->regist);
android_chiaki_log_fini(&regist->log, env);
E->DeleteGlobalRef(env, regist->java_regist);
android_chiaki_regist_fini_partial(env, regist);
free(regist);
}

View file

@ -89,6 +89,12 @@ class ChiakiLog(val levelMask: Int, val callback: (level: Int, text: String) ->
{
callback(level, text)
}
fun d(text: String) = log(Level.DEBUG.value, text)
fun v(text: String) = log(Level.VERBOSE.value, text)
fun i(text: String) = log(Level.INFO.value, text)
fun w(text: String) = log(Level.WARNING.value, text)
fun e(text: String) = log(Level.ERROR.value, text)
}
private fun maxAbs(a: Short, b: Short) = if(abs(a.toInt()) > abs(b.toInt())) a else b

View file

@ -17,9 +17,10 @@
package com.metallic.chiaki.regist
import android.content.Intent
import android.os.Bundle
import android.text.method.ScrollingMovementMethod
import android.util.Log
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
@ -55,6 +56,33 @@ class RegistExecuteActivity: AppCompatActivity()
logTextView.scrollTo(0, max(scrollY, 0))
})
viewModel.state.observe(this, Observer {
progressBar.visibility = if(it == RegistExecuteViewModel.State.RUNNING) View.VISIBLE else View.GONE
when(it)
{
RegistExecuteViewModel.State.FAILED ->
{
infoTextView.visibility = View.VISIBLE
infoTextView.setText(R.string.regist_info_failed)
}
RegistExecuteViewModel.State.SUCCESSFUL ->
{
infoTextView.visibility = View.VISIBLE
infoTextView.setText(R.string.regist_info_success)
}
else -> infoTextView.visibility = View.GONE
}
})
shareLogButton.setOnClickListener {
val log = viewModel.logText.value ?: ""
Intent(Intent.ACTION_SEND).also {
it.type = "text/plain"
it.putExtra(Intent.EXTRA_TEXT, log)
startActivity(Intent.createChooser(it, resources.getString(R.string.action_share_log)))
}
}
val registInfo = RegistInfo(
intent.getStringExtra(EXTRA_HOST) ?: return,
intent.getBooleanExtra(EXTRA_BROADCAST, false),

View file

@ -53,7 +53,7 @@ class RegistExecuteViewModel: ViewModel()
}
catch(error: CreateError)
{
// TODO: log about error
log.log.e("Failed to create Regist: ${error.errorCode}")
_state.value = State.FAILED
}
}

View file

@ -74,7 +74,8 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textNoSuggestions|textVisiblePassword"
android:maxLines="1"/>
android:maxLines="1"
android:text="test"/>
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textview.MaterialTextView
@ -122,7 +123,8 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number"
android:maxLength="8" />
android:maxLength="8"
android:text="01234567"/>
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.button.MaterialButton

View file

@ -6,7 +6,8 @@
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="8dp">
android:padding="8dp"
tools:context=".regist.RegistExecuteActivity">
<ImageView
android:id="@+id/iconImageView"

View file

@ -27,4 +27,6 @@
<string name="regist_psn_id_invalid">Please enter a valid PSN ID</string>
<string name="regist_pin_invalid">Please enter a valid %d-digit PIN</string>
<string name="action_share_log">Share Log</string>
<string name="regist_info_success">Regist successful.</string>
<string name="regist_info_failed">Regist failed.</string>
</resources>