From 923615f0ba2489cb37eeec36305b7dbe9fbe904f Mon Sep 17 00:00:00 2001 From: Kangping Dong Date: Sun, 11 Aug 2024 12:29:06 +0800 Subject: [PATCH] [android] consolidate app and service --- android/build-commissioner-libs.sh | 8 +- android/openthread_commissioner/.gitignore | 4 +- .../openthread_commissioner/app/.gitignore | 1 - .../openthread_commissioner/app/build.gradle | 25 +++- .../ActiveOperationalDatasetTest.java | 0 .../app/src/main/AndroidManifest.xml | 11 +- .../app}/BorderAgentDiscoverer.java | 2 +- .../commissioner/app}/BorderAgentInfo.java | 6 +- .../commissioner/app}/CameraSourceView.java | 2 +- .../commissioner/app}/CommissionerUtils.java | 2 +- .../app/CommissioningFragment.java} | 40 +++--- .../commissioner/app}/Constants.java | 2 +- .../app}/FetchCredentialDialogFragment.java | 2 +- .../commissioner/app}/FragmentCallback.java | 16 +-- .../commissioner/app/FragmentUtils.java} | 40 +++--- .../app/InputNetworkPasswordFragment.java | 126 ++++++++++++++++++ .../commissioner/app}/JoinerDeviceInfo.java | 2 +- .../commissioner/app/MainActivity.java | 43 +----- .../app}/NativeCommissionerLogger.java | 2 +- .../commissioner/app}/NetworkAdapter.java | 12 +- .../commissioner/app}/ScanQrCodeFragment.java | 44 +++--- .../app}/SelectNetworkFragment.java | 120 ++++------------- .../app}/ThreadCommissionerException.java | 2 +- .../app}/ThreadCommissionerService.java | 2 +- .../app}/ThreadCommissionerServiceImpl.java | 17 ++- .../commissioner/app}/ThreadNetworkInfo.java | 2 +- .../app}/ThreadNetworkInfoHolder.java | 2 +- .../src/main/res/drawable/ic_done_icon.xml | 0 .../src/main/res/drawable/ic_error_icon.xml | 0 .../res/drawable/ic_network_selected_icon.xml | 0 .../res/drawable/ic_wireless_network_icon.xml | 0 .../main/res/layout/activity_commissioner.xml | 0 .../fragment_fetch_credential_dialog.xml | 0 .../fragment_input_network_password.xml | 7 + .../src/main/res/layout/fragment_meshcop.xml | 2 +- .../fragment_network_password_dialog.xml | 0 .../main/res/layout/fragment_scan_qrcode.xml | 6 +- .../res/layout/fragment_select_network.xml | 0 .../src/main/res/layout/network_list_item.xml | 0 .../app/src/main/res/values/colors.xml | 3 + .../app/src/main/res/values/strings.xml | 20 +++ .../src/main/res/values/styles.xml | 0 .../service/.gitignore | 3 - .../service/build.gradle | 87 ------------ .../service/consumer-rules.pro | 0 .../service/proguard-rules.pro | 21 --- .../service/src/main/AndroidManifest.xml | 19 --- .../service/CommissionerActivity.java | 126 ------------------ .../InputNetworkPasswordDialogFragment.java | 80 ----------- .../service/src/main/res/values/colors.xml | 6 - .../service/src/main/res/values/strings.xml | 22 --- .../openthread_commissioner/settings.gradle | 1 - 52 files changed, 334 insertions(+), 604 deletions(-) delete mode 100644 android/openthread_commissioner/app/.gitignore rename android/openthread_commissioner/{service => app}/src/androidTest/java/io/openthread/commissioner/ActiveOperationalDatasetTest.java (100%) rename android/openthread_commissioner/{service/src/main/java/io/openthread/commissioner/service => app/src/main/java/io/openthread/commissioner/app}/BorderAgentDiscoverer.java (99%) rename android/openthread_commissioner/{service/src/main/java/io/openthread/commissioner/service => app/src/main/java/io/openthread/commissioner/app}/BorderAgentInfo.java (95%) rename android/openthread_commissioner/{service/src/main/java/io/openthread/commissioner/service => app/src/main/java/io/openthread/commissioner/app}/CameraSourceView.java (99%) rename android/openthread_commissioner/{service/src/main/java/io/openthread/commissioner/service => app/src/main/java/io/openthread/commissioner/app}/CommissionerUtils.java (98%) rename android/openthread_commissioner/{service/src/main/java/io/openthread/commissioner/service/MeshcopFragment.java => app/src/main/java/io/openthread/commissioner/app/CommissioningFragment.java} (86%) rename android/openthread_commissioner/{service/src/main/java/io/openthread/commissioner/service => app/src/main/java/io/openthread/commissioner/app}/Constants.java (97%) rename android/openthread_commissioner/{service/src/main/java/io/openthread/commissioner/service => app/src/main/java/io/openthread/commissioner/app}/FetchCredentialDialogFragment.java (99%) rename android/openthread_commissioner/{service/src/main/java/io/openthread/commissioner/service => app/src/main/java/io/openthread/commissioner/app}/FragmentCallback.java (84%) rename android/openthread_commissioner/{service/src/main/java/io/openthread/commissioner/service/CommissionerServiceApp.java => app/src/main/java/io/openthread/commissioner/app/FragmentUtils.java} (57%) create mode 100644 android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/InputNetworkPasswordFragment.java rename android/openthread_commissioner/{service/src/main/java/io/openthread/commissioner/service => app/src/main/java/io/openthread/commissioner/app}/JoinerDeviceInfo.java (98%) rename android/openthread_commissioner/{service/src/main/java/io/openthread/commissioner/service => app/src/main/java/io/openthread/commissioner/app}/NativeCommissionerLogger.java (97%) rename android/openthread_commissioner/{service/src/main/java/io/openthread/commissioner/service => app/src/main/java/io/openthread/commissioner/app}/NetworkAdapter.java (92%) rename android/openthread_commissioner/{service/src/main/java/io/openthread/commissioner/service => app/src/main/java/io/openthread/commissioner/app}/ScanQrCodeFragment.java (84%) rename android/openthread_commissioner/{service/src/main/java/io/openthread/commissioner/service => app/src/main/java/io/openthread/commissioner/app}/SelectNetworkFragment.java (60%) rename android/openthread_commissioner/{service/src/main/java/io/openthread/commissioner/service => app/src/main/java/io/openthread/commissioner/app}/ThreadCommissionerException.java (98%) rename android/openthread_commissioner/{service/src/main/java/io/openthread/commissioner/service => app/src/main/java/io/openthread/commissioner/app}/ThreadCommissionerService.java (98%) rename android/openthread_commissioner/{service/src/main/java/io/openthread/commissioner/service => app/src/main/java/io/openthread/commissioner/app}/ThreadCommissionerServiceImpl.java (95%) rename android/openthread_commissioner/{service/src/main/java/io/openthread/commissioner/service => app/src/main/java/io/openthread/commissioner/app}/ThreadNetworkInfo.java (98%) rename android/openthread_commissioner/{service/src/main/java/io/openthread/commissioner/service => app/src/main/java/io/openthread/commissioner/app}/ThreadNetworkInfoHolder.java (98%) rename android/openthread_commissioner/{service => app}/src/main/res/drawable/ic_done_icon.xml (100%) rename android/openthread_commissioner/{service => app}/src/main/res/drawable/ic_error_icon.xml (100%) rename android/openthread_commissioner/{service => app}/src/main/res/drawable/ic_network_selected_icon.xml (100%) rename android/openthread_commissioner/{service => app}/src/main/res/drawable/ic_wireless_network_icon.xml (100%) rename android/openthread_commissioner/{service => app}/src/main/res/layout/activity_commissioner.xml (100%) rename android/openthread_commissioner/{service => app}/src/main/res/layout/fragment_fetch_credential_dialog.xml (100%) create mode 100644 android/openthread_commissioner/app/src/main/res/layout/fragment_input_network_password.xml rename android/openthread_commissioner/{service => app}/src/main/res/layout/fragment_meshcop.xml (97%) rename android/openthread_commissioner/{service => app}/src/main/res/layout/fragment_network_password_dialog.xml (100%) rename android/openthread_commissioner/{service => app}/src/main/res/layout/fragment_scan_qrcode.xml (91%) rename android/openthread_commissioner/{service => app}/src/main/res/layout/fragment_select_network.xml (100%) rename android/openthread_commissioner/{service => app}/src/main/res/layout/network_list_item.xml (100%) rename android/openthread_commissioner/{service => app}/src/main/res/values/styles.xml (100%) delete mode 100644 android/openthread_commissioner/service/.gitignore delete mode 100644 android/openthread_commissioner/service/build.gradle delete mode 100644 android/openthread_commissioner/service/consumer-rules.pro delete mode 100644 android/openthread_commissioner/service/proguard-rules.pro delete mode 100644 android/openthread_commissioner/service/src/main/AndroidManifest.xml delete mode 100644 android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/CommissionerActivity.java delete mode 100644 android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/InputNetworkPasswordDialogFragment.java delete mode 100644 android/openthread_commissioner/service/src/main/res/values/colors.xml delete mode 100644 android/openthread_commissioner/service/src/main/res/values/strings.xml diff --git a/android/build-commissioner-libs.sh b/android/build-commissioner-libs.sh index 1054904d8..ed9c40e95 100755 --- a/android/build-commissioner-libs.sh +++ b/android/build-commissioner-libs.sh @@ -77,7 +77,7 @@ cd ../../../ ## Copy shared native libraries cp "$BUILD_DIR"/src/java/libcommissioner-java.so "$BUILD_DIR"/libs -mkdir -p openthread_commissioner/service/libs -mkdir -p openthread_commissioner/service/src/main/jniLibs/"${ANDROID_ABI}" -cp "$BUILD_DIR"/libs/libotcommissioner.jar openthread_commissioner/service/libs -cp "$BUILD_DIR"/libs/*.so openthread_commissioner/service/src/main/jniLibs/"${ANDROID_ABI}" +mkdir -p openthread_commissioner/app/libs +mkdir -p openthread_commissioner/app/src/main/jniLibs/"${ANDROID_ABI}" +cp "$BUILD_DIR"/libs/libotcommissioner.jar openthread_commissioner/app/libs +cp "$BUILD_DIR"/libs/*.so openthread_commissioner/app/src/main/jniLibs/"${ANDROID_ABI}" diff --git a/android/openthread_commissioner/.gitignore b/android/openthread_commissioner/.gitignore index aa724b770..f4aeed1df 100644 --- a/android/openthread_commissioner/.gitignore +++ b/android/openthread_commissioner/.gitignore @@ -8,8 +8,10 @@ /.idea/navEditor.xml /.idea/assetWizardSettings.xml .DS_Store -/build +build/ /captures .externalNativeBuild .cxx local.properties +*.jar +*.so diff --git a/android/openthread_commissioner/app/.gitignore b/android/openthread_commissioner/app/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/android/openthread_commissioner/app/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/android/openthread_commissioner/app/build.gradle b/android/openthread_commissioner/app/build.gradle index 45b4ad1f8..6aa612ab2 100644 --- a/android/openthread_commissioner/app/build.gradle +++ b/android/openthread_commissioner/app/build.gradle @@ -78,6 +78,11 @@ android { } } +// This is for the local tests (src/test) to find the native libraries. +tasks.withType(Test) { + systemProperty "java.library.path", "/usr/local/lib" +} + configurations.all { resolutionStrategy { force 'androidx.test:core:1.5.0' @@ -85,12 +90,22 @@ configurations.all { } dependencies { - implementation project(':service') + implementation 'org.jetbrains:annotations:15.0' + def room_version = "2.2.5" + implementation "androidx.room:room-runtime:$room_version" + annotationProcessor "androidx.room:room-compiler:$room_version" + + implementation fileTree(dir: "libs", include: ["*.jar"]) + implementation 'com.google.guava:guava:31.1-jre' implementation 'androidx.appcompat:appcompat:1.2.0' + implementation "androidx.concurrent:concurrent-futures:1.1.0" + implementation 'androidx.constraintlayout:constraintlayout:2.0.2' + implementation 'androidx.navigation:navigation-fragment:2.3.0' + implementation 'com.google.android.gms:play-services-vision:20.1.3+' + implementation 'com.google.android.gms:play-services-threadnetwork:16.0.0' implementation 'com.google.android.material:material:1.2.1' - implementation 'androidx.constraintlayout:constraintlayout:2.0.1' - testImplementation 'junit:junit:4.0' - androidTestImplementation 'androidx.test.ext:junit:1.1.2' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' + androidTestImplementation 'com.google.truth:truth:1.4.4' + androidTestImplementation 'androidx.test.ext:junit:1.1.5' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0' } diff --git a/android/openthread_commissioner/service/src/androidTest/java/io/openthread/commissioner/ActiveOperationalDatasetTest.java b/android/openthread_commissioner/app/src/androidTest/java/io/openthread/commissioner/ActiveOperationalDatasetTest.java similarity index 100% rename from android/openthread_commissioner/service/src/androidTest/java/io/openthread/commissioner/ActiveOperationalDatasetTest.java rename to android/openthread_commissioner/app/src/androidTest/java/io/openthread/commissioner/ActiveOperationalDatasetTest.java diff --git a/android/openthread_commissioner/app/src/main/AndroidManifest.xml b/android/openthread_commissioner/app/src/main/AndroidManifest.xml index b9beb9581..7430cd07b 100644 --- a/android/openthread_commissioner/app/src/main/AndroidManifest.xml +++ b/android/openthread_commissioner/app/src/main/AndroidManifest.xml @@ -1,5 +1,15 @@ + + + + + + + + - diff --git a/android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/BorderAgentDiscoverer.java b/android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/BorderAgentDiscoverer.java similarity index 99% rename from android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/BorderAgentDiscoverer.java rename to android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/BorderAgentDiscoverer.java index 6e4214d12..38c1eca3c 100644 --- a/android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/BorderAgentDiscoverer.java +++ b/android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/BorderAgentDiscoverer.java @@ -26,7 +26,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ -package io.openthread.commissioner.service; +package io.openthread.commissioner.app; import android.Manifest.permission; import android.content.Context; diff --git a/android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/BorderAgentInfo.java b/android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/BorderAgentInfo.java similarity index 95% rename from android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/BorderAgentInfo.java rename to android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/BorderAgentInfo.java index 0a9babede..a916be670 100644 --- a/android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/BorderAgentInfo.java +++ b/android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/BorderAgentInfo.java @@ -26,7 +26,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ -package io.openthread.commissioner.service; +package io.openthread.commissioner.app; import android.os.Parcel; import android.os.Parcelable; @@ -48,9 +48,9 @@ public BorderAgentInfo( @NonNull byte[] extendedPanId, @NonNull InetAddress host, @NonNull int port) { - this.id = id.clone(); + this.id = id == null ? null : id.clone(); this.networkName = networkName; - this.extendedPanId = extendedPanId.clone(); + this.extendedPanId = extendedPanId == null ? null : extendedPanId.clone(); this.host = host; this.port = port; } diff --git a/android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/CameraSourceView.java b/android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/CameraSourceView.java similarity index 99% rename from android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/CameraSourceView.java rename to android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/CameraSourceView.java index 7ca189bf8..3b2b30502 100644 --- a/android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/CameraSourceView.java +++ b/android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/CameraSourceView.java @@ -26,7 +26,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ -package io.openthread.commissioner.service; +package io.openthread.commissioner.app; import android.Manifest; import android.content.Context; diff --git a/android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/CommissionerUtils.java b/android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/CommissionerUtils.java similarity index 98% rename from android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/CommissionerUtils.java rename to android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/CommissionerUtils.java index b31748886..952e18d3f 100644 --- a/android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/CommissionerUtils.java +++ b/android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/CommissionerUtils.java @@ -26,7 +26,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ -package io.openthread.commissioner.service; +package io.openthread.commissioner.app; import androidx.annotation.Nullable; import androidx.concurrent.futures.CallbackToFutureAdapter; diff --git a/android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/MeshcopFragment.java b/android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/CommissioningFragment.java similarity index 86% rename from android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/MeshcopFragment.java rename to android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/CommissioningFragment.java index 2ba0eb6ab..be02476e1 100644 --- a/android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/MeshcopFragment.java +++ b/android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/CommissioningFragment.java @@ -26,7 +26,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ -package io.openthread.commissioner.service; +package io.openthread.commissioner.app; import android.app.Activity; import android.os.Bundle; @@ -46,10 +46,10 @@ import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.ListenableFuture; -public class MeshcopFragment extends Fragment +public class CommissioningFragment extends Fragment implements ThreadCommissionerServiceImpl.IntermediateStateCallback { - private static final String TAG = MeshcopFragment.class.getSimpleName(); + private static final String TAG = CommissioningFragment.class.getSimpleName(); TextView statusText; ProgressBar progressBar; @@ -58,24 +58,20 @@ public class MeshcopFragment extends Fragment ImageView doneImage; ImageView errorImage; - @NonNull private final FragmentCallback meshcopCallback; + private final FragmentCallback fragmentCallback; + private final ThreadNetworkInfoHolder networkInfoHolder; + private final byte[] pskc; + private final JoinerDeviceInfo joinerDeviceInfo; - @NonNull private final ThreadNetworkInfoHolder networkInfoHolder; - - @NonNull private final byte[] pskc; - - @NonNull private final JoinerDeviceInfo joinerDeviceInfo; - - private final ThreadCommissionerServiceImpl commissionerService = - ThreadCommissionerServiceImpl.newInstance(this); + private ThreadCommissionerServiceImpl commissionerService; private ListenableFuture commissionFuture; - public MeshcopFragment( - @NonNull FragmentCallback meshcopCallback, - @NonNull ThreadNetworkInfoHolder networkInfoHolder, - @NonNull byte[] pskc, - @NonNull JoinerDeviceInfo joinerDeviceInfo) { - this.meshcopCallback = meshcopCallback; + public CommissioningFragment( + FragmentCallback fragmentCallback, + ThreadNetworkInfoHolder networkInfoHolder, + byte[] pskc, + JoinerDeviceInfo joinerDeviceInfo) { + this.fragmentCallback = fragmentCallback; this.networkInfoHolder = networkInfoHolder; this.pskc = pskc; this.joinerDeviceInfo = joinerDeviceInfo; @@ -91,6 +87,10 @@ public View onCreateView( public void onViewCreated(@NonNull View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); + if (commissionerService == null) { + commissionerService = ThreadCommissionerServiceImpl.newInstance(requireActivity(), this); + } + cancelButton = view.findViewById(R.id.cancel_button); doneButton = view.findViewById(R.id.done_button); doneImage = view.findViewById(R.id.done_image); @@ -101,13 +101,13 @@ public void onViewCreated(@NonNull View view, Bundle savedInstanceState) { view.findViewById(R.id.cancel_button) .setOnClickListener( v -> { - meshcopCallback.onMeshcopResult(Activity.RESULT_CANCELED); + fragmentCallback.onAddDeviceResult(Activity.RESULT_CANCELED); }); view.findViewById(R.id.done_button) .setOnClickListener( v -> { - meshcopCallback.onMeshcopResult(Activity.RESULT_OK); + fragmentCallback.onAddDeviceResult(Activity.RESULT_OK); }); } diff --git a/android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/Constants.java b/android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/Constants.java similarity index 97% rename from android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/Constants.java rename to android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/Constants.java index 92255dfcd..01958487c 100644 --- a/android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/Constants.java +++ b/android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/Constants.java @@ -26,7 +26,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ -package io.openthread.commissioner.service; +package io.openthread.commissioner.app; public class Constants { public static final String KEY_DEVICE_INFO = "deviceinfo"; diff --git a/android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/FetchCredentialDialogFragment.java b/android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/FetchCredentialDialogFragment.java similarity index 99% rename from android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/FetchCredentialDialogFragment.java rename to android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/FetchCredentialDialogFragment.java index 7331e61b3..65b87f8ee 100644 --- a/android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/FetchCredentialDialogFragment.java +++ b/android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/FetchCredentialDialogFragment.java @@ -26,7 +26,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ -package io.openthread.commissioner.service; +package io.openthread.commissioner.app; import android.app.AlertDialog; import android.app.Dialog; diff --git a/android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/FragmentCallback.java b/android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/FragmentCallback.java similarity index 84% rename from android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/FragmentCallback.java rename to android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/FragmentCallback.java index 98aeeb2f4..24ea2f9e1 100644 --- a/android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/FragmentCallback.java +++ b/android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/FragmentCallback.java @@ -26,15 +26,13 @@ * POSSIBILITY OF SUCH DAMAGE. */ -package io.openthread.commissioner.service; - -import androidx.annotation.Nullable; +package io.openthread.commissioner.app; public interface FragmentCallback { - void onJoinerInfoReceived(@Nullable JoinerDeviceInfo joinerDeviceInfo); - - void onNetworkSelected( - @Nullable ThreadNetworkInfoHolder networkInfoHolder, @Nullable byte[] pskc); - - void onMeshcopResult(int result); + /** + * Called when adding a new Thread device has finished either successfully or failed. + * + * @param result can be one of RESULT_* of {@link android.app.Activity} + */ + void onAddDeviceResult(int result); } diff --git a/android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/CommissionerServiceApp.java b/android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/FragmentUtils.java similarity index 57% rename from android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/CommissionerServiceApp.java rename to android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/FragmentUtils.java index 753ceffa7..e78070a3e 100644 --- a/android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/CommissionerServiceApp.java +++ b/android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/FragmentUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, The OpenThread Commissioner Authors. + * Copyright (c) 2024, The OpenThread Commissioner Authors. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,26 +26,34 @@ * POSSIBILITY OF SUCH DAMAGE. */ -package io.openthread.commissioner.service; +package io.openthread.commissioner.app; -import android.app.Application; +import android.app.Activity; import android.content.Context; +import androidx.fragment.app.Fragment; +import com.google.android.material.dialog.MaterialAlertDialogBuilder; -/** The Commissioner Service App for getting Application Context from anywhere. */ -public class CommissionerServiceApp extends Application { - private static CommissionerServiceApp instance; +public final class FragmentUtils { + private FragmentUtils() {} - public static CommissionerServiceApp getInstance() { - return instance; + /** Shows an alert dialog to the user and exits the commissioning flow when the user consents. */ + public static void showAlertAndExit( + Context context, FragmentCallback fragmentCallback, String title, String message) { + new MaterialAlertDialogBuilder(context, R.style.ThreadNetworkAlertTheme) + .setTitle(title) + .setMessage(message) + .setPositiveButton( + "OK", (dialog, which) -> fragmentCallback.onAddDeviceResult(Activity.RESULT_CANCELED)) + .show(); } - public static Context getContext() { - return instance.getApplicationContext(); - } - - @Override - public void onCreate() { - instance = this; - super.onCreate(); + /** Shows the next fragment and adds the current fragment to the back stack. */ + public static void moveToNextFragment(Fragment currentFragment, Fragment nextFragment) { + currentFragment + .getParentFragmentManager() + .beginTransaction() + .replace(R.id.fragment_container, nextFragment, nextFragment.getClass().getSimpleName()) + .addToBackStack(/* name= */ null) + .commit(); } } diff --git a/android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/InputNetworkPasswordFragment.java b/android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/InputNetworkPasswordFragment.java new file mode 100644 index 000000000..aa73387ec --- /dev/null +++ b/android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/InputNetworkPasswordFragment.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2020, The OpenThread Commissioner Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +package io.openthread.commissioner.app; + +import android.app.Activity; +import android.app.AlertDialog; +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.EditText; +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; +import io.openthread.commissioner.ByteArray; +import io.openthread.commissioner.Commissioner; +import io.openthread.commissioner.Error; +import io.openthread.commissioner.ErrorCode; + +public class InputNetworkPasswordFragment extends Fragment { + + private static final String TAG = InputNetworkPasswordFragment.class.getSimpleName(); + + private final FragmentCallback fragmentCallback; + private final ThreadNetworkInfoHolder selectedNetwork; + private EditText passwordText; + + public InputNetworkPasswordFragment( + FragmentCallback fragmentCallback, ThreadNetworkInfoHolder selectedNetwork) { + this.fragmentCallback = fragmentCallback; + this.selectedNetwork = selectedNetwork; + } + + @Override + public View onCreateView( + LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + return inflater.inflate( + R.layout.fragment_input_network_password, container, /* attachToRoot= */ false); + } + + @Override + public void onViewCreated(@NonNull View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + LayoutInflater inflater = requireActivity().getLayoutInflater(); + View dialogView = inflater.inflate(R.layout.fragment_network_password_dialog, null); + + passwordText = dialogView.findViewById(R.id.network_password); + + new AlertDialog.Builder(requireActivity()) + .setTitle("Enter Password") + .setView(dialogView) + .setPositiveButton(R.string.password_connect, (dialog, which) -> onPasswordInputted()) + .setNegativeButton( + R.string.password_cancel, + (dialog, which) -> fragmentCallback.onAddDeviceResult(Activity.RESULT_CANCELED)) + .create() + .show(); + } + + private void onPasswordInputted() { + byte[] pskc = computePskc(selectedNetwork.getNetworkInfo(), passwordText.getText().toString()); + + if (pskc == null) { + FragmentUtils.showAlertAndExit( + getActivity(), fragmentCallback, "Bad Password", "Cannot compute PSKc!"); + return; + } + + FragmentUtils.moveToNextFragment( + this, new ScanQrCodeFragment(fragmentCallback, selectedNetwork, pskc)); + } + + private byte[] computePskc(ThreadNetworkInfo threadNetworkInfo, String password) { + ByteArray extendedPanId = new ByteArray(threadNetworkInfo.getExtendedPanId()); + ByteArray pskc = new ByteArray(); + Error error = + Commissioner.generatePSKc( + pskc, password, threadNetworkInfo.getNetworkName(), extendedPanId); + if (error.getCode() != ErrorCode.kNone) { + Log.e( + TAG, + String.format( + "failed to generate PSKc: %s; network-name=%s, extended-pan-id=%s", + error, + threadNetworkInfo.getNetworkName(), + CommissionerUtils.getHexString(threadNetworkInfo.getExtendedPanId()))); + return null; + } + + Log.d( + TAG, + String.format( + "generated pskc=%s, network-name=%s, extended-pan-id=%s", + CommissionerUtils.getHexString(pskc), + threadNetworkInfo.getNetworkName(), + CommissionerUtils.getHexString(threadNetworkInfo.getExtendedPanId()))); + return CommissionerUtils.getByteArray(pskc); + } +} diff --git a/android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/JoinerDeviceInfo.java b/android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/JoinerDeviceInfo.java similarity index 98% rename from android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/JoinerDeviceInfo.java rename to android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/JoinerDeviceInfo.java index aacdc2a61..bea6807f5 100644 --- a/android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/JoinerDeviceInfo.java +++ b/android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/JoinerDeviceInfo.java @@ -26,7 +26,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ -package io.openthread.commissioner.service; +package io.openthread.commissioner.app; import android.os.Parcel; import android.os.Parcelable; diff --git a/android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/MainActivity.java b/android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/MainActivity.java index 22df9feca..3039fe150 100644 --- a/android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/MainActivity.java +++ b/android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/MainActivity.java @@ -28,10 +28,8 @@ package io.openthread.commissioner.app; -import android.app.Activity; import android.content.Intent; import android.os.Bundle; -import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.widget.TextView; @@ -40,12 +38,6 @@ import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentTransaction; -import io.openthread.commissioner.service.FragmentCallback; -import io.openthread.commissioner.service.JoinerDeviceInfo; -import io.openthread.commissioner.service.MeshcopFragment; -import io.openthread.commissioner.service.ScanQrCodeFragment; -import io.openthread.commissioner.service.SelectNetworkFragment; -import io.openthread.commissioner.service.ThreadNetworkInfoHolder; public class MainActivity extends AppCompatActivity implements FragmentCallback { @@ -114,44 +106,11 @@ private void clearFragmentsInBackStack() { } private void finishCommissioning(int result) { - // TODO(wgtdkp): show a dialog to the user. - selectedNetwork = null; - pskc = null; - joinerDeviceInfo = null; clearFragmentsInBackStack(); } @Override - public void onNetworkSelected( - @Nullable ThreadNetworkInfoHolder networkInfoHolder, @Nullable byte[] pskc) { - if (networkInfoHolder == null || pskc == null) { - Log.e(TAG, "failed to get selected network or PSKc!"); - finishCommissioning(Activity.RESULT_CANCELED); - return; - } - - this.selectedNetwork = networkInfoHolder; - this.pskc = pskc; - showFragment(new ScanQrCodeFragment(this), true); - } - - @Override - public void onJoinerInfoReceived(@Nullable JoinerDeviceInfo joinerDeviceInfo) { - if (joinerDeviceInfo == null) { - // TODO(wgtdkp): show dialog - Log.e(TAG, "failed to get Joiner Device info!"); - finishCommissioning(Activity.RESULT_CANCELED); - return; - } - - if (this.joinerDeviceInfo == null) { - this.joinerDeviceInfo = joinerDeviceInfo; - showFragment(new MeshcopFragment(this, selectedNetwork, pskc, joinerDeviceInfo), true); - } - } - - @Override - public void onMeshcopResult(int result) { + public void onAddDeviceResult(int result) { finishCommissioning(result); } } diff --git a/android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/NativeCommissionerLogger.java b/android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/NativeCommissionerLogger.java similarity index 97% rename from android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/NativeCommissionerLogger.java rename to android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/NativeCommissionerLogger.java index 06031e54e..60afa57fc 100644 --- a/android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/NativeCommissionerLogger.java +++ b/android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/NativeCommissionerLogger.java @@ -26,7 +26,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ -package io.openthread.commissioner.service; +package io.openthread.commissioner.app; import android.util.Log; import io.openthread.commissioner.LogLevel; diff --git a/android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/NetworkAdapter.java b/android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/NetworkAdapter.java similarity index 92% rename from android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/NetworkAdapter.java rename to android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/NetworkAdapter.java index ebb259621..24ef05598 100644 --- a/android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/NetworkAdapter.java +++ b/android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/NetworkAdapter.java @@ -26,7 +26,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ -package io.openthread.commissioner.service; +package io.openthread.commissioner.app; import android.content.Context; import android.os.Handler; @@ -36,7 +36,7 @@ import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView; -import io.openthread.commissioner.service.BorderAgentDiscoverer.BorderAgentListener; +import io.openthread.commissioner.app.BorderAgentDiscoverer.BorderAgentListener; import java.util.Arrays; import java.util.Vector; @@ -66,7 +66,7 @@ public void addBorderAgent(BorderAgentInfo borderAgent) { networks.add(new ThreadNetworkInfoHolder(borderAgent)); } - new Handler(Looper.getMainLooper()).post(() -> notifyDataSetChanged()); + notifyDataSetChanged(); } public void removeBorderAgent(byte[] lostBorderAgentId) { @@ -78,7 +78,7 @@ public void removeBorderAgent(byte[] lostBorderAgentId) { networks.remove(networkInfoHolder); } - new Handler(Looper.getMainLooper()).post(() -> notifyDataSetChanged()); + notifyDataSetChanged(); return; } } @@ -116,11 +116,11 @@ public View getView(int position, View convertView, ViewGroup container) { @Override public void onBorderAgentFound(BorderAgentInfo borderAgentInfo) { - addBorderAgent(borderAgentInfo); + new Handler(Looper.getMainLooper()).post(() -> addBorderAgent(borderAgentInfo)); } @Override public void onBorderAgentLost(byte[] borderAgentId) { - removeBorderAgent(borderAgentId); + new Handler(Looper.getMainLooper()).post(() -> removeBorderAgent(borderAgentId)); } } diff --git a/android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/ScanQrCodeFragment.java b/android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/ScanQrCodeFragment.java similarity index 84% rename from android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/ScanQrCodeFragment.java rename to android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/ScanQrCodeFragment.java index 229a6003d..f6701c47b 100644 --- a/android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/ScanQrCodeFragment.java +++ b/android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/ScanQrCodeFragment.java @@ -26,9 +26,10 @@ * POSSIBILITY OF SUCH DAMAGE. */ -package io.openthread.commissioner.service; +package io.openthread.commissioner.app; import android.Manifest; +import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.pm.PackageManager; @@ -42,6 +43,7 @@ import android.view.View; import android.view.ViewGroup; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.annotation.RequiresPermission; import androidx.core.app.ActivityCompat; import androidx.fragment.app.Fragment; @@ -59,12 +61,16 @@ public class ScanQrCodeFragment extends Fragment implements Detector.Processor { - joinerInfoCallback.onJoinerInfoReceived(null); - }); + .setOnClickListener(v -> fragmentCallback.onAddDeviceResult(Activity.RESULT_CANCELED)); cameraSourceView = view.findViewById(R.id.camera_view); if (hasCameraPermission()) { @@ -152,12 +155,13 @@ public void onRequestPermissionsResult( + " Result code = " + (grantResults.length > 0 ? grantResults[0] : "(empty)")); + showAlertAndExit("Permission Denied", "No camera permission!"); + } + + /** Shows an alert dialog to the user and exits the commissioning flow when the user consents. */ + private void showAlertAndExit(String title, String message) { DialogInterface.OnClickListener listener = - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - joinerInfoCallback.onJoinerInfoReceived(null); - } - }; + (dialog, id) -> fragmentCallback.onAddDeviceResult(Activity.RESULT_CANCELED); AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder @@ -208,12 +212,20 @@ private void handleBarcode(Barcode barcode) { cameraSourceView.startCamera(); } - joinerInfoCallback.onJoinerInfoReceived(joinerDeviceInfo); + getParentFragmentManager() + .beginTransaction() + .replace( + R.id.fragment_container, + new CommissioningFragment(fragmentCallback, selectedNetwork, pskc, joinerDeviceInfo), + CommissioningFragment.class.getSimpleName()) + .addToBackStack(/* name= */ null) + .commit(); } + @Nullable private JoinerDeviceInfo parseJoinerDeviceInfo(Barcode barcode) { if (barcode.valueFormat != Barcode.TEXT) { - Log.e(TAG, "broken QR code! expect QR code encode a URL string."); + Log.e(TAG, "broken QR code! expect QR code encode a TEXT string."); return null; } diff --git a/android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/SelectNetworkFragment.java b/android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/SelectNetworkFragment.java similarity index 60% rename from android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/SelectNetworkFragment.java rename to android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/SelectNetworkFragment.java index c34ede3a4..9990f7148 100644 --- a/android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/SelectNetworkFragment.java +++ b/android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/SelectNetworkFragment.java @@ -26,9 +26,8 @@ * POSSIBILITY OF SUCH DAMAGE. */ -package io.openthread.commissioner.service; +package io.openthread.commissioner.app; -import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; @@ -43,29 +42,20 @@ import androidx.core.content.ContextCompat; import androidx.fragment.app.Fragment; import com.google.android.gms.threadnetwork.ThreadNetworkCredentials; -import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.common.util.concurrent.FluentFuture; import com.google.common.util.concurrent.FutureCallback; -import io.openthread.commissioner.ByteArray; -import io.openthread.commissioner.Commissioner; -import io.openthread.commissioner.Error; -import io.openthread.commissioner.ErrorCode; -public class SelectNetworkFragment extends Fragment - implements InputNetworkPasswordDialogFragment.PasswordDialogListener, - FetchCredentialDialogFragment.CredentialListener, - View.OnClickListener { +public class SelectNetworkFragment extends Fragment { private static final String TAG = SelectNetworkFragment.class.getSimpleName(); - private FragmentCallback networkInfoCallback; + private FragmentCallback fragmentCallback; @Nullable private JoinerDeviceInfo joinerDeviceInfo; private NetworkAdapter networksAdapter; private ThreadNetworkInfoHolder selectedNetwork; - private byte[] userInputPskc; private Button addDeviceButton; private BorderAgentDiscoverer borderAgentDiscoverer; @@ -73,8 +63,8 @@ public class SelectNetworkFragment extends Fragment public SelectNetworkFragment() {} public SelectNetworkFragment( - @NonNull FragmentCallback networkInfoCallback, @Nullable JoinerDeviceInfo joinerDeviceInfo) { - this.networkInfoCallback = networkInfoCallback; + @NonNull FragmentCallback fragmentCallback, @Nullable JoinerDeviceInfo joinerDeviceInfo) { + this.fragmentCallback = fragmentCallback; this.joinerDeviceInfo = joinerDeviceInfo; } @@ -119,7 +109,6 @@ public void onPause() { @Override public View onCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - // Inflate the layout for this fragment return inflater.inflate(R.layout.fragment_select_network, container, false); } @@ -127,9 +116,9 @@ public View onCreateView( public void onViewCreated(@NonNull View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); - // Hide the button addDeviceButton = view.findViewById(R.id.add_device_button); addDeviceButton.setVisibility(View.GONE); + addDeviceButton.setOnClickListener(v -> onAddDeviceButtonClicked()); if (joinerDeviceInfo != null) { String deviceInfoString = @@ -152,62 +141,22 @@ public void onViewCreated(@NonNull View view, Bundle savedInstanceState) { selectedNetwork = (ThreadNetworkInfoHolder) adapterView.getItemAtPosition(position); addDeviceButton.setVisibility(View.VISIBLE); }); - - view.findViewById(R.id.add_device_button).setOnClickListener(this); - } - - // Click listeners for network password dialog. - - @Override - public void onPositiveClick(InputNetworkPasswordDialogFragment fragment, String password) { - BorderAgentInfo selectedBorderAgent = selectedNetwork.getBorderAgents().get(0); - userInputPskc = computePskc(selectedNetwork.getNetworkInfo(), password); - - networkInfoCallback.onNetworkSelected(selectedNetwork, userInputPskc); - } - - @Override - public void onNegativeClick(InputNetworkPasswordDialogFragment fragment) { - networkInfoCallback.onNetworkSelected(selectedNetwork, null); - } - - private byte[] computePskc(ThreadNetworkInfo threadNetworkInfo, String password) { - ByteArray extendedPanId = new ByteArray(threadNetworkInfo.getExtendedPanId()); - ByteArray pskc = new ByteArray(); - Error error = - Commissioner.generatePSKc( - pskc, password, threadNetworkInfo.getNetworkName(), extendedPanId); - if (error.getCode() != ErrorCode.kNone) { - Log.e( - TAG, - String.format( - "failed to generate PSKc: %s; network-name=%s, extended-pan-id=%s", - error.toString(), - threadNetworkInfo.getNetworkName(), - CommissionerUtils.getHexString(threadNetworkInfo.getExtendedPanId()))); - } else { - Log.d( - TAG, - String.format( - "generated pskc=%s, network-name=%s, extended-pan-id=%s", - CommissionerUtils.getHexString(pskc), - threadNetworkInfo.getNetworkName(), - CommissionerUtils.getHexString(threadNetworkInfo.getExtendedPanId()))); - } - - return CommissionerUtils.getByteArray(pskc); } - @Override - public void onClick(View view) { + private void onAddDeviceButtonClicked() { BorderAgentInfo selectedBorderAgent = selectedNetwork.getBorderAgents().get(0); if (selectedBorderAgent.id == null) { - showAlertDialog("Invalid Border Router: no \"id\" associated"); + FragmentUtils.showAlertAndExit( + getActivity(), + fragmentCallback, + "Invalid Border Router", + "No \"id\" found in Border Router mDNS service"); return; } ThreadCommissionerServiceImpl commissionerService = - ThreadCommissionerServiceImpl.newInstance(null); + ThreadCommissionerServiceImpl.newInstance( + getActivity(), /* intermediateStateCallback= */ null); FluentFuture.from(commissionerService.getThreadNetworkCredentials(selectedBorderAgent)) .addCallback( @@ -215,44 +164,27 @@ public void onClick(View view) { @Override public void onSuccess(ThreadNetworkCredentials credentials) { if (credentials != null) { - networkInfoCallback.onNetworkSelected(selectedNetwork, credentials.getPskc()); + FragmentUtils.moveToNextFragment( + SelectNetworkFragment.this, + new ScanQrCodeFragment( + fragmentCallback, selectedNetwork, credentials.getPskc())); } else { - // Ask the user to input Commissioner password. - new InputNetworkPasswordDialogFragment(SelectNetworkFragment.this) - .show( - getParentFragmentManager(), - InputNetworkPasswordDialogFragment.class.getSimpleName()); + FragmentUtils.moveToNextFragment( + SelectNetworkFragment.this, + new InputNetworkPasswordFragment(fragmentCallback, selectedNetwork)); } } @Override public void onFailure(Throwable t) { Log.e(TAG, "Failed to retrieve Thread network credentials from GMS", t); - showAlertDialog(t.getMessage()); + FragmentUtils.showAlertAndExit( + getActivity(), + fragmentCallback, + "Retrieve Thread Credentials Error", + "Failed to retrieve Thread network credentials from GMS: " + t.getMessage()); } }, ContextCompat.getMainExecutor(getActivity())); } - - private void showAlertDialog(String message) { - new MaterialAlertDialogBuilder(getActivity(), R.style.ThreadNetworkAlertTheme) - .setMessage(message) - .setPositiveButton( - "OK", - ((dialog, which) -> { - networkInfoCallback.onMeshcopResult(Activity.RESULT_CANCELED); - })) - .show(); - } - - @Override - public void onCancelClick(FetchCredentialDialogFragment fragment) { - // TODO: - } - - @Override - public void onConfirmClick( - FetchCredentialDialogFragment fragment, ThreadNetworkCredentials credentials) { - // TODO: - } } diff --git a/android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/ThreadCommissionerException.java b/android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/ThreadCommissionerException.java similarity index 98% rename from android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/ThreadCommissionerException.java rename to android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/ThreadCommissionerException.java index 2d8512b23..acec43adf 100644 --- a/android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/ThreadCommissionerException.java +++ b/android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/ThreadCommissionerException.java @@ -26,7 +26,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ -package io.openthread.commissioner.service; +package io.openthread.commissioner.app; import androidx.annotation.NonNull; import io.openthread.commissioner.ErrorCode; diff --git a/android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/ThreadCommissionerService.java b/android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/ThreadCommissionerService.java similarity index 98% rename from android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/ThreadCommissionerService.java rename to android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/ThreadCommissionerService.java index 87add5fca..25c233a18 100644 --- a/android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/ThreadCommissionerService.java +++ b/android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/ThreadCommissionerService.java @@ -26,7 +26,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ -package io.openthread.commissioner.service; +package io.openthread.commissioner.app; import androidx.annotation.NonNull; import com.google.android.gms.threadnetwork.ThreadNetworkCredentials; diff --git a/android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/ThreadCommissionerServiceImpl.java b/android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/ThreadCommissionerServiceImpl.java similarity index 95% rename from android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/ThreadCommissionerServiceImpl.java rename to android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/ThreadCommissionerServiceImpl.java index e2490118e..0bd8c8bbb 100644 --- a/android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/ThreadCommissionerServiceImpl.java +++ b/android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/ThreadCommissionerServiceImpl.java @@ -26,8 +26,9 @@ * POSSIBILITY OF SUCH DAMAGE. */ -package io.openthread.commissioner.service; +package io.openthread.commissioner.app; +import android.content.Context; import android.os.ConditionVariable; import android.util.Log; import androidx.annotation.NonNull; @@ -48,6 +49,7 @@ import io.openthread.commissioner.Config; import io.openthread.commissioner.Error; import io.openthread.commissioner.ErrorCode; +import io.openthread.commissioner.Logger; import java.math.BigInteger; import java.net.Inet6Address; import java.net.InetAddress; @@ -69,6 +71,9 @@ public interface IntermediateStateCallback { private static final int SECONDS_WAIT_FOR_JOINER = 60; + // Use a static reference to the logger to workaround the Java & C++ reference dependency issue + private static Logger commissionerLogger = new NativeCommissionerLogger(); + private final ThreadNetworkClient threadNetworkClient; private final Executor executor; @Nullable private IntermediateStateCallback intermediateStateCallback; @@ -77,9 +82,9 @@ public interface IntermediateStateCallback { private ConditionVariable curJoinerCommissioned = new ConditionVariable(); public static ThreadCommissionerServiceImpl newInstance( - @Nullable IntermediateStateCallback intermediateStateCallback) { + Context context, @Nullable IntermediateStateCallback intermediateStateCallback) { return new ThreadCommissionerServiceImpl( - ThreadNetwork.getClient(CommissionerServiceApp.getContext()), + ThreadNetwork.getClient(context), Executors.newSingleThreadExecutor(), intermediateStateCallback); } @@ -143,9 +148,9 @@ private void doCommissionJoinerDevice( config.setId("TestComm"); config.setDomainName("TestDomain"); config.setEnableCcm(false); - config.setEnableDtlsDebugLogging(false); + config.setEnableDtlsDebugLogging(true); config.setPSKc(new ByteArray(pskc)); - config.setLogger(new NativeCommissionerLogger()); + config.setLogger(commissionerLogger); try { // Initialize the native commissioner. @@ -206,7 +211,7 @@ private byte[] doFetchActiveDataset( config.setEnableCcm(false); config.setEnableDtlsDebugLogging(true); config.setPSKc(new ByteArray(pskc)); - config.setLogger(new NativeCommissionerLogger()); + config.setLogger(commissionerLogger); try { // Initialize the native commissioner diff --git a/android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/ThreadNetworkInfo.java b/android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/ThreadNetworkInfo.java similarity index 98% rename from android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/ThreadNetworkInfo.java rename to android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/ThreadNetworkInfo.java index 87b6b4036..6afed98df 100644 --- a/android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/ThreadNetworkInfo.java +++ b/android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/ThreadNetworkInfo.java @@ -26,7 +26,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ -package io.openthread.commissioner.service; +package io.openthread.commissioner.app; import android.os.Parcel; import android.os.Parcelable; diff --git a/android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/ThreadNetworkInfoHolder.java b/android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/ThreadNetworkInfoHolder.java similarity index 98% rename from android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/ThreadNetworkInfoHolder.java rename to android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/ThreadNetworkInfoHolder.java index 9aa068437..59b27fc32 100644 --- a/android/openthread_commissioner/service/src/main/java/io/openthread/commissioner/service/ThreadNetworkInfoHolder.java +++ b/android/openthread_commissioner/app/src/main/java/io/openthread/commissioner/app/ThreadNetworkInfoHolder.java @@ -26,7 +26,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ -package io.openthread.commissioner.service; +package io.openthread.commissioner.app; import android.os.Parcel; import android.os.Parcelable; diff --git a/android/openthread_commissioner/service/src/main/res/drawable/ic_done_icon.xml b/android/openthread_commissioner/app/src/main/res/drawable/ic_done_icon.xml similarity index 100% rename from android/openthread_commissioner/service/src/main/res/drawable/ic_done_icon.xml rename to android/openthread_commissioner/app/src/main/res/drawable/ic_done_icon.xml diff --git a/android/openthread_commissioner/service/src/main/res/drawable/ic_error_icon.xml b/android/openthread_commissioner/app/src/main/res/drawable/ic_error_icon.xml similarity index 100% rename from android/openthread_commissioner/service/src/main/res/drawable/ic_error_icon.xml rename to android/openthread_commissioner/app/src/main/res/drawable/ic_error_icon.xml diff --git a/android/openthread_commissioner/service/src/main/res/drawable/ic_network_selected_icon.xml b/android/openthread_commissioner/app/src/main/res/drawable/ic_network_selected_icon.xml similarity index 100% rename from android/openthread_commissioner/service/src/main/res/drawable/ic_network_selected_icon.xml rename to android/openthread_commissioner/app/src/main/res/drawable/ic_network_selected_icon.xml diff --git a/android/openthread_commissioner/service/src/main/res/drawable/ic_wireless_network_icon.xml b/android/openthread_commissioner/app/src/main/res/drawable/ic_wireless_network_icon.xml similarity index 100% rename from android/openthread_commissioner/service/src/main/res/drawable/ic_wireless_network_icon.xml rename to android/openthread_commissioner/app/src/main/res/drawable/ic_wireless_network_icon.xml diff --git a/android/openthread_commissioner/service/src/main/res/layout/activity_commissioner.xml b/android/openthread_commissioner/app/src/main/res/layout/activity_commissioner.xml similarity index 100% rename from android/openthread_commissioner/service/src/main/res/layout/activity_commissioner.xml rename to android/openthread_commissioner/app/src/main/res/layout/activity_commissioner.xml diff --git a/android/openthread_commissioner/service/src/main/res/layout/fragment_fetch_credential_dialog.xml b/android/openthread_commissioner/app/src/main/res/layout/fragment_fetch_credential_dialog.xml similarity index 100% rename from android/openthread_commissioner/service/src/main/res/layout/fragment_fetch_credential_dialog.xml rename to android/openthread_commissioner/app/src/main/res/layout/fragment_fetch_credential_dialog.xml diff --git a/android/openthread_commissioner/app/src/main/res/layout/fragment_input_network_password.xml b/android/openthread_commissioner/app/src/main/res/layout/fragment_input_network_password.xml new file mode 100644 index 000000000..5e01fcfb5 --- /dev/null +++ b/android/openthread_commissioner/app/src/main/res/layout/fragment_input_network_password.xml @@ -0,0 +1,7 @@ + + + diff --git a/android/openthread_commissioner/service/src/main/res/layout/fragment_meshcop.xml b/android/openthread_commissioner/app/src/main/res/layout/fragment_meshcop.xml similarity index 97% rename from android/openthread_commissioner/service/src/main/res/layout/fragment_meshcop.xml rename to android/openthread_commissioner/app/src/main/res/layout/fragment_meshcop.xml index d2f55e18f..15f21dc97 100644 --- a/android/openthread_commissioner/service/src/main/res/layout/fragment_meshcop.xml +++ b/android/openthread_commissioner/app/src/main/res/layout/fragment_meshcop.xml @@ -4,7 +4,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - tools:context="io.openthread.commissioner.service.CommissionerActivity"> + tools:context=".MainActivity"> + tools:context=".MainActivity"> - + app:layout_constraintTop_toBottomOf="@id/title_text">