elements = new ArrayList<>(meshNetwork.getElements(group));
+ final BottomSheetDetailsDialogFragment onOffFragment = BottomSheetDetailsDialogFragment.getInstance(group, elements);
+ onOffFragment.show(getSupportFragmentManager(), DETAILS_FRAGMENT);
+ }
}
@Override
public void editModelItem(@NonNull final Element element, @NonNull final MeshModel model) {
final Boolean isConnectedToNetwork = mViewModel.isConnectedToProxy().getValue();
if (isConnectedToNetwork != null && isConnectedToNetwork) {
- final ProvisionedMeshNode node = mViewModel.getMeshManagerApi().getMeshNetwork().getProvisionedNode(element.getElementAddress());
+ final MeshNetwork network = mViewModel.getNetworkLiveData().getMeshNetwork();
+ final ProvisionedMeshNode node = network.getNode(element.getElementAddress());
if (node != null) {
mViewModel.setSelectedMeshNode(node);
mViewModel.setSelectedElement(element);
mViewModel.setSelectedModel(model);
- startActivity(model);
+ mViewModel.navigateToModelActivity(this, model);
}
} else {
Toast.makeText(this, R.string.disconnected_network_rationale, Toast.LENGTH_SHORT).show();
@@ -284,30 +296,8 @@ public void editModelItem(@NonNull final Element element, @NonNull final MeshMod
@Override
public void onGroupNameChanged(@NonNull final Group group) {
- mViewModel.getMeshManagerApi().getMeshNetwork().updateGroup(group);
- }
-
- /**
- * Start activity based on the type of the model
- *
- * This way we can seperate the ui logic for different activities
- *
- * @param model model
- */
- private void startActivity(final MeshModel model) {
- final Intent intent;
- if (model instanceof ConfigurationServerModel) {
- intent = new Intent(this, ConfigurationServerActivity.class);
- } else if (model instanceof GenericOnOffServerModel) {
- intent = new Intent(this, GenericOnOffServerActivity.class);
- } else if (model instanceof GenericLevelServerModel) {
- intent = new Intent(this, GenericLevelServerActivity.class);
- } else if (model instanceof VendorModel) {
- intent = new Intent(this, VendorModelActivity.class);
- } else {
- intent = new Intent(this, ModelConfigurationActivity.class);
- }
- startActivity(intent);
+ final MeshNetwork network = mViewModel.getNetworkLiveData().getMeshNetwork();
+ network.updateGroup(group);
}
@Override
@@ -320,14 +310,17 @@ public void sendVendorModelMessage(final int modelId, final int keyIndex, final
if (model == null)
return;
- final ApplicationKey appKey = mViewModel.getMeshManagerApi().getMeshNetwork().getAppKey(keyIndex);
- final MeshMessage message;
- if (acknowledged) {
- message = new VendorModelMessageAcked(appKey.getKey(), modelId, model.getCompanyIdentifier(), opCode, parameters);
- } else {
- message = new VendorModelMessageUnacked(appKey.getKey(), modelId, model.getCompanyIdentifier(), opCode, parameters);
+ final MeshNetwork network = mViewModel.getNetworkLiveData().getMeshNetwork();
+ if (network != null) {
+ final ApplicationKey appKey = network.getAppKey(keyIndex);
+ final MeshMessage message;
+ if (acknowledged) {
+ message = new VendorModelMessageAcked(appKey, modelId, model.getCompanyIdentifier(), opCode, parameters);
+ } else {
+ message = new VendorModelMessageUnacked(appKey, modelId, model.getCompanyIdentifier(), opCode, parameters);
+ }
+ sendMessage(group.getAddress(), message);
}
- mViewModel.getMeshManagerApi().sendMeshMessage(group.getGroupAddress(), message);
}
private VendorModel getModel(final int modelId, final int appKeyIndex) {
@@ -342,4 +335,14 @@ private VendorModel getModel(final int modelId, final int appKeyIndex) {
return null;
}
+
+ private void sendMessage(final int address, final MeshMessage meshMessage) {
+ try {
+ mViewModel.getMeshManagerApi().createMeshPdu(address, meshMessage);
+ } catch (IllegalArgumentException ex) {
+ final DialogFragmentError message = DialogFragmentError.
+ newInstance(getString(R.string.title_error), ex.getMessage());
+ message.show(getSupportFragmentManager(), null);
+ }
+ }
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/GroupsFragment.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/GroupsFragment.java
index 5c8ad57d1..5ab8292a4 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/GroupsFragment.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/GroupsFragment.java
@@ -22,29 +22,30 @@
package no.nordicsemi.android.nrfmeshprovisioner;
-import android.arch.lifecycle.ViewModelProvider;
-import android.arch.lifecycle.ViewModelProviders;
-import android.content.Context;
+import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.design.widget.FloatingActionButton;
-import android.support.design.widget.Snackbar;
-import android.support.v4.app.Fragment;
-import android.support.v7.widget.DividerItemDecoration;
-import android.support.v7.widget.LinearLayoutManager;
-import android.support.v7.widget.RecyclerView;
-import android.support.v7.widget.helper.ItemTouchHelper;
import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
+import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton;
+import com.google.android.material.snackbar.Snackbar;
+
+import java.util.UUID;
+
import javax.inject.Inject;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.coordinatorlayout.widget.CoordinatorLayout;
+import androidx.fragment.app.Fragment;
+import androidx.lifecycle.ViewModelProvider;
+import androidx.lifecycle.ViewModelProviders;
+import androidx.recyclerview.widget.DividerItemDecoration;
+import androidx.recyclerview.widget.ItemTouchHelper;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
import butterknife.BindView;
import butterknife.ButterKnife;
import no.nordicsemi.android.meshprovisioner.Group;
@@ -52,7 +53,6 @@
import no.nordicsemi.android.nrfmeshprovisioner.adapter.GroupAdapter;
import no.nordicsemi.android.nrfmeshprovisioner.di.Injectable;
import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentCreateGroup;
-import no.nordicsemi.android.nrfmeshprovisioner.utils.Utils;
import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.SharedViewModel;
import no.nordicsemi.android.nrfmeshprovisioner.widgets.ItemTouchHelperAdapter;
import no.nordicsemi.android.nrfmeshprovisioner.widgets.RemovableItemTouchHelperCallback;
@@ -61,9 +61,7 @@
public class GroupsFragment extends Fragment implements Injectable,
ItemTouchHelperAdapter,
GroupAdapter.OnItemClickListener,
- DialogFragmentCreateGroup.DialogFragmentCreateGroupListener {
-
- private static final String TAG = GroupsFragment.class.getSimpleName();
+ GroupCallbacks {
private SharedViewModel mViewModel;
@@ -71,25 +69,23 @@ public class GroupsFragment extends Fragment implements Injectable,
ViewModelProvider.Factory mViewModelFactory;
@BindView(R.id.container)
- View container;
- @BindView(R.id.fab_add_group)
- FloatingActionButton fab;
+ CoordinatorLayout container;
+ @BindView(android.R.id.empty)
+ View mEmptyView;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setHasOptionsMenu(true);
}
@Nullable
@Override
public View onCreateView(@NonNull final LayoutInflater inflater, @Nullable final ViewGroup container, @Nullable final Bundle savedInstanceState) {
- final View rootView = inflater.inflate(R.layout.fragment_groups, null);
- ButterKnife.bind(this, rootView);
-
+ @SuppressLint("InflateParams") final View rootView = inflater.inflate(R.layout.fragment_groups, null);
mViewModel = ViewModelProviders.of(requireActivity(), mViewModelFactory).get(SharedViewModel.class);
+ ButterKnife.bind(this, rootView);
- final View noGroupsConfiguredView = rootView.findViewById(R.id.no_groups_configured);
+ final ExtendedFloatingActionButton fab = rootView.findViewById(R.id.fab_add_group);
// Configure the recycler view
final RecyclerView recyclerViewGroups = rootView.findViewById(R.id.recycler_view_groups);
@@ -103,18 +99,18 @@ public View onCreateView(@NonNull final LayoutInflater inflater, @Nullable final
adapter.setOnItemClickListener(this);
recyclerViewGroups.setAdapter(adapter);
- mViewModel.getMeshNetworkLiveData().observe(this, meshNetworkLiveData -> {
+ mViewModel.getNetworkLiveData().observe(this, meshNetworkLiveData -> {
if (meshNetworkLiveData != null) {
- if(meshNetworkLiveData.getMeshNetwork().getGroups().isEmpty()){
- noGroupsConfiguredView.setVisibility(View.VISIBLE);
+ if (meshNetworkLiveData.getMeshNetwork().getGroups().isEmpty()) {
+ mEmptyView.setVisibility(View.VISIBLE);
} else {
- noGroupsConfiguredView.setVisibility(View.INVISIBLE);
+ mEmptyView.setVisibility(View.INVISIBLE);
}
}
});
mViewModel.getGroups().observe(this, groups -> {
- final MeshNetwork network = mViewModel.getMeshNetworkLiveData().getMeshNetwork();
+ final MeshNetwork network = mViewModel.getNetworkLiveData().getMeshNetwork();
adapter.updateAdapter(network, groups);
});
@@ -123,41 +119,23 @@ public View onCreateView(@NonNull final LayoutInflater inflater, @Nullable final
fragmentCreateGroup.show(getChildFragmentManager(), null);
});
- return rootView;
-
- }
-
- @Override
- public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
- if (mViewModel.getProvisionedNodes().getValue() != null && !mViewModel.getProvisionedNodes().getValue().isEmpty()) {
- final Boolean isConnectedToNetwork = mViewModel.isConnectedToProxy().getValue();
- if (isConnectedToNetwork != null && isConnectedToNetwork) {
- inflater.inflate(R.menu.disconnect, menu);
- } else {
- inflater.inflate(R.menu.connect, menu);
+ recyclerViewGroups.addOnScrollListener(new RecyclerView.OnScrollListener() {
+ @Override
+ public void onScrolled(@NonNull final RecyclerView recyclerView, final int dx, final int dy) {
+ super.onScrolled(recyclerView, dx, dy);
+ final LinearLayoutManager m = (LinearLayoutManager) recyclerView.getLayoutManager();
+ if (m != null) {
+ if (m.findFirstCompletelyVisibleItemPosition() == 0) {
+ fab.extend(true);
+ } else {
+ fab.shrink(true);
+ }
+ }
}
- }
- }
+ });
- @Override
- public boolean onOptionsItemSelected(final MenuItem item) {
- final int id = item.getItemId();
- switch (id) {
- case R.id.action_connect:
- final Intent intent = new Intent(requireActivity(), ScannerActivity.class);
- intent.putExtra(Utils.EXTRA_DATA_PROVISIONING_SERVICE, false);
- startActivity(intent);
- return true;
- case R.id.action_disconnect:
- mViewModel.disconnect();
- return true;
- }
- return false;
- }
+ return rootView;
- @Override
- public void onAttach(final Context context) {
- super.onAttach(context);
}
@Override
@@ -169,31 +147,66 @@ public void onItemClick(final int address) {
@Override
public void onItemDismiss(final RemovableViewHolder viewHolder) {
final int position = viewHolder.getAdapterPosition();
- final MeshNetwork network = mViewModel.getMeshNetworkLiveData().getMeshNetwork();
+ final MeshNetwork network = mViewModel.getNetworkLiveData().getMeshNetwork();
final Group group = network.getGroups().get(position);
- if(network.getModels(group).size() == 0) {
+ if (network.getModels(group).size() == 0) {
network.removeGroup(group);
- final String message = getString(R.string.group_deleted, group.getName());
- displaySnackBar(message);
+ displaySnackBar(group);
}
}
@Override
public void onItemDismissFailed(final RemovableViewHolder viewHolder) {
final String message = getString(R.string.error_group_unsubscribe_to_delete);
- displaySnackBar(message);
+ mViewModel.displaySnackBar(requireActivity(), container, message, Snackbar.LENGTH_LONG);
}
+ @Override
+ public Group createGroup() {
+ final MeshNetwork network = mViewModel.getNetworkLiveData().getMeshNetwork();
+ return network.createGroup(network.getSelectedProvisioner(), "Mesh Group");
+ }
- private void displaySnackBar(final String message){
- Snackbar.make(container, message, Snackbar.LENGTH_LONG)
- .setActionTextColor(getResources().getColor(R.color.colorPrimaryDark ))
- .show();
+ @Override
+ public Group createGroup(@NonNull final String name) {
+ final MeshNetwork network = mViewModel.getNetworkLiveData().getMeshNetwork();
+ return network.createGroup(network.getSelectedProvisioner(), name);
+ }
+
+ @Override
+ public Group createGroup(@NonNull final UUID uuid, final String name) {
+ final MeshNetwork network = mViewModel.getNetworkLiveData().getMeshNetwork();
+ return network.createGroup(uuid, null, name);
}
@Override
- public boolean createGroup(@NonNull final String name, final int address) {
- final MeshNetwork network = mViewModel.getMeshNetworkLiveData().getMeshNetwork();
- return network.addGroup(address, name);
+ public boolean onGroupAdded(@NonNull final String name, final int address) {
+ final MeshNetwork network = mViewModel.getNetworkLiveData().getMeshNetwork();
+ final Group group = network.createGroup(network.getSelectedProvisioner(), address, name);
+ if (group != null) {
+ return network.addGroup(group);
+ }
+ return false;
+ }
+
+ @Override
+ public boolean onGroupAdded(@NonNull final Group group) {
+ final MeshNetwork network = mViewModel.getNetworkLiveData().getMeshNetwork();
+ return network.addGroup(group);
+ }
+
+ private void displaySnackBar(final Group group) {
+ final String message = getString(R.string.group_deleted, group.getName());
+ Snackbar.make(container, message, Snackbar.LENGTH_LONG)
+ .setActionTextColor(getResources().getColor(R.color.colorPrimaryDark))
+ .setAction(R.string.undo, v -> {
+ mEmptyView.setVisibility(View.INVISIBLE);
+ final MeshNetwork network = mViewModel.getNetworkLiveData().getMeshNetwork();
+ if (network != null) {
+ network.addGroup(group);
+ }
+
+ })
+ .show();
}
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/MainActivity.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/MainActivity.java
index b695088a6..5a5335549 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/MainActivity.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/MainActivity.java
@@ -22,34 +22,36 @@
package no.nordicsemi.android.nrfmeshprovisioner;
-import android.arch.lifecycle.ViewModelProvider;
import android.content.Intent;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.design.widget.BottomNavigationView;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentTransaction;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.Toolbar;
+import android.view.Menu;
import android.view.MenuItem;
-import android.view.View;
+
+import com.google.android.material.bottomnavigation.BottomNavigationView;
import javax.inject.Inject;
-import butterknife.BindView;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.Toolbar;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentTransaction;
+import androidx.lifecycle.ViewModelProvider;
+import androidx.lifecycle.ViewModelProviders;
import butterknife.ButterKnife;
import dagger.android.AndroidInjector;
import dagger.android.DispatchingAndroidInjector;
import dagger.android.support.HasSupportFragmentInjector;
import no.nordicsemi.android.nrfmeshprovisioner.di.Injectable;
+import no.nordicsemi.android.nrfmeshprovisioner.utils.Utils;
+import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.SharedViewModel;
public class MainActivity extends AppCompatActivity implements Injectable,
HasSupportFragmentInjector,
BottomNavigationView.OnNavigationItemSelectedListener,
BottomNavigationView.OnNavigationItemReselectedListener {
- private static final int TAB_COUNT = 3;
private static final String CURRENT_FRAGMENT = "CURRENT_FRAGMENT";
@Inject
@@ -58,49 +60,68 @@ public class MainActivity extends AppCompatActivity implements Injectable,
@Inject
ViewModelProvider.Factory mViewModelFactory;
- private BottomNavigationView mBottomNavigationView;
-
private NetworkFragment mNetworkFragment;
private GroupsFragment mGroupsFragment;
+ private ProxyFilterFragment mProxyFilterFragment;
private Fragment mSettingsFragment;
+ private SharedViewModel mViewModel;
@Override
protected void onCreate(@Nullable final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
+ mViewModel = ViewModelProviders.of(this).get(SharedViewModel.class);
ButterKnife.bind(this);
final Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
+ //noinspection ConstantConditions
getSupportActionBar().setTitle(R.string.app_name);
mNetworkFragment = (NetworkFragment) getSupportFragmentManager().findFragmentById(R.id.fragment_network);
mGroupsFragment = (GroupsFragment) getSupportFragmentManager().findFragmentById(R.id.fragment_groups);
+ mProxyFilterFragment = (ProxyFilterFragment) getSupportFragmentManager().findFragmentById(R.id.fragment_proxy);
mSettingsFragment = getSupportFragmentManager().findFragmentById(R.id.fragment_settings);
- mBottomNavigationView = findViewById(R.id.bottom_navigation_view);
+ final BottomNavigationView bottomNavigationView = findViewById(R.id.bottom_navigation_view);
- mBottomNavigationView.setOnNavigationItemSelectedListener(this);
- mBottomNavigationView.setOnNavigationItemReselectedListener(this);
+ bottomNavigationView.setOnNavigationItemSelectedListener(this);
+ bottomNavigationView.setOnNavigationItemReselectedListener(this);
if (savedInstanceState == null) {
- onNavigationItemSelected(mBottomNavigationView.getMenu().findItem(R.id.action_network));
+ onNavigationItemSelected(bottomNavigationView.getMenu().findItem(R.id.action_network));
} else {
- mBottomNavigationView.setSelectedItemId(savedInstanceState.getInt(CURRENT_FRAGMENT));
+ bottomNavigationView.setSelectedItemId(savedInstanceState.getInt(CURRENT_FRAGMENT));
}
}
@Override
- public void onBackPressed() {
- if(getSupportFragmentManager().getFragments().size() > TAB_COUNT) {
- getSupportFragmentManager().popBackStack();
+ public boolean onCreateOptionsMenu(final Menu menu) {
+ final Boolean isConnectedToNetwork = mViewModel.isConnectedToProxy().getValue();
+ if (isConnectedToNetwork != null && isConnectedToNetwork) {
+ getMenuInflater().inflate(R.menu.disconnect, menu);
} else {
- super.onBackPressed();
+ getMenuInflater().inflate(R.menu.connect, menu);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(final MenuItem item) {
+ final int id = item.getItemId();
+ switch (id) {
+ case R.id.action_connect:
+ mViewModel.navigateToScannerActivity(this, false, Utils.CONNECT_TO_NETWORK, false);
+ return true;
+ case R.id.action_disconnect:
+ mViewModel.disconnect();
+ return true;
}
+ return false;
}
@Override
- protected void onDestroy() {
- super.onDestroy();
+ public void onBackPressed() {
+ super.onBackPressed();
}
@Override
@@ -114,13 +135,16 @@ public boolean onNavigationItemSelected(@NonNull MenuItem item) {
final FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
switch (id) {
case R.id.action_network:
- ft.show(mNetworkFragment).hide(mGroupsFragment).hide(mSettingsFragment);
+ ft.show(mNetworkFragment).hide(mGroupsFragment).hide(mProxyFilterFragment).hide(mSettingsFragment);
+ break;
+ case R.id.action_groups:
+ ft.hide(mNetworkFragment).show(mGroupsFragment).hide(mProxyFilterFragment).hide(mSettingsFragment);
break;
- case R.id.action_scanner:
- ft.hide(mNetworkFragment).show(mGroupsFragment).hide(mSettingsFragment);
+ case R.id.action_proxy:
+ ft.hide(mNetworkFragment).hide(mGroupsFragment).show(mProxyFilterFragment).hide(mSettingsFragment);
break;
case R.id.action_settings:
- ft.hide(mNetworkFragment).hide(mGroupsFragment).show(mSettingsFragment);
+ ft.hide(mNetworkFragment).hide(mGroupsFragment).hide(mProxyFilterFragment).show(mSettingsFragment);
break;
}
ft.commit();
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/ManageAppKeysActivity.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/ManageAppKeysActivity.java
deleted file mode 100644
index 6831a85f4..000000000
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/ManageAppKeysActivity.java
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * Copyright (c) 2018, Nordic Semiconductor
- * 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 no.nordicsemi.android.nrfmeshprovisioner;
-
-import android.app.Activity;
-import android.arch.lifecycle.ViewModelProvider;
-import android.arch.lifecycle.ViewModelProviders;
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.annotation.Nullable;
-import android.support.design.widget.FloatingActionButton;
-import android.support.design.widget.Snackbar;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.DefaultItemAnimator;
-import android.support.v7.widget.DividerItemDecoration;
-import android.support.v7.widget.LinearLayoutManager;
-import android.support.v7.widget.RecyclerView;
-import android.support.v7.widget.Toolbar;
-import android.support.v7.widget.helper.ItemTouchHelper;
-import android.view.MenuItem;
-import android.view.View;
-import android.widget.TextView;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.inject.Inject;
-
-import butterknife.BindView;
-import butterknife.ButterKnife;
-import no.nordicsemi.android.meshprovisioner.transport.ApplicationKey;
-import no.nordicsemi.android.meshprovisioner.transport.ProvisionedMeshNode;
-import no.nordicsemi.android.nrfmeshprovisioner.adapter.ManageAppKeyAdapter;
-import no.nordicsemi.android.nrfmeshprovisioner.di.Injectable;
-import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentAddAppKey;
-import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentEditAppKey;
-import no.nordicsemi.android.nrfmeshprovisioner.utils.Utils;
-import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.ManageAppKeysViewModel;
-import no.nordicsemi.android.nrfmeshprovisioner.widgets.ItemTouchHelperAdapter;
-import no.nordicsemi.android.nrfmeshprovisioner.widgets.RemovableItemTouchHelperCallback;
-import no.nordicsemi.android.nrfmeshprovisioner.widgets.RemovableViewHolder;
-
-public class ManageAppKeysActivity extends AppCompatActivity implements Injectable, ManageAppKeyAdapter.OnItemClickListener,
- DialogFragmentAddAppKey.DialogFragmentAddAppKeysListener,
- DialogFragmentEditAppKey.DialogFragmentEditAppKeysListener,
- ItemTouchHelperAdapter {
-
- public static final String RESULT_APP_KEY = "RESULT_APP_KEY";
- public static final String RESULT_APP_KEY_INDEX = "RESULT_APP_KEY_INDEX";
- public static final String RESULT_APP_KEY_LIST_SIZE = "RESULT_APP_KEY_LIST_SIZE";
- public static final String APP_KEYS = "APP_KEYS";
- public static final int SELECT_APP_KEY = 2011; //Random number
- public static final int MANAGE_APP_KEYS = 2012; //Random number
- private static final String MAIN_ACTIVITY = ".MainActivity";
-
- @Inject
- ViewModelProvider.Factory mViewModelFactory;
-
- //UI Bindings
- @BindView(android.R.id.empty)
- View mEmptyView;
- @BindView(R.id.container)
- View container;
-
- private ManageAppKeysViewModel mViewModel;
- private ManageAppKeyAdapter mAdapter;
-
- @Override
- protected void onCreate(@Nullable final Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_manage_app_keys);
- mViewModel = ViewModelProviders.of(this, mViewModelFactory).get(ManageAppKeysViewModel.class);
-
- //Bind ui
- ButterKnife.bind(this);
-
- final Toolbar toolbar = findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
- final FloatingActionButton fab = findViewById(R.id.fab);
-
- getSupportActionBar().setDisplayHomeAsUpEnabled(true);
- final RecyclerView appKeysRecyclerView = findViewById(R.id.recycler_view_app_keys);
- appKeysRecyclerView.setLayoutManager(new LinearLayoutManager(this));
- final DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(appKeysRecyclerView.getContext(), DividerItemDecoration.VERTICAL);
- appKeysRecyclerView.addItemDecoration(dividerItemDecoration);
- appKeysRecyclerView.setItemAnimator(new DefaultItemAnimator());
-
- //noinspection ConstantConditions
- switch (getIntent().getExtras().getInt(Utils.EXTRA_DATA)) {
- case Utils.MANAGE_APP_KEY:
- getSupportActionBar().setTitle(R.string.title_manage_app_keys);
- final ItemTouchHelper.Callback itemTouchHelperCallback = new RemovableItemTouchHelperCallback(this);
- final ItemTouchHelper itemTouchHelper = new ItemTouchHelper(itemTouchHelperCallback);
- itemTouchHelper.attachToRecyclerView(appKeysRecyclerView);
- mAdapter = new ManageAppKeyAdapter(this, mViewModel.getMeshNetworkLiveData());
- mAdapter.setOnItemClickListener(this);
- appKeysRecyclerView.setAdapter(mAdapter);
- setUpObserver();
- break;
- case Utils.ADD_APP_KEY:
- getSupportActionBar().setTitle(R.string.title_select_app_key);
- fab.hide();
- mAdapter = new ManageAppKeyAdapter(this, mViewModel.getMeshNetworkLiveData());
- mAdapter.setOnItemClickListener(this);
- appKeysRecyclerView.setAdapter(mAdapter);
- setUpObserver();
- break;
- case Utils.BIND_APP_KEY:
- case Utils.PUBLICATION_APP_KEY:
- getSupportActionBar().setTitle(R.string.title_select_app_key);
- fab.hide();
- //Get selected mesh node
- final ProvisionedMeshNode node = mViewModel.getSelectedMeshNode().getValue();
- if (node != null) {
- final List applicationKeys = new ArrayList<>(node.getAddedApplicationKeys().values());
- if (!applicationKeys.isEmpty()) {
- mAdapter = new ManageAppKeyAdapter(this, applicationKeys);
- mAdapter.setOnItemClickListener(this);
- appKeysRecyclerView.setAdapter(mAdapter);
- } else {
- final TextView textView = mEmptyView.findViewById(R.id.rationale);
- textView.setText(R.string.no_added_app_keys_rationale);
- mEmptyView.setVisibility(View.VISIBLE);
- }
- }
- break;
- }
-
- fab.setOnClickListener(v -> {
- final DialogFragmentAddAppKey dialogFragmentAddAppKey = DialogFragmentAddAppKey.newInstance(null);
- dialogFragmentAddAppKey.show(getSupportFragmentManager(), null);
- });
- }
-
- @Override
- public boolean onOptionsItemSelected(final MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- }
- return false;
- }
-
- @Override
- public void onBackPressed() {
- final int extras = getIntent().getExtras().getInt(Utils.EXTRA_DATA);
- switch (extras) {
- case Utils.MANAGE_APP_KEY:
- Intent returnIntent = new Intent();
- returnIntent.putExtra(RESULT_APP_KEY_LIST_SIZE, mAdapter.getItemCount());
- setResult(Activity.RESULT_OK, returnIntent);
- finish();
- break;
- default:
- super.onBackPressed();
- break;
- }
- }
-
- @Override
- public void onItemClick(final int position, final ApplicationKey appKey) {
- final int extras = getIntent().getExtras().getInt(Utils.EXTRA_DATA);
- switch (extras) {
- case Utils.MANAGE_APP_KEY:
- final DialogFragmentEditAppKey dialogFragmentEditAppKey = DialogFragmentEditAppKey.newInstance(position, appKey);
- dialogFragmentEditAppKey.show(getSupportFragmentManager(), null);
- break;
- default:
- Intent returnIntent = new Intent();
- returnIntent.putExtra(RESULT_APP_KEY_INDEX, position);
- returnIntent.putExtra(RESULT_APP_KEY, appKey);
- setResult(Activity.RESULT_OK, returnIntent);
- finish();
- break;
- }
- }
-
- @Override
- public void onAppKeysUpdated(final int position, final String appKey) {
- mViewModel.getMeshNetworkLiveData().updateAppKey(position, appKey);
- }
-
- @Override
- public void onAppKeyAdded(final String appKey) {
- mViewModel.getMeshNetworkLiveData().addAppKey(appKey);
- }
-
- @Override
- public void onItemDismiss(final RemovableViewHolder viewHolder) {
- final ApplicationKey key = (ApplicationKey) viewHolder.getSwipeableView().getTag();
- mViewModel.getMeshNetworkLiveData().removeAppKey(key);
- displaySnackBar(viewHolder.getAdapterPosition(), key);
- // Show the empty view
- final boolean empty = mAdapter.getItemCount() == 0;
- if (empty) {
- mEmptyView.setVisibility(View.VISIBLE);
- }
- }
-
- @Override
- public void onItemDismissFailed(final RemovableViewHolder viewHolder) {
-
- }
-
- private void setUpObserver() {
- mViewModel.getMeshNetworkLiveData().observe(this, networkLiveData -> {
- if (networkLiveData != null) {
- final List keys = networkLiveData.getAppKeys();
- if (keys != null) {
- mEmptyView.setVisibility(keys.isEmpty() ? View.VISIBLE : View.GONE);
- }
- }
- });
- }
-
- private void displaySnackBar(final int key, final ApplicationKey appKey) {
-
- Snackbar.make(container, getString(R.string.app_key_deleted), Snackbar.LENGTH_LONG)
- .setAction(getString(R.string.undo), view -> {
- mEmptyView.setVisibility(View.INVISIBLE);
- mViewModel.getMeshNetworkLiveData().addAppKey(appKey);
- })
- .setActionTextColor(getResources().getColor(R.color.colorPrimaryDark))
- .show();
- }
-}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/NetworkFragment.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/NetworkFragment.java
index aa22cf56a..842e7e430 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/NetworkFragment.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/NetworkFragment.java
@@ -22,158 +22,200 @@
package no.nordicsemi.android.nrfmeshprovisioner;
-import android.arch.lifecycle.ViewModelProvider;
-import android.arch.lifecycle.ViewModelProviders;
+import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.design.widget.FloatingActionButton;
-import android.support.design.widget.Snackbar;
-import android.support.v4.app.Fragment;
-import android.support.v7.widget.DividerItemDecoration;
-import android.support.v7.widget.LinearLayoutManager;
-import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
+import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton;
+import com.google.android.material.snackbar.Snackbar;
+
import javax.inject.Inject;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.coordinatorlayout.widget.CoordinatorLayout;
+import androidx.fragment.app.Fragment;
+import androidx.lifecycle.ViewModelProvider;
+import androidx.lifecycle.ViewModelProviders;
+import androidx.recyclerview.widget.DividerItemDecoration;
+import androidx.recyclerview.widget.ItemTouchHelper;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
import butterknife.BindView;
import butterknife.ButterKnife;
import no.nordicsemi.android.meshprovisioner.transport.ProvisionedMeshNode;
-import no.nordicsemi.android.nrfmeshprovisioner.adapter.NodeAdapter;
+import no.nordicsemi.android.nrfmeshprovisioner.ble.ScannerActivity;
import no.nordicsemi.android.nrfmeshprovisioner.di.Injectable;
-import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentConfigError;
+import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentError;
+import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentDeleteNode;
+import no.nordicsemi.android.nrfmeshprovisioner.node.NodeConfigurationActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.node.adapter.NodeAdapter;
import no.nordicsemi.android.nrfmeshprovisioner.utils.Utils;
import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.SharedViewModel;
+import no.nordicsemi.android.nrfmeshprovisioner.widgets.ItemTouchHelperAdapter;
+import no.nordicsemi.android.nrfmeshprovisioner.widgets.RemovableItemTouchHelperCallback;
+import no.nordicsemi.android.nrfmeshprovisioner.widgets.RemovableViewHolder;
import static android.app.Activity.RESULT_OK;
public class NetworkFragment extends Fragment implements Injectable,
- NodeAdapter.OnItemClickListener {
+ NodeAdapter.OnItemClickListener,
+ ItemTouchHelperAdapter,
+ DialogFragmentDeleteNode.DialogFragmentDeleteNodeListener {
- private static final String TAG_SCANNER_FRAGMENT = "SCANNER_FRAGMENT";
private SharedViewModel mViewModel;
@Inject
ViewModelProvider.Factory mViewModelFactory;
- @BindView(R.id.main_content)
- View container;
+ @BindView(R.id.container)
+ CoordinatorLayout container;
@BindView(R.id.recycler_view_provisioned_nodes)
RecyclerView mRecyclerViewNodes;
-
- private NodeAdapter mAdapter;
-
- @Override
- public void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setHasOptionsMenu(true);
- }
+ private NodeAdapter mNodeAdapter;
@Nullable
@Override
public View onCreateView(@NonNull final LayoutInflater inflater, @Nullable final ViewGroup container, @Nullable final Bundle savedInstanceState) {
- final View rootView = inflater.inflate(R.layout.fragment_network, null);
+ @SuppressLint("InflateParams") final View rootView = inflater.inflate(R.layout.fragment_network, null);
+ mViewModel = ViewModelProviders.of(requireActivity(), mViewModelFactory).get(SharedViewModel.class);
ButterKnife.bind(this, rootView);
- final FloatingActionButton fab = rootView.findViewById(R.id.fab_add_node);
+ final ExtendedFloatingActionButton fab = rootView.findViewById(R.id.fab_add_node);
final View noNetworksConfiguredView = rootView.findViewById(R.id.no_networks_configured);
- mViewModel = ViewModelProviders.of(requireActivity(), mViewModelFactory).get(SharedViewModel.class);
-
// Configure the recycler view
- mAdapter = new NodeAdapter(getActivity(), mViewModel.getProvisionedNodes());
- mAdapter.setOnItemClickListener(this);
+ mNodeAdapter = new NodeAdapter(requireContext(), mViewModel.getNodes());
+ mNodeAdapter.setOnItemClickListener(this);
mRecyclerViewNodes.setLayoutManager(new LinearLayoutManager(getContext()));
final DividerItemDecoration decoration = new DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL);
mRecyclerViewNodes.addItemDecoration(decoration);
- mRecyclerViewNodes.setAdapter(mAdapter);
+ final ItemTouchHelper.Callback itemTouchHelperCallback = new RemovableItemTouchHelperCallback(this);
+ final ItemTouchHelper itemTouchHelper = new ItemTouchHelper(itemTouchHelperCallback);
+ itemTouchHelper.attachToRecyclerView(mRecyclerViewNodes);
+ mRecyclerViewNodes.setAdapter(mNodeAdapter);
// Create view model containing utility methods for scanning
- mViewModel.getProvisionedNodes().observe(this, nodes -> {
- if (!nodes.isEmpty()) {
+ mViewModel.getNodes().observe(this, nodes -> {
+ if (nodes != null && !nodes.isEmpty()) {
noNetworksConfiguredView.setVisibility(View.GONE);
} else {
noNetworksConfiguredView.setVisibility(View.VISIBLE);
}
- mAdapter.notifyDataSetChanged();
+ requireActivity().invalidateOptionsMenu();
});
- mViewModel.getProvisionedNodes().observe(this, provisionedNodes -> requireActivity().invalidateOptionsMenu());
-
mViewModel.isConnectedToProxy().observe(this, isConnected -> {
if (isConnected != null) {
requireActivity().invalidateOptionsMenu();
}
});
- mViewModel.getConnectedMeshNodeAddress().observe(this, unicastAddress -> mAdapter.selectConnectedMeshNode(unicastAddress));
+ mRecyclerViewNodes.addOnScrollListener(new RecyclerView.OnScrollListener() {
+ @Override
+ public void onScrolled(@NonNull final RecyclerView recyclerView, final int dx, final int dy) {
+ super.onScrolled(recyclerView, dx, dy);
+ final LinearLayoutManager m = (LinearLayoutManager) recyclerView.getLayoutManager();
+ if (m != null) {
+ if (m.findFirstCompletelyVisibleItemPosition() == 0) {
+ fab.extend(true);
+ } else {
+ fab.shrink(true);
+ }
+ }
+ }
+ });
fab.setOnClickListener(v -> {
- final Intent intent = new Intent(requireActivity(), ScannerActivity.class);
+ final Intent intent = new Intent(requireContext(), ScannerActivity.class);
intent.putExtra(Utils.EXTRA_DATA_PROVISIONING_SERVICE, true);
startActivityForResult(intent, Utils.PROVISIONING_SUCCESS);
});
return rootView;
+ }
+ @Override
+ public void onActivityResult(final int requestCode, final int resultCode, @Nullable final Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ handleActivityResult(requestCode, resultCode, data);
}
@Override
- public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
- if (mViewModel.getProvisionedNodes().getValue() != null && !mViewModel.getProvisionedNodes().getValue().isEmpty()) {
- final Boolean isConnectedToNetwork = mViewModel.isConnectedToProxy().getValue();
- if (isConnectedToNetwork != null && isConnectedToNetwork) {
- inflater.inflate(R.menu.disconnect, menu);
- } else {
- inflater.inflate(R.menu.connect, menu);
- }
+ public void onConfigureClicked(final ProvisionedMeshNode node) {
+ mViewModel.setSelectedMeshNode(node);
+ final Intent meshConfigurationIntent = new Intent(getActivity(), NodeConfigurationActivity.class);
+ requireActivity().startActivity(meshConfigurationIntent);
+ }
+
+ @Override
+ public void onItemDismiss(final RemovableViewHolder viewHolder) {
+ final int position = viewHolder.getAdapterPosition();
+ if (!mNodeAdapter.isEmpty()) {
+ final DialogFragmentDeleteNode fragmentDeleteNode = DialogFragmentDeleteNode.newInstance(position);
+ fragmentDeleteNode.show(getChildFragmentManager(), null);
}
}
@Override
- public boolean onOptionsItemSelected(final MenuItem item) {
- final int id = item.getItemId();
- switch (id) {
- case R.id.action_connect:
- final Intent intent = new Intent(requireActivity(), ScannerActivity.class);
- intent.putExtra(Utils.EXTRA_DATA_PROVISIONING_SERVICE, false);
- startActivityForResult(intent, Utils.CONNECT_TO_NETWORK);
- return true;
- case R.id.action_disconnect:
- mViewModel.disconnect();
- return true;
+ public void onItemDismissFailed(final RemovableViewHolder viewHolder) {
+ //Do nothing
+ }
+
+ @Override
+ public void onNodeDeleteConfirmed(final int position) {
+ final ProvisionedMeshNode node = mNodeAdapter.getItem(position);
+ if (mViewModel.getNetworkLiveData().getMeshNetwork().deleteNode(node)) {
+ mViewModel.displaySnackBar(requireActivity(), container, getString(R.string.node_deleted), Snackbar.LENGTH_LONG);
}
- return false;
}
@Override
- public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
+ public void onNodeDeleteCancelled(final int position) {
+ mNodeAdapter.notifyItemChanged(position);
+ }
+
+ private void handleActivityResult(final int requestCode, final int resultCode, @NonNull final Intent data) {
if (requestCode == Utils.PROVISIONING_SUCCESS) {
if (resultCode == RESULT_OK) {
final boolean provisioningSuccess = data.getBooleanExtra(Utils.PROVISIONING_COMPLETED, false);
+ final DialogFragmentError fragmentConfigError;
if (provisioningSuccess) {
- final boolean compositionDataReceived = data.getBooleanExtra(Utils.COMPOSITION_DATA_COMPLETED, false);
- final boolean appKeyAddCompleted = data.getBooleanExtra(Utils.APP_KEY_ADD_COMPLETED, false);
- final DialogFragmentConfigError fragmentConfigError;
- if(compositionDataReceived){
- if(!appKeyAddCompleted){
- fragmentConfigError =
- DialogFragmentConfigError.newInstance(getString(R.string.title_init_config_error)
- , getString(R.string.init_config_error_app_key_msg));
- fragmentConfigError.show(getChildFragmentManager(), null);
- }
- } else {
+ final boolean provisionerUnassigned = data.getBooleanExtra(Utils.PROVISIONER_UNASSIGNED, false);
+ if (provisionerUnassigned) {
fragmentConfigError =
- DialogFragmentConfigError.newInstance(getString(R.string.title_init_config_error)
- , getString(R.string.init_config_error_all));
+ DialogFragmentError.newInstance(getString(R.string.title_init_config_error)
+ , getString(R.string.provisioner_unassigned_msg));
fragmentConfigError.show(getChildFragmentManager(), null);
+ } else {
+ final boolean compositionDataReceived = data.getBooleanExtra(Utils.COMPOSITION_DATA_COMPLETED, false);
+ final boolean defaultTtlGetCompleted = data.getBooleanExtra(Utils.DEFAULT_GET_COMPLETED, false);
+ final boolean appKeyAddCompleted = data.getBooleanExtra(Utils.APP_KEY_ADD_COMPLETED, false);
+ final boolean networkRetransmitSetCompleted = data.getBooleanExtra(Utils.NETWORK_TRANSMIT_SET_COMPLETED, false);
+ final String title = getString(R.string.title_init_config_error);
+ final String message;
+ if (compositionDataReceived) {
+ if (defaultTtlGetCompleted) {
+ if (appKeyAddCompleted) {
+ if (!networkRetransmitSetCompleted) {
+ message = getString(R.string.init_config_error_app_key_msg);
+ showErrorDialog(title, message);
+ }
+ } else {
+ message = getString(R.string.init_config_error_app_key_msg);
+ showErrorDialog(title, message);
+ }
+ } else {
+ message = getString(R.string.init_config_error_default_ttl_get_msg);
+ showErrorDialog(title, message);
+ }
+ } else {
+ message = getString(R.string.init_config_error_all);
+ showErrorDialog(title, message);
+ }
}
}
requireActivity().invalidateOptionsMenu();
@@ -181,29 +223,8 @@ public void onActivityResult(final int requestCode, final int resultCode, final
}
}
- @Override
- public void onConfigureClicked(final ProvisionedMeshNode node) {
- final Boolean isConnectedToProxy = mViewModel.isConnectedToProxy().getValue();
- if (isConnectedToProxy != null && isConnectedToProxy) {
- mViewModel.setSelectedMeshNode(node);
- final Intent meshConfigurationIntent = new Intent(getActivity(), NodeConfigurationActivity.class);
- requireActivity().startActivity(meshConfigurationIntent);
- } else {
- displaySnackBar(getString(R.string.disconnected_network_rationale));
- }
- }
-
- @Override
- public void onDetailsClicked(final ProvisionedMeshNode node) {
- final Intent meshConfigurationIntent = new Intent(getActivity(), NodeDetailsActivity.class);
- meshConfigurationIntent.putExtra(Utils.EXTRA_DEVICE, node);
- requireActivity().startActivity(meshConfigurationIntent);
- }
-
-
- private void displaySnackBar(final String message){
- Snackbar.make(container, message, Snackbar.LENGTH_LONG)
- .setActionTextColor(getResources().getColor(R.color.colorPrimaryDark ))
- .show();
+ private void showErrorDialog(@NonNull final String title, @NonNull final String message) {
+ final DialogFragmentError dialogFragmentError = DialogFragmentError.newInstance(title, message);
+ dialogFragmentError.show(getChildFragmentManager(), null);
}
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/NodeConfigurationActivity.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/NodeConfigurationActivity.java
deleted file mode 100644
index 07711cb38..000000000
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/NodeConfigurationActivity.java
+++ /dev/null
@@ -1,570 +0,0 @@
-/*
- * Copyright (c) 2018, Nordic Semiconductor
- * 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 no.nordicsemi.android.nrfmeshprovisioner;
-
-import android.arch.lifecycle.ViewModelProvider;
-import android.arch.lifecycle.ViewModelProviders;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.Handler;
-import android.support.v4.widget.NestedScrollView;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.CardView;
-import android.support.v7.widget.DefaultItemAnimator;
-import android.support.v7.widget.LinearLayoutManager;
-import android.support.v7.widget.RecyclerView;
-import android.support.v7.widget.Toolbar;
-import android.support.v7.widget.helper.ItemTouchHelper;
-import android.util.Log;
-import android.view.MenuItem;
-import android.view.View;
-import android.widget.Button;
-import android.widget.ProgressBar;
-import android.widget.Switch;
-import android.widget.TextView;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.inject.Inject;
-
-import butterknife.BindView;
-import butterknife.ButterKnife;
-import no.nordicsemi.android.meshprovisioner.models.ConfigurationServerModel;
-import no.nordicsemi.android.meshprovisioner.models.GenericLevelServerModel;
-import no.nordicsemi.android.meshprovisioner.models.GenericOnOffServerModel;
-import no.nordicsemi.android.meshprovisioner.models.VendorModel;
-import no.nordicsemi.android.meshprovisioner.transport.ApplicationKey;
-import no.nordicsemi.android.meshprovisioner.transport.ConfigAppKeyAdd;
-import no.nordicsemi.android.meshprovisioner.transport.ConfigAppKeyStatus;
-import no.nordicsemi.android.meshprovisioner.transport.ConfigCompositionDataGet;
-import no.nordicsemi.android.meshprovisioner.transport.ConfigCompositionDataStatus;
-import no.nordicsemi.android.meshprovisioner.transport.ConfigNodeReset;
-import no.nordicsemi.android.meshprovisioner.transport.ConfigNodeResetStatus;
-import no.nordicsemi.android.meshprovisioner.transport.ConfigProxyGet;
-import no.nordicsemi.android.meshprovisioner.transport.ConfigProxySet;
-import no.nordicsemi.android.meshprovisioner.transport.ConfigProxyStatus;
-import no.nordicsemi.android.meshprovisioner.transport.Element;
-import no.nordicsemi.android.meshprovisioner.transport.MeshMessage;
-import no.nordicsemi.android.meshprovisioner.transport.MeshModel;
-import no.nordicsemi.android.meshprovisioner.transport.NetworkKey;
-import no.nordicsemi.android.meshprovisioner.transport.ProvisionedMeshNode;
-import no.nordicsemi.android.meshprovisioner.transport.ProxyConfigAddAddressToFilter;
-import no.nordicsemi.android.meshprovisioner.transport.ProxyConfigFilterStatus;
-import no.nordicsemi.android.meshprovisioner.transport.ProxyConfigRemoveAddressFromFilter;
-import no.nordicsemi.android.meshprovisioner.transport.ProxyConfigSetFilterType;
-import no.nordicsemi.android.meshprovisioner.utils.AddressArray;
-import no.nordicsemi.android.meshprovisioner.utils.MeshAddress;
-import no.nordicsemi.android.meshprovisioner.utils.ProxyFilter;
-import no.nordicsemi.android.meshprovisioner.utils.ProxyFilterType;
-import no.nordicsemi.android.nrfmeshprovisioner.adapter.AddedAppKeyAdapter;
-import no.nordicsemi.android.nrfmeshprovisioner.adapter.ElementAdapter;
-import no.nordicsemi.android.nrfmeshprovisioner.adapter.FilterAddressAdapter;
-import no.nordicsemi.android.nrfmeshprovisioner.di.Injectable;
-import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentAppKeyAddStatus;
-import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentFilterAddAddress;
-import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentProxySet;
-import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentResetNode;
-import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentTransactionStatus;
-import no.nordicsemi.android.nrfmeshprovisioner.utils.Utils;
-import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.NodeConfigurationViewModel;
-import no.nordicsemi.android.nrfmeshprovisioner.widgets.ItemTouchHelperAdapter;
-import no.nordicsemi.android.nrfmeshprovisioner.widgets.RemovableItemTouchHelperCallback;
-import no.nordicsemi.android.nrfmeshprovisioner.widgets.RemovableViewHolder;
-
-public class NodeConfigurationActivity extends AppCompatActivity implements Injectable,
- ElementAdapter.OnItemClickListener,
- DialogFragmentAppKeyAddStatus.DialogFragmentAppKeyAddStatusListener,
- DialogFragmentProxySet.DialogFragmentProxySetListener,
- DialogFragmentFilterAddAddress.DialogFragmentFilterAddressListener,
- DialogFragmentResetNode.DialogFragmentNodeResetListener,
- AddedAppKeyAdapter.OnItemClickListener,
- ItemTouchHelperAdapter {
-
- private final static String TAG = NodeConfigurationActivity.class.getSimpleName();
- private static final String PROGRESS_BAR_STATE = "PROGRESS_BAR_STATE";
- private static final String PROXY_STATE = "PROXY_STATE";
- private static final String REQUESTED_PROXY_STATE = "REQUESTED_PROXY_STATE";
- private static final String DIALOG_FRAGMENT_APP_KEY_STATUS = "DIALOG_FRAGMENT_APP_KEY_STATUS";
-
- @Inject
- ViewModelProvider.Factory mViewModelFactory;
-
- @BindView(R.id.main_container)
- NestedScrollView mContainer;
- @BindView(R.id.action_get_compostion_data)
- Button actionGetCompositionData;
- @BindView(R.id.action_add_app_keys)
- Button actionAddAppkey;
- @BindView(R.id.node_proxy_state_card)
- View mProxyStateCard;
- @BindView(R.id.proxy_state_summary)
- TextView mProxyStateRationaleSummary;
- @BindView(R.id.action_get_proxy_state)
- Button actionGetProxyState;
- @BindView(R.id.action_set_proxy_state)
- Button actionSetProxyState;
- @BindView(R.id.filter_switch)
- Switch actionSwitchFilter;
- @BindView(R.id.action_add_address)
- Button actionAddFilterAddress;
- @BindView(R.id.action_clear_addresses)
- Button actionClearFilterAddress;
- @BindView(R.id.action_reset_node)
- Button actionResetNode;
- @BindView(R.id.recycler_view_elements)
- RecyclerView mRecyclerViewElements;
- @BindView(R.id.composition_data_card)
- CardView mCompositionDataCard;
- @BindView(R.id.proxy_filter_card)
- CardView mProxyFilterCard;
- @BindView(R.id.configuration_progress_bar)
- ProgressBar mProgressbar;
-
- private NodeConfigurationViewModel mViewModel;
- private Handler mHandler;
- private boolean mProxyState;
- private boolean mRequestedState = true;
-
-
- private final Runnable mOperationTimeout = this::hideProgressBar;
-
- @Override
- protected void onCreate(final Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_mesh_node_configuration);
- ButterKnife.bind(this);
- mViewModel = ViewModelProviders.of(this, mViewModelFactory).get(NodeConfigurationViewModel.class);
-
- if (savedInstanceState != null) {
- if (savedInstanceState.getBoolean(PROGRESS_BAR_STATE)) {
- mProgressbar.setVisibility(View.VISIBLE);
- disableClickableViews();
- } else {
- mProgressbar.setVisibility(View.INVISIBLE);
- enableClickableViews();
- }
- mRequestedState = savedInstanceState.getBoolean(PROXY_STATE, true);
- mProxyState = savedInstanceState.getBoolean(PROXY_STATE, true);
- }
-
- mHandler = new Handler();
- // Set up views
- final Toolbar toolbar = findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
- getSupportActionBar().setDisplayHomeAsUpEnabled(true);
- getSupportActionBar().setTitle(R.string.title_node_configuration);
- getSupportActionBar().setSubtitle(mViewModel.getSelectedMeshNode().getValue().getNodeName());
-
- final TextView noElementsFound = findViewById(R.id.no_elements);
- final TextView noAppKeysFound = findViewById(R.id.no_app_keys);
- final View compositionActionContainer = findViewById(R.id.composition_action_container);
- mRecyclerViewElements.setLayoutManager(new LinearLayoutManager(this));
- final ElementAdapter adapter = new ElementAdapter(this, mViewModel.getSelectedMeshNode());
- adapter.setHasStableIds(true);
- adapter.setOnItemClickListener(this);
- mRecyclerViewElements.setAdapter(adapter);
-
- final RecyclerView recyclerViewAppKeys = findViewById(R.id.recycler_view_app_keys);
- recyclerViewAppKeys.setLayoutManager(new LinearLayoutManager(this));
- recyclerViewAppKeys.setItemAnimator(new DefaultItemAnimator());
- final AddedAppKeyAdapter appKeyAdapter = new AddedAppKeyAdapter(this, mViewModel.getSelectedMeshNode());
- recyclerViewAppKeys.setAdapter(appKeyAdapter);
-
- final TextView noAddressesAdded = findViewById(R.id.no_addresses);
- final RecyclerView recyclerViewAddresses = findViewById(R.id.recycler_view_addresses);
-
- final Integer unicast = mViewModel.getConnectedMeshNodeAddress().getValue();
- if (unicast != null && unicast == mViewModel.getSelectedMeshNode().getValue().getUnicastAddress()) {
- mProxyFilterCard.setVisibility(View.VISIBLE);
- recyclerViewAddresses.setLayoutManager(new LinearLayoutManager(this));
- recyclerViewAddresses.setItemAnimator(new DefaultItemAnimator());
- final ItemTouchHelper.Callback itemTouchHelperCallback = new RemovableItemTouchHelperCallback(this);
- final ItemTouchHelper itemTouchHelper = new ItemTouchHelper(itemTouchHelperCallback);
- itemTouchHelper.attachToRecyclerView(recyclerViewAddresses);
- final FilterAddressAdapter addressAdapter = new FilterAddressAdapter(this, mViewModel.getSelectedMeshNode());
- recyclerViewAddresses.setAdapter(addressAdapter);
- }
-
- mViewModel.getSelectedMeshNode().observe(this, meshNode -> {
- if (meshNode == null) {
- finish();
- return;
- }
-
- if (!meshNode.getElements().isEmpty()) {
- compositionActionContainer.setVisibility(View.GONE);
- noElementsFound.setVisibility(View.INVISIBLE);
- mRecyclerViewElements.setVisibility(View.VISIBLE);
- } else {
- noElementsFound.setVisibility(View.VISIBLE);
- compositionActionContainer.setVisibility(View.VISIBLE);
- mRecyclerViewElements.setVisibility(View.INVISIBLE);
- }
-
- if (!meshNode.getAddedApplicationKeys().isEmpty()) {
- noAppKeysFound.setVisibility(View.GONE);
- recyclerViewAppKeys.setVisibility(View.VISIBLE);
- } else {
- noAppKeysFound.setVisibility(View.VISIBLE);
- recyclerViewAppKeys.setVisibility(View.GONE);
- }
- final ProxyFilter filter = meshNode.getProxyFilter();
- if (filter != null) {
- actionSwitchFilter.setChecked(filter.getFilterType().getType() == ProxyFilterType.WHITE_LIST_FILTER);
- if (!filter.getAddresses().isEmpty()) {
- noAddressesAdded.setVisibility(View.GONE);
- recyclerViewAddresses.setVisibility(View.VISIBLE);
- actionClearFilterAddress.setVisibility(View.VISIBLE);
- } else {
- noAddressesAdded.setVisibility(View.VISIBLE);
- recyclerViewAddresses.setVisibility(View.GONE);
- actionClearFilterAddress.setVisibility(View.GONE);
- }
- }
- });
-
- actionGetCompositionData.setOnClickListener(v -> {
- final ProvisionedMeshNode node = mViewModel.getSelectedMeshNode().getValue();
- final ConfigCompositionDataGet configCompositionDataGet = new ConfigCompositionDataGet();
- mViewModel.getMeshManagerApi().sendMeshMessage(node.getUnicastAddress(), configCompositionDataGet);
- showProgressbar();
- });
-
- actionAddAppkey.setOnClickListener(v -> {
- final Intent addAppKeys = new Intent(NodeConfigurationActivity.this, ManageAppKeysActivity.class);
- addAppKeys.putExtra(Utils.EXTRA_DATA, Utils.ADD_APP_KEY);
- startActivityForResult(addAppKeys, ManageAppKeysActivity.SELECT_APP_KEY);
- });
-
- actionGetProxyState.setOnClickListener(v -> {
- final ProvisionedMeshNode node = mViewModel.getSelectedMeshNode().getValue();
- final ConfigProxyGet configProxyGet = new ConfigProxyGet();
- mViewModel.getMeshManagerApi().sendMeshMessage(node.getUnicastAddress(), configProxyGet);
- });
-
- actionSetProxyState.setOnClickListener(v -> {
- final String message;
- if (mProxyState) {
- message = getString(R.string.proxy_set_off_rationale_summary);
- } else {
- message = getString(R.string.proxy_set_on_rationale_summary);
- }
- final DialogFragmentProxySet resetNodeFragment = DialogFragmentProxySet.
- newInstance(getString(R.string.title_proxy_state_settings), message, !mProxyState);
- resetNodeFragment.show(getSupportFragmentManager(), null);
- });
-
- actionSwitchFilter.setOnClickListener(v -> {
- if (((Switch)v).isChecked()) {
- setFilter(new ProxyFilterType(ProxyFilterType.WHITE_LIST_FILTER));
- actionSwitchFilter.setText(R.string.white_list_filter);
- } else {
- setFilter(new ProxyFilterType(ProxyFilterType.BLACK_LIST_FILTER));
- actionSwitchFilter.setText(R.string.black_list_filter);
- }
- });
-
- actionAddFilterAddress.setOnClickListener(v -> {
- final ProxyFilter filter = mViewModel.getSelectedMeshNode().getValue().getProxyFilter();
- final ProxyFilterType filterType;
- if (filter == null) {
- filterType = new ProxyFilterType(ProxyFilterType.WHITE_LIST_FILTER);
- } else {
- filterType = filter.getFilterType();
- }
- final DialogFragmentFilterAddAddress filterAddAddress = DialogFragmentFilterAddAddress.newInstance(filterType);
- filterAddAddress.show(getSupportFragmentManager(), null);
- });
-
- actionClearFilterAddress.setOnClickListener(v -> removeAddresses());
-
- actionResetNode.setOnClickListener(v -> {
- final DialogFragmentResetNode resetNodeFragment = DialogFragmentResetNode.
- newInstance(getString(R.string.title_reset_node), getString(R.string.reset_node_rationale_summary));
- resetNodeFragment.show(getSupportFragmentManager(), null);
- });
-
- mViewModel.getTransactionStatus().observe(this, transactionStatus -> {
- hideProgressBar();
- final String message;
- if (transactionStatus.isIncompleteTimerExpired()) {
- message = getString(R.string.segments_not_received_timed_out);
- } else {
- message = getString(R.string.operation_timed_out);
- }
- DialogFragmentTransactionStatus fragmentMessage = DialogFragmentTransactionStatus.newInstance(getString(R.string.title_transaction_failed), message);
- fragmentMessage.show(getSupportFragmentManager(), null);
- });
-
- mViewModel.isConnectedToProxy().observe(this, isConnected -> {
- if (isConnected != null && !isConnected)
- finish();
- });
-
- mViewModel.getMeshMessageLiveData().observe(this, this::updateMeshMessage);
-
- updateProxySettingsCardUi();
- }
-
- @Override
- public boolean onOptionsItemSelected(final MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- }
- return false;
- }
-
- @Override
- protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
- if (requestCode == ManageAppKeysActivity.SELECT_APP_KEY) {
- if (resultCode == RESULT_OK) {
- final ApplicationKey appKey = data.getParcelableExtra(Utils.RESULT_APP_KEY);
- if (appKey != null) {
- showProgressbar();
- final ProvisionedMeshNode node = mViewModel.getSelectedMeshNode().getValue();
- final NetworkKey networkKey = mViewModel.getMeshManagerApi().getMeshNetwork().getPrimaryNetworkKey();
- final ConfigAppKeyAdd configAppKeyAdd = new ConfigAppKeyAdd(networkKey, appKey);
- mViewModel.getMeshManagerApi().sendMeshMessage(node.getUnicastAddress(), configAppKeyAdd);
- }
- }
- }
- }
-
- @Override
- protected void onStop() {
- super.onStop();
- if (isFinishing()) {
- mHandler.removeCallbacksAndMessages(null);
- }
- }
-
- @Override
- public void onBackPressed() {
- super.onBackPressed();
- }
-
- @Override
- protected void onSaveInstanceState(final Bundle outState) {
- super.onSaveInstanceState(outState);
- outState.putBoolean(PROGRESS_BAR_STATE, mProgressbar.getVisibility() == View.VISIBLE);
- outState.putBoolean(PROXY_STATE, mProxyState);
- outState.putBoolean(REQUESTED_PROXY_STATE, mRequestedState);
- }
-
- @Override
- public void onElementItemClick(final ProvisionedMeshNode meshNode, final Element element, final MeshModel model) {
- mViewModel.setSelectedElement(element);
- mViewModel.setSelectedModel(model);
- startActivity(model);
- }
-
- @Override
- public void onAppKeyAddStatusReceived() {
-
- }
-
- @Override
- public void onItemDismiss(final RemovableViewHolder viewHolder) {
- final int position = viewHolder.getAdapterPosition();
- if (viewHolder instanceof FilterAddressAdapter.ViewHolder) {
- removeAddress(position);
- }
- }
-
- @Override
- public void onItemDismissFailed(final RemovableViewHolder viewHolder) {
-
- }
-
- @Override
- public void onItemClick(final ApplicationKey appKey) {
-
- }
-
- @Override
- public void onNodeReset() {
- try {
- final ProvisionedMeshNode node = mViewModel.getSelectedMeshNode().getValue();
- final ConfigNodeReset configNodeReset = new ConfigNodeReset();
- mViewModel.getMeshManagerApi().sendMeshMessage(node.getUnicastAddress(), configNodeReset);
- } catch (Exception ex) {
- Log.e(TAG, ex.getMessage());
- }
- }
-
- @Override
- public void onProxySet(@ConfigProxySet.ProxyState final int state) {
- try {
- final ProvisionedMeshNode node = mViewModel.getSelectedMeshNode().getValue();
- final ConfigProxySet configProxySet = new ConfigProxySet(state);
- mViewModel.getMeshManagerApi().sendMeshMessage(node.getUnicastAddress(), configProxySet);
- mRequestedState = state == 1;
- } catch (Exception ex) {
- Log.e(TAG, ex.getMessage());
- }
- }
-
- private void updateProxySettingsCardUi() {
- final ProvisionedMeshNode meshNode = mViewModel.getSelectedMeshNode().getValue();
- if (meshNode.getNodeFeatures() != null && meshNode.getNodeFeatures().isProxyFeatureSupported()) {
- mProxyStateCard.setVisibility(View.VISIBLE);
- updateProxySettingsButtonUi();
- }
- }
-
- private void updateProxySettingsButtonUi() {
- if (mProxyState) {
- mProxyStateRationaleSummary.setText(R.string.proxy_set_off_rationale);
- actionSetProxyState.setText(R.string.action_proxy_state_set_off);
- } else {
- mProxyStateRationaleSummary.setText(R.string.proxy_set_on_rationale);
- actionSetProxyState.setText(R.string.action_proxy_state_set_on);
- }
- }
-
- private void showProgressbar() {
- disableClickableViews();
- mProgressbar.setVisibility(View.VISIBLE);
- }
-
- private void hideProgressBar() {
- mHandler.removeCallbacks(mOperationTimeout);
- enableClickableViews();
- mProgressbar.setVisibility(View.INVISIBLE);
- }
-
- private void enableClickableViews() {
- actionGetCompositionData.setEnabled(true);
- actionAddAppkey.setEnabled(true);
- actionGetProxyState.setEnabled(true);
- actionSetProxyState.setEnabled(true);
- actionSwitchFilter.setEnabled(true);
- actionAddFilterAddress.setEnabled(true);
- actionClearFilterAddress.setEnabled(true);
- actionResetNode.setEnabled(true);
- }
-
- private void disableClickableViews() {
- actionGetCompositionData.setEnabled(false);
- actionAddAppkey.setEnabled(false);
- actionGetProxyState.setEnabled(false);
- actionSetProxyState.setEnabled(false);
- actionSwitchFilter.setEnabled(false);
- actionAddFilterAddress.setEnabled(false);
- actionClearFilterAddress.setEnabled(false);
- actionResetNode.setEnabled(false);
- }
-
- /**
- * Start activity based on the type of the model
- *
- * This way we can seperate the ui logic for different activities
- *
- * @param model model
- */
- private void startActivity(final MeshModel model) {
- final Intent intent;
- if (model instanceof ConfigurationServerModel) {
- intent = new Intent(this, ConfigurationServerActivity.class);
- } else if (model instanceof GenericOnOffServerModel) {
- intent = new Intent(this, GenericOnOffServerActivity.class);
- } else if (model instanceof GenericLevelServerModel) {
- intent = new Intent(this, GenericLevelServerActivity.class);
- } else if (model instanceof VendorModel) {
- intent = new Intent(this, VendorModelActivity.class);
- } else {
- intent = new Intent(this, ModelConfigurationActivity.class);
- }
- startActivity(intent);
- }
-
- private void updateMeshMessage(final MeshMessage meshMessage) {
- if (meshMessage instanceof ProxyConfigFilterStatus) {
- hideProgressBar();
- }
- if (meshMessage instanceof ConfigCompositionDataStatus) {
- hideProgressBar();
- } else if (meshMessage instanceof ConfigAppKeyStatus) {
- if (getSupportFragmentManager().findFragmentByTag(DIALOG_FRAGMENT_APP_KEY_STATUS) == null) {
- if (!((ConfigAppKeyStatus) meshMessage).isSuccessful()) {
- final DialogFragmentAppKeyAddStatus fragmentAppKeyAddStatus = DialogFragmentAppKeyAddStatus.
- newInstance(getString(R.string.title_appkey_status), ((ConfigAppKeyStatus) meshMessage).getStatusCodeName());
- fragmentAppKeyAddStatus.show(getSupportFragmentManager(), DIALOG_FRAGMENT_APP_KEY_STATUS);
- }
- }
- hideProgressBar();
- } else if (meshMessage instanceof ConfigNodeResetStatus) {
- hideProgressBar();
- finish();
- } else if (meshMessage instanceof ConfigProxyStatus) {
- final ConfigProxyStatus status = (ConfigProxyStatus) meshMessage;
- mProxyState = status.isProxyFeatureEnabled();
- updateProxySettingsCardUi();
- hideProgressBar();
- }
- }
-
- @Override
- public void addAddresses(final List addresses) {
- final ProxyConfigAddAddressToFilter addAddressToFilter = new ProxyConfigAddAddressToFilter(addresses);
- mViewModel.getMeshManagerApi().sendMeshMessage(MeshAddress.UNASSIGNED_ADDRESS, addAddressToFilter);
- }
-
- private void removeAddress(final int position) {
- final ProvisionedMeshNode meshNode = mViewModel.getSelectedMeshNode().getValue();
- if(meshNode != null) {
- final ProxyFilter proxyFilter = meshNode.getProxyFilter();
- if(proxyFilter != null) {
- final AddressArray addressArr = proxyFilter.getAddresses().get(position);
- final List addresses = new ArrayList<>();
- addresses.add(addressArr);
- final ProxyConfigRemoveAddressFromFilter removeAddressFromFilter = new ProxyConfigRemoveAddressFromFilter(addresses);
- mViewModel.getMeshManagerApi().sendMeshMessage(MeshAddress.UNASSIGNED_ADDRESS, removeAddressFromFilter);
- showProgressbar();
- }
- }
- }
-
- private void removeAddresses() {
- final ProvisionedMeshNode meshNode = mViewModel.getSelectedMeshNode().getValue();
- if (meshNode != null) {
- final ProxyFilter proxyFilter = meshNode.getProxyFilter();
- if (proxyFilter != null) {
- if (!proxyFilter.getAddresses().isEmpty()) {
- final ProxyConfigRemoveAddressFromFilter removeAddressFromFilter = new ProxyConfigRemoveAddressFromFilter(proxyFilter.getAddresses());
- mViewModel.getMeshManagerApi().sendMeshMessage(MeshAddress.UNASSIGNED_ADDRESS, removeAddressFromFilter);
- }
- }
- }
- }
-
- private void setFilter(final ProxyFilterType filterType) {
- showProgressbar();
- final ProxyConfigSetFilterType setFilterType = new ProxyConfigSetFilterType(filterType);
- mViewModel.getMeshManagerApi().sendMeshMessage(MeshAddress.UNASSIGNED_ADDRESS, setFilterType);
- }
-}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/MeshProvisionerActivity.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/ProvisioningActivity.java
similarity index 67%
rename from Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/MeshProvisionerActivity.java
rename to Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/ProvisioningActivity.java
index 60352226b..ec1ef4064 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/MeshProvisionerActivity.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/ProvisioningActivity.java
@@ -23,17 +23,8 @@
package no.nordicsemi.android.nrfmeshprovisioner;
import android.app.Activity;
-import android.arch.lifecycle.ViewModelProvider;
-import android.arch.lifecycle.ViewModelProviders;
import android.content.Intent;
import android.os.Bundle;
-import android.support.design.widget.CoordinatorLayout;
-import android.support.design.widget.Snackbar;
-import android.support.v4.content.ContextCompat;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.LinearLayoutManager;
-import android.support.v7.widget.RecyclerView;
-import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
@@ -42,18 +33,29 @@
import android.widget.ScrollView;
import android.widget.TextView;
-import java.util.ArrayList;
-import java.util.List;
+import com.google.android.material.snackbar.Snackbar;
+
import java.util.Locale;
import javax.inject.Inject;
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.Toolbar;
+import androidx.coordinatorlayout.widget.CoordinatorLayout;
+import androidx.core.content.ContextCompat;
+import androidx.lifecycle.ViewModelProvider;
+import androidx.lifecycle.ViewModelProviders;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
import butterknife.BindView;
import butterknife.ButterKnife;
+import no.nordicsemi.android.meshprovisioner.ApplicationKey;
+import no.nordicsemi.android.meshprovisioner.MeshNetwork;
+import no.nordicsemi.android.meshprovisioner.Provisioner;
import no.nordicsemi.android.meshprovisioner.provisionerstates.ProvisioningCapabilities;
import no.nordicsemi.android.meshprovisioner.provisionerstates.ProvisioningFailedState;
import no.nordicsemi.android.meshprovisioner.provisionerstates.UnprovisionedMeshNode;
-import no.nordicsemi.android.meshprovisioner.transport.ApplicationKey;
import no.nordicsemi.android.meshprovisioner.utils.AlgorithmType;
import no.nordicsemi.android.meshprovisioner.utils.AuthenticationOOBMethods;
import no.nordicsemi.android.meshprovisioner.utils.InputOOBAction;
@@ -63,37 +65,29 @@
import no.nordicsemi.android.nrfmeshprovisioner.adapter.ExtendedBluetoothDevice;
import no.nordicsemi.android.nrfmeshprovisioner.adapter.ProvisioningProgressAdapter;
import no.nordicsemi.android.nrfmeshprovisioner.di.Injectable;
-import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentAppKeyAddStatus;
import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentAuthenticationInput;
-import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentFlags;
-import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentIvIndex;
-import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentKeyIndex;
-import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentNetworkKey;
-import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentNodeName;
+import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentConfigurationComplete;
import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentProvisioningFailedError;
import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentSelectOOBType;
import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentUnicastAddress;
+import no.nordicsemi.android.nrfmeshprovisioner.keys.AppKeysActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.node.dialog.DialogFragmentNodeName;
+import no.nordicsemi.android.nrfmeshprovisioner.utils.ProvisionerStates;
import no.nordicsemi.android.nrfmeshprovisioner.utils.Utils;
-import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.MeshNetworkLiveData;
-import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.MeshProvisionerViewModel;
import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.ProvisionerProgress;
-import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.ProvisioningStatusLiveData;
+import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.ProvisioningViewModel;
-public class MeshProvisionerActivity extends AppCompatActivity implements Injectable,
+public class ProvisioningActivity extends AppCompatActivity implements Injectable,
DialogFragmentSelectOOBType.DialogFragmentSelectOOBTypeListener,
DialogFragmentAuthenticationInput.ProvisionerInputFragmentListener,
DialogFragmentNodeName.DialogFragmentNodeNameListener,
- DialogFragmentNetworkKey.DialogFragmentNetworkKeyListener,
- DialogFragmentKeyIndex.DialogFragmentKeyIndexListener,
- DialogFragmentFlags.DialogFragmentFlagsListener,
- DialogFragmentIvIndex.DialogFragmentIvIndexListener,
DialogFragmentUnicastAddress.DialogFragmentUnicastAddressListener,
DialogFragmentProvisioningFailedError.DialogFragmentProvisioningFailedErrorListener,
- DialogFragmentAppKeyAddStatus.DialogFragmentAppKeyAddStatusListener {
+ DialogFragmentConfigurationComplete.ConfigurationCompleteListener {
private static final String DIALOG_FRAGMENT_PROVISIONING_FAILED = "DIALOG_FRAGMENT_PROVISIONING_FAILED";
private static final String DIALOG_FRAGMENT_AUTH_INPUT_TAG = "DIALOG_FRAGMENT_AUTH_INPUT_TAG";
- private static final String DIALOG_FRAGMENT_APP_KEY_STATUS = "DIALOG_FRAGMENT_APP_KEY_STATUS";
+ private static final String DIALOG_FRAGMENT_CONFIGURATION_STATUS = "DIALOG_FRAGMENT_CONFIGURATION_STATUS";
@BindView(R.id.container)
CoordinatorLayout mCoordinatorLayout;
@@ -109,7 +103,7 @@ public class MeshProvisionerActivity extends AppCompatActivity implements Inject
@Inject
ViewModelProvider.Factory mViewModelFactory;
- private MeshProvisionerViewModel mViewModel;
+ private ProvisioningViewModel mViewModel;
@Override
protected void onCreate(final Bundle savedInstanceState) {
@@ -129,45 +123,56 @@ protected void onCreate(final Bundle savedInstanceState) {
getSupportActionBar().setSubtitle(deviceAddress);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
- mViewModel = ViewModelProviders.of(this, mViewModelFactory).get(MeshProvisionerViewModel.class);
+ mViewModel = ViewModelProviders.of(this, mViewModelFactory).get(ProvisioningViewModel.class);
if (savedInstanceState == null)
mViewModel.connect(this, device, false);
// Set up views
final LinearLayout connectivityProgressContainer = findViewById(R.id.connectivity_progress_container);
final TextView connectionState = findViewById(R.id.connection_state);
- final Button provisioner = findViewById(R.id.action_provision_device);
+ final Button action_provision = findViewById(R.id.action_provision_device);
- final View containerName = findViewById(R.id.container_element_count);
- containerName.findViewById(R.id.image).setBackground(ContextCompat.getDrawable(this, R.drawable.ic_vpn_key_black_alpha_24dp));
+ final View containerName = findViewById(R.id.container_name);
+ containerName.findViewById(R.id.image)
+ .setBackground(ContextCompat.getDrawable(this, R.drawable.ic_label_outline_black_alpha_24dp));
final TextView nameTitle = containerName.findViewById(R.id.title);
nameTitle.setText(R.string.summary_name);
final TextView nameView = containerName.findViewById(R.id.text);
+ nameView.setVisibility(View.VISIBLE);
containerName.setOnClickListener(v -> {
final DialogFragmentNodeName dialogFragmentNodeName = DialogFragmentNodeName.newInstance(deviceName);
dialogFragmentNodeName.show(getSupportFragmentManager(), null);
});
- final View containerUnicastAddress = findViewById(R.id.container_supported_algorithm);
- containerUnicastAddress.findViewById(R.id.image).setBackground(ContextCompat.getDrawable(this, R.drawable.ic_lan_black_alpha_24dp));
+ final View containerUnicastAddress = findViewById(R.id.container_unicast);
+ containerUnicastAddress.findViewById(R.id.image)
+ .setBackground(ContextCompat.getDrawable(this, R.drawable.ic_lan_black_alpha_24dp));
final TextView unicastAddressTitle = containerUnicastAddress.findViewById(R.id.title);
- unicastAddressTitle.setText(R.string.summary_unicast_address);
+ unicastAddressTitle.setText(R.string.title_unicast_address);
final TextView unicastAddressView = containerUnicastAddress.findViewById(R.id.text);
+ unicastAddressView.setVisibility(View.VISIBLE);
containerUnicastAddress.setOnClickListener(v -> {
- final int unicastAddress = mViewModel.getMeshNetworkLiveData().getUnicastAddress();
- final DialogFragmentUnicastAddress dialogFragmentFlags = DialogFragmentUnicastAddress.newInstance(unicastAddress);
- dialogFragmentFlags.show(getSupportFragmentManager(), null);
+
+ final UnprovisionedMeshNode node = mViewModel.getUnprovisionedMeshNode().getValue();
+ if (node != null && node.getProvisioningCapabilities() != null) {
+ final int elementCount = node.getProvisioningCapabilities().getNumberOfElements();
+ final DialogFragmentUnicastAddress dialogFragmentFlags = DialogFragmentUnicastAddress.
+ newInstance(mViewModel.getNetworkLiveData().getMeshNetwork().getUnicastAddress(), elementCount);
+ dialogFragmentFlags.show(getSupportFragmentManager(), null);
+ }
});
- final View containerAppKey = findViewById(R.id.container_public_key_type);
- containerAppKey.findViewById(R.id.image).setBackground(ContextCompat.getDrawable(this, R.drawable.ic_vpn_key_black_alpha_24dp));
+ final View containerAppKey = findViewById(R.id.container_app_keys);
+ containerAppKey.findViewById(R.id.image)
+ .setBackground(ContextCompat.getDrawable(this, R.drawable.ic_vpn_key_black_alpha_24dp));
final TextView appKeyTitle = containerAppKey.findViewById(R.id.title);
- appKeyTitle.setText(R.string.summary_app_keys);
+ appKeyTitle.setText(R.string.title_app_keys);
final TextView appKeyView = containerAppKey.findViewById(R.id.text);
+ appKeyView.setVisibility(View.VISIBLE);
containerAppKey.setOnClickListener(v -> {
- final Intent manageAppKeys = new Intent(MeshProvisionerActivity.this, ManageAppKeysActivity.class);
+ final Intent manageAppKeys = new Intent(ProvisioningActivity.this, AppKeysActivity.class);
manageAppKeys.putExtra(Utils.EXTRA_DATA, Utils.ADD_APP_KEY);
- startActivityForResult(manageAppKeys, ManageAppKeysActivity.SELECT_APP_KEY);
+ startActivityForResult(manageAppKeys, Utils.SELECT_KEY);
});
mViewModel.getConnectionState().observe(this, connectionState::setText);
@@ -198,7 +203,7 @@ protected void onCreate(final Bundle savedInstanceState) {
mViewModel.isReconnecting().observe(this, isReconnecting -> {
if (isReconnecting != null && isReconnecting) {
- mViewModel.getUnProvisionedMeshNode().removeObservers(this);
+ mViewModel.getUnprovisionedMeshNode().removeObservers(this);
provisioningStatusContainer.setVisibility(View.GONE);
container.setVisibility(View.GONE);
mProvisioningProgressBar.setVisibility(View.GONE);
@@ -208,27 +213,42 @@ protected void onCreate(final Bundle savedInstanceState) {
}
});
- mViewModel.getMeshNetworkLiveData().observe(this, meshNetworkLiveData -> {
+ mViewModel.getNetworkLiveData().observe(this, meshNetworkLiveData -> {
nameView.setText(meshNetworkLiveData.getNodeName());
- unicastAddressView.setText(getString(R.string.hex_format, String.format(Locale.US, "%04X", meshNetworkLiveData.getUnicastAddress())));
final ApplicationKey applicationKey = meshNetworkLiveData.getSelectedAppKey();
appKeyView.setText(MeshParserUtils.bytesToHex(applicationKey.getKey(), false));
+ unicastAddressView.setText(getString(R.string.hex_format,
+ String.format(Locale.US, "%04X", meshNetworkLiveData.getMeshNetwork().getUnicastAddress())));
});
- mViewModel.getUnProvisionedMeshNode().observe(this, meshNode -> {
+ mViewModel.getUnprovisionedMeshNode().observe(this, meshNode -> {
if (meshNode != null) {
- if (meshNode.getProvisioningCapabilities() != null) {
+ final ProvisioningCapabilities capabilities = meshNode.getProvisioningCapabilities();
+ if (capabilities != null) {
mProvisioningProgressBar.setVisibility(View.INVISIBLE);
- provisioner.setText(R.string.provision_action);
- updateCapabilitiesUi(meshNode.getProvisioningCapabilities());
+ action_provision.setText(R.string.provision_action);
+ containerUnicastAddress.setVisibility(View.VISIBLE);
+ final MeshNetwork network = mViewModel.getNetworkLiveData().getMeshNetwork();
+ if (network != null) {
+ try {
+ final int elementCount = capabilities.getNumberOfElements();
+ final Provisioner provisioner = network.getSelectedProvisioner();
+ final int unicast = network.nextAvailableUnicastAddress(elementCount, provisioner);
+ network.assignUnicastAddress(unicast);
+ updateCapabilitiesUi(capabilities);
+ } catch (IllegalArgumentException ex) {
+ action_provision.setEnabled(false);
+ mViewModel.displaySnackBar(this, mCoordinatorLayout, ex.getMessage(), Snackbar.LENGTH_LONG);
+ }
+ }
}
}
});
- provisioner.setOnClickListener(v -> {
- final UnprovisionedMeshNode node = mViewModel.getUnProvisionedMeshNode().getValue();
+ action_provision.setOnClickListener(v -> {
+ final UnprovisionedMeshNode node = mViewModel.getUnprovisionedMeshNode().getValue();
if (node == null) {
- device.setName(mViewModel.getMeshNetworkLiveData().getNodeName());
+ device.setName(mViewModel.getNetworkLiveData().getNodeName());
mViewModel.getNrfMeshRepository().identifyNode(device);
return;
}
@@ -244,16 +264,15 @@ protected void onCreate(final Bundle savedInstanceState) {
}
});
- if(savedInstanceState == null)
- mViewModel.getMeshNetworkLiveData().resetSelectedAppKey();
+ if (savedInstanceState == null)
+ mViewModel.getNetworkLiveData().resetSelectedAppKey();
}
@Override
public boolean onOptionsItemSelected(final MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
+ if (item.getItemId() == android.R.id.home) {
+ onBackPressed();
+ return true;
}
return false;
}
@@ -273,11 +292,11 @@ protected void onDestroy() {
@Override
protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
super.onActivityResult(requestCode, resultCode, data);
- if (requestCode == ManageAppKeysActivity.SELECT_APP_KEY) {
+ if (requestCode == Utils.SELECT_KEY) {
if (resultCode == RESULT_OK) {
- final ApplicationKey appKey = data.getParcelableExtra(ManageAppKeysActivity.RESULT_APP_KEY);
+ final ApplicationKey appKey = data.getParcelableExtra(AppKeysActivity.RESULT_APP_KEY);
if (appKey != null) {
- mViewModel.getMeshNetworkLiveData().setSelectedAppKey(appKey);
+ mViewModel.getNetworkLiveData().setSelectedAppKey(appKey);
}
}
}
@@ -285,7 +304,7 @@ protected void onActivityResult(final int requestCode, final int resultCode, fin
@Override
public void onPinInputComplete(final String pin) {
- mViewModel.getMeshManagerApi().setProvisioningConfirmation(pin);
+ mViewModel.getMeshManagerApi().setProvisioningAuthentication(pin);
}
@Override
@@ -297,33 +316,24 @@ public void onPinInputCanceled() {
}
@Override
- public void onNodeNameUpdated(final String nodeName) {
- mViewModel.getMeshNetworkLiveData().setNodeName(nodeName);
+ public boolean onNodeNameUpdated(@NonNull final String nodeName) {
+ mViewModel.getNetworkLiveData().setNodeName(nodeName);
+ return true;
}
@Override
- public void onNetworkKeyGenerated(final String networkKey) {
- mViewModel.getMeshNetworkLiveData().setPrimaryNetworkKey(networkKey);
- }
-
- @Override
- public void onKeyIndexGenerated(final int keyIndex) {
- mViewModel.getMeshNetworkLiveData().setKeyIndex(keyIndex);
- }
-
- @Override
- public void onFlagsSelected(final int keyRefreshFlag, final int ivUpdateFlag) {
- mViewModel.getMeshNetworkLiveData().setFlags(MeshParserUtils.parseUpdateFlags(keyRefreshFlag, ivUpdateFlag));
- }
-
- @Override
- public void setIvIndex(final int ivIndex) {
- mViewModel.getMeshNetworkLiveData().setIvIndex(ivIndex);
+ public boolean setUnicastAddress(final int unicastAddress) {
+ final MeshNetwork network = mViewModel.getMeshManagerApi().getMeshNetwork();
+ if (network != null) {
+ return network.assignUnicastAddress(unicastAddress);
+ }
+ return false;
}
@Override
- public void setUnicastAddress(final int unicastAddress) {
- mViewModel.getMeshNetworkLiveData().setUnicastAddress(unicastAddress);
+ public int getNextUnicastAddress(final int elementCount) {
+ final MeshNetwork network = mViewModel.getNetworkLiveData().getMeshNetwork();
+ return network.nextAvailableUnicastAddress(elementCount, network.getSelectedProvisioner());
}
@Override
@@ -334,7 +344,7 @@ public void onProvisioningFailed() {
}
private void disconnect() {
- mViewModel.getUnProvisionedMeshNode().removeObservers(this);
+ mViewModel.getUnprovisionedMeshNode().removeObservers(this);
mViewModel.disconnect();
}
@@ -347,11 +357,11 @@ public void setupProvisionerStateObservers(final View provisioningStatusContaine
recyclerView.setAdapter(adapter);
mViewModel.getProvisioningStatus().observe(this, provisioningStateLiveData -> {
- if(provisioningStateLiveData != null) {
+ if (provisioningStateLiveData != null) {
final ProvisionerProgress provisionerProgress = provisioningStateLiveData.getProvisionerProgress();
adapter.refresh(provisioningStateLiveData.getStateList());
if (provisionerProgress != null) {
- final ProvisioningStatusLiveData.ProvisioningLiveDataState state = provisionerProgress.getState();
+ final ProvisionerStates state = provisionerProgress.getState();
switch (state) {
case PROVISIONING_FAILED:
if (getSupportFragmentManager().findFragmentByTag(DIALOG_FRAGMENT_PROVISIONING_FAILED) == null) {
@@ -363,21 +373,21 @@ public void setupProvisionerStateObservers(final View provisioningStatusContaine
case PROVISIONING_AUTHENTICATION_STATIC_OOB_WAITING:
if (getSupportFragmentManager().findFragmentByTag(DIALOG_FRAGMENT_AUTH_INPUT_TAG) == null) {
DialogFragmentAuthenticationInput dialogFragmentAuthenticationInput = DialogFragmentAuthenticationInput.
- newInstance(mViewModel.getUnProvisionedMeshNode().getValue());
+ newInstance(mViewModel.getUnprovisionedMeshNode().getValue());
dialogFragmentAuthenticationInput.show(getSupportFragmentManager(), DIALOG_FRAGMENT_AUTH_INPUT_TAG);
}
break;
case PROVISIONING_AUTHENTICATION_OUTPUT_OOB_WAITING:
if (getSupportFragmentManager().findFragmentByTag(DIALOG_FRAGMENT_AUTH_INPUT_TAG) == null) {
DialogFragmentAuthenticationInput dialogFragmentAuthenticationInput = DialogFragmentAuthenticationInput.
- newInstance(mViewModel.getUnProvisionedMeshNode().getValue());
+ newInstance(mViewModel.getUnprovisionedMeshNode().getValue());
dialogFragmentAuthenticationInput.show(getSupportFragmentManager(), DIALOG_FRAGMENT_AUTH_INPUT_TAG);
}
break;
case PROVISIONING_AUTHENTICATION_INPUT_OOB_WAITING:
if (getSupportFragmentManager().findFragmentByTag(DIALOG_FRAGMENT_AUTH_INPUT_TAG) == null) {
DialogFragmentAuthenticationInput dialogFragmentAuthenticationInput = DialogFragmentAuthenticationInput.
- newInstance(mViewModel.getUnProvisionedMeshNode().getValue());
+ newInstance(mViewModel.getUnprovisionedMeshNode().getValue());
dialogFragmentAuthenticationInput.show(getSupportFragmentManager(), DIALOG_FRAGMENT_AUTH_INPUT_TAG);
}
break;
@@ -387,13 +397,18 @@ public void setupProvisionerStateObservers(final View provisioningStatusContaine
if (fragment != null)
fragment.dismiss();
break;
- case APP_KEY_STATUS_RECEIVED:
- if (getSupportFragmentManager().findFragmentByTag(DIALOG_FRAGMENT_APP_KEY_STATUS) == null) {
- DialogFragmentAppKeyAddStatus fragmentAppKeyAddStatus = DialogFragmentAppKeyAddStatus.
+ case NETWORK_TRANSMIT_STATUS_RECEIVED:
+ if (getSupportFragmentManager().findFragmentByTag(DIALOG_FRAGMENT_CONFIGURATION_STATUS) == null) {
+ DialogFragmentConfigurationComplete fragmentConfigComplete = DialogFragmentConfigurationComplete.
newInstance(getString(R.string.title_configuration_compete), getString(R.string.configuration_complete_summary));
- fragmentAppKeyAddStatus.show(getSupportFragmentManager(), DIALOG_FRAGMENT_APP_KEY_STATUS);
+ fragmentConfigComplete.show(getSupportFragmentManager(), DIALOG_FRAGMENT_CONFIGURATION_STATUS);
}
break;
+ case PROVISIONER_UNASSIGNED:
+ setResultIntent();
+ break;
+ default:
+ break;
}
}
@@ -404,7 +419,7 @@ public void setupProvisionerStateObservers(final View provisioningStatusContaine
}
@Override
- public void onAppKeyAddStatusReceived() {
+ public void onConfigurationCompleted() {
setResultIntent();
}
@@ -413,10 +428,21 @@ private void setResultIntent() {
if (mViewModel.isProvisioningComplete()) {
returnIntent.putExtra(Utils.PROVISIONING_COMPLETED, true);
setResult(Activity.RESULT_OK, returnIntent);
- if (mViewModel.isCompositionDataStatusReceived()) {
- returnIntent.putExtra(Utils.COMPOSITION_DATA_COMPLETED, true);
- if (mViewModel.isAppKeyAddCompleted()) {
- returnIntent.putExtra(Utils.APP_KEY_ADD_COMPLETED, true);
+ final ProvisionerProgress progress = mViewModel.getProvisioningStatus().getProvisionerProgress();
+ if (progress.getState() == ProvisionerStates.PROVISIONER_UNASSIGNED) {
+ returnIntent.putExtra(Utils.PROVISIONER_UNASSIGNED, true);
+ } else {
+ if (mViewModel.isCompositionDataStatusReceived()) {
+ returnIntent.putExtra(Utils.COMPOSITION_DATA_COMPLETED, true);
+ if (mViewModel.isDefaultTtlReceived()) {
+ returnIntent.putExtra(Utils.DEFAULT_GET_COMPLETED, true);
+ if (mViewModel.isAppKeyAddCompleted()) {
+ returnIntent.putExtra(Utils.APP_KEY_ADD_COMPLETED, true);
+ if (mViewModel.isNetworkRetransmitSetCompleted()) {
+ returnIntent.putExtra(Utils.NETWORK_TRANSMIT_SET_COMPLETED, true);
+ }
+ }
+ }
}
}
}
@@ -517,41 +543,61 @@ private String parseInputOOBActions(final ProvisioningCapabilities capabilities)
@Override
public void onNoOOBSelected() {
- final UnprovisionedMeshNode node = mViewModel.getUnProvisionedMeshNode().getValue();
+ final UnprovisionedMeshNode node = mViewModel.getUnprovisionedMeshNode().getValue();
if (node != null) {
- setupProvisionerStateObservers(provisioningStatusContainer);
- mProvisioningProgressBar.setVisibility(View.VISIBLE);
- mViewModel.getMeshManagerApi().startProvisioning(node);
+ try {
+ node.setNodeName(mViewModel.getNetworkLiveData().getNodeName());
+ setupProvisionerStateObservers(provisioningStatusContainer);
+ mProvisioningProgressBar.setVisibility(View.VISIBLE);
+ mViewModel.getMeshManagerApi().startProvisioning(node);
+ } catch (IllegalArgumentException ex) {
+ mViewModel.displaySnackBar(this, mCoordinatorLayout, ex.getMessage(), Snackbar.LENGTH_LONG);
+ }
}
}
@Override
public void onStaticOOBSelected(final StaticOOBType staticOOBType) {
- final UnprovisionedMeshNode node = mViewModel.getUnProvisionedMeshNode().getValue();
+ final UnprovisionedMeshNode node = mViewModel.getUnprovisionedMeshNode().getValue();
if (node != null) {
- setupProvisionerStateObservers(provisioningStatusContainer);
- mProvisioningProgressBar.setVisibility(View.VISIBLE);
- mViewModel.getMeshManagerApi().startProvisioningWithStaticOOB(node);
+ try {
+ node.setNodeName(mViewModel.getNetworkLiveData().getNodeName());
+ setupProvisionerStateObservers(provisioningStatusContainer);
+ mProvisioningProgressBar.setVisibility(View.VISIBLE);
+ mViewModel.getMeshManagerApi().startProvisioningWithStaticOOB(node);
+ } catch (IllegalArgumentException ex) {
+ mViewModel.displaySnackBar(this, mCoordinatorLayout, ex.getMessage(), Snackbar.LENGTH_LONG);
+ }
}
}
@Override
public void onOutputOOBActionSelected(final OutputOOBAction action) {
- final UnprovisionedMeshNode node = mViewModel.getUnProvisionedMeshNode().getValue();
+ final UnprovisionedMeshNode node = mViewModel.getUnprovisionedMeshNode().getValue();
if (node != null) {
- setupProvisionerStateObservers(provisioningStatusContainer);
- mProvisioningProgressBar.setVisibility(View.VISIBLE);
- mViewModel.getMeshManagerApi().startProvisioningWithOutputOOB(node, action);
+ try {
+ node.setNodeName(mViewModel.getNetworkLiveData().getNodeName());
+ setupProvisionerStateObservers(provisioningStatusContainer);
+ mProvisioningProgressBar.setVisibility(View.VISIBLE);
+ mViewModel.getMeshManagerApi().startProvisioningWithOutputOOB(node, action);
+ } catch (IllegalArgumentException ex) {
+ mViewModel.displaySnackBar(this, mCoordinatorLayout, ex.getMessage(), Snackbar.LENGTH_LONG);
+ }
}
}
@Override
public void onInputOOBActionSelected(final InputOOBAction action) {
- final UnprovisionedMeshNode node = mViewModel.getUnProvisionedMeshNode().getValue();
+ final UnprovisionedMeshNode node = mViewModel.getUnprovisionedMeshNode().getValue();
if (node != null) {
- setupProvisionerStateObservers(provisioningStatusContainer);
- mProvisioningProgressBar.setVisibility(View.VISIBLE);
- mViewModel.getMeshManagerApi().startProvisioningWithInputOOB(node, action);
+ try {
+ node.setNodeName(mViewModel.getNetworkLiveData().getNodeName());
+ setupProvisionerStateObservers(provisioningStatusContainer);
+ mProvisioningProgressBar.setVisibility(View.VISIBLE);
+ mViewModel.getMeshManagerApi().startProvisioningWithInputOOB(node, action);
+ } catch (IllegalArgumentException ex) {
+ mViewModel.displaySnackBar(this, mCoordinatorLayout, ex.getMessage(), Snackbar.LENGTH_LONG);
+ }
}
}
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/ProxyFilterFragment.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/ProxyFilterFragment.java
new file mode 100644
index 000000000..e75dfeeba
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/ProxyFilterFragment.java
@@ -0,0 +1,295 @@
+/*
+ * Copyright (c) 2018, Nordic Semiconductor
+ * 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 no.nordicsemi.android.nrfmeshprovisioner;
+
+import android.annotation.SuppressLint;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.cardview.widget.CardView;
+import androidx.fragment.app.Fragment;
+import androidx.lifecycle.ViewModelProvider;
+import androidx.lifecycle.ViewModelProviders;
+import androidx.recyclerview.widget.DefaultItemAnimator;
+import androidx.recyclerview.widget.ItemTouchHelper;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import butterknife.BindView;
+import butterknife.ButterKnife;
+import no.nordicsemi.android.meshprovisioner.MeshNetwork;
+import no.nordicsemi.android.meshprovisioner.transport.MeshMessage;
+import no.nordicsemi.android.meshprovisioner.transport.ProxyConfigAddAddressToFilter;
+import no.nordicsemi.android.meshprovisioner.transport.ProxyConfigRemoveAddressFromFilter;
+import no.nordicsemi.android.meshprovisioner.transport.ProxyConfigSetFilterType;
+import no.nordicsemi.android.meshprovisioner.utils.AddressArray;
+import no.nordicsemi.android.meshprovisioner.utils.MeshAddress;
+import no.nordicsemi.android.meshprovisioner.utils.ProxyFilter;
+import no.nordicsemi.android.meshprovisioner.utils.ProxyFilterType;
+import no.nordicsemi.android.nrfmeshprovisioner.adapter.FilterAddressAdapter;
+import no.nordicsemi.android.nrfmeshprovisioner.di.Injectable;
+import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentError;
+import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentFilterAddAddress;
+import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.SharedViewModel;
+import no.nordicsemi.android.nrfmeshprovisioner.widgets.ItemTouchHelperAdapter;
+import no.nordicsemi.android.nrfmeshprovisioner.widgets.RemovableItemTouchHelperCallback;
+import no.nordicsemi.android.nrfmeshprovisioner.widgets.RemovableViewHolder;
+
+public class ProxyFilterFragment extends Fragment implements Injectable,
+ DialogFragmentFilterAddAddress.DialogFragmentFilterAddressListener,
+ ItemTouchHelperAdapter {
+
+ private static final String CLEAR_ADDRESS_PRESSED = "CLEAR_ADDRESS_PRESSED";
+ private static final String PROXY_FILTER_DISABLED = "PROXY_FILTER_DISABLED";
+
+ private SharedViewModel mViewModel;
+
+ @Inject
+ ViewModelProvider.Factory mViewModelFactory;
+ @BindView(R.id.action_white_list)
+ Button actionEnableWhiteList;
+ @BindView(R.id.action_black_list)
+ Button actionEnableBlackList;
+ @BindView(R.id.action_disable)
+ Button actionDisable;
+ @BindView(R.id.action_add_address)
+ Button actionAddFilterAddress;
+ @BindView(R.id.action_clear_addresses)
+ Button actionClearFilterAddress;
+ @BindView(R.id.proxy_filter_address_card)
+ CardView mProxyFilterCard;
+ private ProxyFilter mFilter;
+ private boolean clearAddressPressed;
+ private boolean isProxyFilterDisabled;
+ private FilterAddressAdapter addressAdapter;
+
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ }
+
+ @Nullable
+ @Override
+ public View onCreateView(@NonNull final LayoutInflater inflater, @Nullable final ViewGroup container, @Nullable final Bundle savedInstanceState) {
+ @SuppressLint("InflateParams") final View rootView = inflater.inflate(R.layout.fragment_proxy_filter, null);
+ mViewModel = ViewModelProviders.of(requireActivity(), mViewModelFactory).get(SharedViewModel.class);
+ ButterKnife.bind(this, rootView);
+
+ if (savedInstanceState != null) {
+ clearAddressPressed = savedInstanceState.getBoolean(CLEAR_ADDRESS_PRESSED);
+ isProxyFilterDisabled = savedInstanceState.getBoolean(PROXY_FILTER_DISABLED);
+ }
+
+ final TextView noAddressesAdded = rootView.findViewById(R.id.no_addresses);
+ final RecyclerView recyclerViewAddresses = rootView.findViewById(R.id.recycler_view_filter_addresses);
+ actionEnableWhiteList.setEnabled(false);
+ actionEnableBlackList.setEnabled(false);
+ actionDisable.setEnabled(false);
+
+ recyclerViewAddresses.setLayoutManager(new LinearLayoutManager(requireContext()));
+ recyclerViewAddresses.setItemAnimator(new DefaultItemAnimator());
+ final ItemTouchHelper.Callback itemTouchHelperCallback = new RemovableItemTouchHelperCallback(this);
+ final ItemTouchHelper itemTouchHelper = new ItemTouchHelper(itemTouchHelperCallback);
+ itemTouchHelper.attachToRecyclerView(recyclerViewAddresses);
+ addressAdapter = new FilterAddressAdapter(requireContext());
+ recyclerViewAddresses.setAdapter(addressAdapter);
+
+ mViewModel.isConnectedToProxy().observe(this, isConnected -> {
+ if (!isConnected) {
+ clearAddressPressed = false;
+ final MeshNetwork network = mViewModel.getNetworkLiveData().getMeshNetwork();
+ if (network != null) {
+ mFilter = network.getProxyFilter();
+ if (mFilter == null) {
+ addressAdapter.clearData();
+ noAddressesAdded.setVisibility(View.VISIBLE);
+ recyclerViewAddresses.setVisibility(View.GONE);
+ }
+ }
+
+ actionEnableWhiteList.setSelected(isConnected);
+ actionEnableBlackList.setSelected(isConnected);
+ actionDisable.setSelected(isConnected);
+ actionAddFilterAddress.setEnabled(isConnected);
+ actionClearFilterAddress.setVisibility(View.GONE);
+ }
+ actionDisable.setEnabled(false);
+ actionEnableWhiteList.setEnabled(isConnected);
+ actionEnableBlackList.setEnabled(isConnected);
+ });
+
+ mViewModel.getNetworkLiveData().observe(this, meshNetworkLiveData -> {
+ final MeshNetwork network = meshNetworkLiveData.getMeshNetwork();
+ if (network == null) {
+ return;
+ }
+
+ final ProxyFilter filter = mFilter = network.getProxyFilter();
+ if (filter == null) {
+ addressAdapter.clearData();
+ return;
+ } else if (clearAddressPressed) {
+ clearAddressPressed = false;
+ return;
+ } else if (isProxyFilterDisabled) {
+ actionDisable.setSelected(true);
+ }
+
+ actionEnableWhiteList.setSelected(mFilter.getFilterType().getType() == ProxyFilterType.WHITE_LIST_FILTER && !actionDisable.isSelected());
+ actionEnableBlackList.setSelected(mFilter.getFilterType().getType() == ProxyFilterType.BLACK_LIST_FILTER);
+
+ if (!mFilter.getAddresses().isEmpty()) {
+ noAddressesAdded.setVisibility(View.GONE);
+ actionClearFilterAddress.setVisibility(View.VISIBLE);
+ } else {
+ noAddressesAdded.setVisibility(View.VISIBLE);
+ actionClearFilterAddress.setVisibility(View.GONE);
+ }
+ actionAddFilterAddress.setEnabled(!actionDisable.isSelected());
+ addressAdapter.updateData(filter);
+ });
+
+ actionEnableWhiteList.setOnClickListener(v -> {
+ isProxyFilterDisabled = false;
+ v.setSelected(true);
+ actionEnableBlackList.setSelected(false);
+ actionDisable.setSelected(false);
+ actionDisable.setEnabled(true);
+ setFilter(new ProxyFilterType(ProxyFilterType.WHITE_LIST_FILTER));
+ });
+
+ actionEnableBlackList.setOnClickListener(v -> {
+ isProxyFilterDisabled = false;
+ v.setSelected(true);
+ actionEnableWhiteList.setSelected(false);
+ actionDisable.setSelected(false);
+ actionDisable.setEnabled(true);
+ setFilter(new ProxyFilterType(ProxyFilterType.BLACK_LIST_FILTER));
+ });
+
+ actionDisable.setOnClickListener(v -> {
+ v.setSelected(true);
+ isProxyFilterDisabled = true;
+ actionEnableWhiteList.setSelected(false);
+ actionEnableBlackList.setSelected(false);
+ addressAdapter.clearData();
+ actionDisable.setEnabled(false);
+ setFilter(new ProxyFilterType(ProxyFilterType.WHITE_LIST_FILTER));
+ });
+
+ actionAddFilterAddress.setOnClickListener(v -> {
+ final ProxyFilterType filterType;
+ if (mFilter == null) {
+ filterType = new ProxyFilterType(ProxyFilterType.WHITE_LIST_FILTER);
+ } else {
+ filterType = mFilter.getFilterType();
+ }
+ final DialogFragmentFilterAddAddress filterAddAddress = DialogFragmentFilterAddAddress.newInstance(filterType);
+ filterAddAddress.show(getChildFragmentManager(), null);
+ });
+
+ actionClearFilterAddress.setOnClickListener(v -> removeAddresses());
+
+ return rootView;
+ }
+
+ @Override
+ public void onSaveInstanceState(@NonNull final Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putBoolean(CLEAR_ADDRESS_PRESSED, clearAddressPressed);
+ outState.putBoolean(PROXY_FILTER_DISABLED, isProxyFilterDisabled);
+ }
+
+ @Override
+ public void addAddresses(final List addresses) {
+ final ProxyConfigAddAddressToFilter addAddressToFilter = new ProxyConfigAddAddressToFilter(addresses);
+ sendMessage(addAddressToFilter);
+ }
+
+ @Override
+ public void onItemDismiss(final RemovableViewHolder viewHolder) {
+ final int position = viewHolder.getAdapterPosition();
+ if (viewHolder instanceof FilterAddressAdapter.ViewHolder) {
+ removeAddress(position);
+ }
+ }
+
+ @Override
+ public void onItemDismissFailed(final RemovableViewHolder viewHolder) {
+
+ }
+
+ private void removeAddress(final int position) {
+ final MeshNetwork meshNetwork = mViewModel.getNetworkLiveData().getMeshNetwork();
+ if (meshNetwork != null) {
+ final ProxyFilter proxyFilter = meshNetwork.getProxyFilter();
+ if (proxyFilter != null) {
+ clearAddressPressed = true;
+ final AddressArray addressArr = proxyFilter.getAddresses().get(position);
+ final List addresses = new ArrayList<>();
+ addresses.add(addressArr);
+ addressAdapter.clearRow(position);
+ final ProxyConfigRemoveAddressFromFilter removeAddressFromFilter = new ProxyConfigRemoveAddressFromFilter(addresses);
+ sendMessage(removeAddressFromFilter);
+ }
+ }
+ }
+
+ private void removeAddresses() {
+ final MeshNetwork meshNetwork = mViewModel.getNetworkLiveData().getMeshNetwork();
+ if (meshNetwork != null) {
+ final ProxyFilter proxyFilter = meshNetwork.getProxyFilter();
+ if (proxyFilter != null) {
+ if (!proxyFilter.getAddresses().isEmpty()) {
+ final ProxyConfigRemoveAddressFromFilter removeAddressFromFilter = new ProxyConfigRemoveAddressFromFilter(proxyFilter.getAddresses());
+ sendMessage(removeAddressFromFilter);
+ }
+ }
+ }
+ }
+
+ private void setFilter(final ProxyFilterType filterType) {
+ final ProxyConfigSetFilterType setFilterType = new ProxyConfigSetFilterType(filterType);
+ sendMessage(setFilterType);
+ }
+
+ private void sendMessage(final MeshMessage meshMessage) {
+ try {
+ mViewModel.getMeshManagerApi().createMeshPdu(MeshAddress.UNASSIGNED_ADDRESS, meshMessage);
+ } catch (IllegalArgumentException ex) {
+ final DialogFragmentError message = DialogFragmentError.
+ newInstance(getString(R.string.title_error), ex.getMessage());
+ message.show(getChildFragmentManager(), null);
+ }
+ }
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/PublicationSettingsActivity.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/PublicationSettingsActivity.java
deleted file mode 100644
index 8e77acce1..000000000
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/PublicationSettingsActivity.java
+++ /dev/null
@@ -1,356 +0,0 @@
-package no.nordicsemi.android.nrfmeshprovisioner;
-
-import android.app.Activity;
-import android.arch.lifecycle.ViewModelProvider;
-import android.arch.lifecycle.ViewModelProviders;
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.Toolbar;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.widget.Switch;
-import android.widget.TextView;
-
-import javax.inject.Inject;
-
-import butterknife.BindView;
-import butterknife.ButterKnife;
-import no.nordicsemi.android.meshprovisioner.transport.ApplicationKey;
-import no.nordicsemi.android.meshprovisioner.transport.MeshModel;
-import no.nordicsemi.android.meshprovisioner.utils.AddressUtils;
-import no.nordicsemi.android.meshprovisioner.utils.MeshAddress;
-import no.nordicsemi.android.meshprovisioner.utils.MeshParserUtils;
-import no.nordicsemi.android.meshprovisioner.utils.PublicationSettings;
-import no.nordicsemi.android.nrfmeshprovisioner.di.Injectable;
-import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentPubRetransmitIntervalSteps;
-import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentPublicationResolution;
-import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentPublicationSteps;
-import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentPublishAddress;
-import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentPublishTtl;
-import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentRetransmitCount;
-import no.nordicsemi.android.nrfmeshprovisioner.utils.Utils;
-import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.PublicationViewModel;
-
-public class PublicationSettingsActivity extends AppCompatActivity implements Injectable,
- DialogFragmentPublishAddress.DialogFragmentPublishAddressListener,
- DialogFragmentPublicationSteps.DialogFragmentPublicationStepsListener,
- DialogFragmentPublicationResolution.DialogFragmentPublicationResolutionListener,
- DialogFragmentRetransmitCount.DialogFragmentRetransmitCountListener,
- DialogFragmentPubRetransmitIntervalSteps.DialogFragmentIntervalStepsListener,
- DialogFragmentPublishTtl.DialogFragmentPublishTtlListener {
-
- public static final int SET_PUBLICATION_SETTINGS = 2021;
- public static final String RESULT_PUBLISH_ADDRESS = "RESULT_PUBLISH_ADDRESS";
- public static final String RESULT_APP_KEY_INDEX = "RESULT_APP_KEY_INDEX";
- public static final String RESULT_CREDENTIAL_FLAG = "RESULT_CREDENTIAL_FLAG";
- public static final String RESULT_PUBLISH_TTL = "RESULT_PUBLISH_TTL";
- public static final String RESULT_PUBLICATION_STEPS = "RESULT_PUBLICATION_STEPS";
- public static final String RESULT_PUBLICATION_RESOLUTION = "RESULT_PUBLICATION_RESOLUTION";
- public static final String RESULT_PUBLISH_RETRANSMIT_COUNT = "RESULT_PUBLISH_RETRANSMIT_COUNT";
- public static final String RESULT_PUBLISH_RETRANSMIT_INTERVAL_STEPS = "RESULT_PUBLISH_RETRANSMIT_INTERVAL_STEPS";
-
- private static final int DEFAULT_PUB_RETRANSMIT_COUNT = 1;
- private static final int DEFAULT_PUB_RETRANSMIT_INTERVAL_STEPS = 1;
- private static final int DEFAULT_PUBLICATION_STEPS = 0;
- @SuppressWarnings("unused")
- private static final int DEFAULT_PUBLICATION_RESOLUTION = MeshParserUtils.RESOLUTION_100_MS;
-
- private MeshModel mMeshModel;
- private int mPublishAddress;
- private Integer mAppKeyIndex;
- private int mPublishTtl = MeshParserUtils.USE_DEFAULT_TTL;
- private int mPublicationSteps = DEFAULT_PUBLICATION_STEPS;
- private int mPublicationResolution;
- private int mPublishRetransmitCount = DEFAULT_PUB_RETRANSMIT_COUNT;
- private int mPublishRetransmitIntervalSteps = DEFAULT_PUB_RETRANSMIT_INTERVAL_STEPS;
-
- @Inject
- ViewModelProvider.Factory mViewModelFactory;
-
- @BindView(R.id.publish_address)
- TextView mPublishAddressView;
- @BindView(R.id.retransmit_count)
- TextView mRetransmitCountView;
- @BindView(R.id.interval_steps)
- TextView mIntervalStepsView;
- @BindView(R.id.publication_steps)
- TextView mPublicationStepsView;
- @BindView(R.id.publication_resolution)
- TextView mPublicationResolutionView;
- @BindView(R.id.app_key_index)
- TextView mAppKeyIndexView;
- @BindView(R.id.publication_ttl)
- TextView mPublishTtlView;
- @BindView(R.id.friendship_credential_flag)
- Switch mActionFriendshipCredentialSwitch;
-
- @Override
- protected void onCreate(@Nullable final Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_publication_settings);
- ButterKnife.bind(this);
-
- final PublicationViewModel viewModel = ViewModelProviders.of(this, mViewModelFactory).get(PublicationViewModel.class);
-
- final MeshModel meshModel = mMeshModel = viewModel.getSelectedModel().getValue();
- if (meshModel == null)
- finish();
-
- //Setup views
- final Toolbar toolbar = findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
- //noinspection ConstantConditions
- getSupportActionBar().setDisplayHomeAsUpEnabled(true);
- getSupportActionBar().setTitle(R.string.title_publication_settings);
-
- final View actionPublishAddress = findViewById(R.id.container_publish_address);
- final View actionRetransmitCount = findViewById(R.id.container_retransmission_count);
- final View actionIntervalSteps = findViewById(R.id.container_interval_steps);
- final View actionPublicationSteps = findViewById(R.id.container_publish_steps);
- final View actionResolution = findViewById(R.id.container_resolution);
- final View actionKeyIndex = findViewById(R.id.container_app_key_index);
- final View actionPublishTtl = findViewById(R.id.container_publication_ttl);
-
- if (savedInstanceState == null) {
- //noinspection ConstantConditions
- updateUi(meshModel);
- }
-
- actionPublishAddress.setOnClickListener(v -> {
- final byte[] address = AddressUtils.getUnicastAddressBytes(this.mPublishAddress);
- final DialogFragmentPublishAddress fragmentPublishAddress = DialogFragmentPublishAddress.newInstance(address);
- fragmentPublishAddress.show(getSupportFragmentManager(), null);
- });
-
- actionRetransmitCount.setOnClickListener(v -> {
- final DialogFragmentRetransmitCount fragmentRetransmitCount = DialogFragmentRetransmitCount.newInstance(mPublishRetransmitCount);
- fragmentRetransmitCount.show(getSupportFragmentManager(), null);
- });
-
- actionIntervalSteps.setOnClickListener(v -> {
- final DialogFragmentPubRetransmitIntervalSteps fragmentIntervalSteps = DialogFragmentPubRetransmitIntervalSteps.newInstance(mPublishRetransmitIntervalSteps);
- fragmentIntervalSteps.show(getSupportFragmentManager(), null);
- });
-
- actionPublicationSteps.setOnClickListener(v -> {
- final DialogFragmentPublicationSteps fragmentPublicationSteps = DialogFragmentPublicationSteps.newInstance(mPublicationSteps);
- fragmentPublicationSteps.show(getSupportFragmentManager(), null);
- });
-
- actionResolution.setOnClickListener(v -> {
- final DialogFragmentPublicationResolution fragmentPublicationResolution = DialogFragmentPublicationResolution.newInstance(mPublicationResolution);
- fragmentPublicationResolution.show(getSupportFragmentManager(), null);
- });
-
- actionKeyIndex.setOnClickListener(v -> {
- final Intent bindAppKeysIntent = new Intent(this, ManageAppKeysActivity.class);
- bindAppKeysIntent.putExtra(Utils.EXTRA_DATA, Utils.PUBLICATION_APP_KEY);
- startActivityForResult(bindAppKeysIntent, ManageAppKeysActivity.SELECT_APP_KEY);
- });
-
- actionPublishTtl.setOnClickListener(v -> {
- if(meshModel != null) {
- final PublicationSettings publicationSettings = meshModel.getPublicationSettings();
- final DialogFragmentPublishTtl fragmentPublishTtl;
- if (publicationSettings != null) {
- fragmentPublishTtl = DialogFragmentPublishTtl.newInstance(meshModel.getPublicationSettings().getPublishTtl());
- } else {
- fragmentPublishTtl = DialogFragmentPublishTtl.newInstance(MeshParserUtils.USE_DEFAULT_TTL);
- }
- fragmentPublishTtl.show(getSupportFragmentManager(), null);
- }
- });
- }
-
- @Override
- public boolean onCreateOptionsMenu(final Menu menu) {
- getMenuInflater().inflate(R.menu.publication_apply, menu);
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(final MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- case R.id.action_apply:
- setReturnIntent();
- return true;
- }
- return false;
- }
-
- @Override
- public void onBackPressed() {
- super.onBackPressed();
- }
-
- @Override
- protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
- if (requestCode == ManageAppKeysActivity.SELECT_APP_KEY) {
- if (resultCode == RESULT_OK) {
- final ApplicationKey appKey = data.getParcelableExtra(ManageAppKeysActivity.RESULT_APP_KEY);
- if (appKey != null) {
- mAppKeyIndex = appKey.getKeyIndex();
- mAppKeyIndexView.setText(getString(R.string.app_key_index, appKey.getKeyIndex()));
- }
- }
- }
- }
-
- @Override
- protected void onSaveInstanceState(final Bundle outState) {
- super.onSaveInstanceState(outState);
- outState.putInt(RESULT_PUBLISH_ADDRESS, mPublishAddress);
- outState.putInt(RESULT_APP_KEY_INDEX, mAppKeyIndex);
- outState.putBoolean(RESULT_CREDENTIAL_FLAG, mActionFriendshipCredentialSwitch.isChecked());
- outState.putInt(RESULT_PUBLISH_TTL, mPublishTtl);
- outState.putInt(RESULT_PUBLICATION_STEPS, mPublicationSteps);
- outState.putInt(RESULT_PUBLICATION_RESOLUTION, mPublicationResolution);
- outState.putInt(RESULT_PUBLISH_RETRANSMIT_COUNT, mPublishRetransmitCount);
- outState.putInt(RESULT_PUBLISH_RETRANSMIT_INTERVAL_STEPS, mPublishRetransmitIntervalSteps);
- }
-
- @Override
- protected void onRestoreInstanceState(final Bundle savedInstanceState) {
- super.onRestoreInstanceState(savedInstanceState);
- mPublishAddress = savedInstanceState.getInt(RESULT_PUBLISH_ADDRESS);
- mAppKeyIndex = savedInstanceState.getInt(RESULT_APP_KEY_INDEX);
- mPublishTtl = savedInstanceState.getInt(RESULT_PUBLISH_TTL);
- mPublicationSteps = savedInstanceState.getInt(RESULT_PUBLICATION_STEPS);
- mPublicationResolution = savedInstanceState.getInt(RESULT_PUBLICATION_RESOLUTION);
- mPublishRetransmitCount = savedInstanceState.getInt(RESULT_PUBLISH_RETRANSMIT_COUNT);
- mPublishRetransmitIntervalSteps = savedInstanceState.getInt(RESULT_PUBLISH_RETRANSMIT_INTERVAL_STEPS);
- updateUi(savedInstanceState.getBoolean(RESULT_CREDENTIAL_FLAG));
- }
-
- @Override
- public void setPublishAddress(final byte[] publishAddress) {
- if (publishAddress != null) {
- mPublishAddress = MeshParserUtils.unsignedBytesToInt(publishAddress[1], publishAddress[0]);
- mPublishAddressView.setText(MeshParserUtils.bytesToHex(publishAddress, true));
- }
- }
-
- @Override
- public void setPublicationResolution(final int resolution) {
- mPublicationResolution = resolution;
- mPublicationResolutionView.setText(getResolutionSummary(resolution));
- }
-
- @Override
- public void setPublicationSteps(final int publicationSteps) {
- mPublicationSteps = publicationSteps;
- mPublicationStepsView.setText(getString(R.string.publication_steps, publicationSteps));
- }
-
- @Override
- public void setRetransmitCount(final int retransmitCount) {
- mPublishRetransmitCount = retransmitCount;
- mRetransmitCountView.setText(getString(R.string.retransmit_count, retransmitCount));
- }
-
- @Override
- public void setRetransmitIntervalSteps(final int intervalSteps) {
- mPublishRetransmitIntervalSteps = intervalSteps;
- mIntervalStepsView.setText(getString(R.string.retransmit_interval_steps, intervalSteps));
- }
-
- @Override
- public void setPublishTtl(final int ttl) {
- mPublishTtl = ttl;
- updateTtlUi(ttl);
- }
-
- private void updateUi(@NonNull final MeshModel model) {
- final PublicationSettings publicationSettings = model.getPublicationSettings();
-
- //Default app key index to the 0th key in the list of bound app keys
- if (!model.getBoundAppKeyIndexes().isEmpty()) {
- mAppKeyIndex = mMeshModel.getBoundAppKeyIndexes().get(0);
- }
-
- if (publicationSettings != null) {
- mPublishAddress = publicationSettings.getPublishAddress();
- mPublishAddressView.setText(MeshAddress.formatAddress(mPublishAddress, true));
-
- mActionFriendshipCredentialSwitch.setChecked(publicationSettings.getCredentialFlag());
- mPublishTtl = publicationSettings.getPublishTtl();
-
- mPublicationSteps = publicationSettings.getPublicationSteps();
- mPublicationStepsView.setText(getString(R.string.publication_steps, mPublicationSteps));
-
- mPublicationResolution = publicationSettings.getPublicationResolution();
- mPublicationResolutionView.setText(getResolutionSummary(mPublicationResolution));
-
- mPublishRetransmitCount = publicationSettings.getPublishRetransmitCount();
- mRetransmitCountView.setText(getString(R.string.retransmit_count, mPublishRetransmitCount));
-
- mPublishRetransmitIntervalSteps = publicationSettings.getPublishRetransmitIntervalSteps();
- mIntervalStepsView.setText(getString(R.string.retransmit_interval_steps, mPublishRetransmitIntervalSteps));
-
- if (!model.getBoundAppKeyIndexes().isEmpty()) {
- mAppKeyIndex = publicationSettings.getAppKeyIndex();
- }
- updateUi(publicationSettings.getCredentialFlag());
- }
- final int ttl = mPublishTtl;
- updateTtlUi(ttl);
-
- }
-
- private void updateUi(final boolean credentialFlag) {
- mPublishAddressView.setText(MeshAddress.formatAddress(mPublishAddress, true));
- mAppKeyIndexView.setText(getString(R.string.app_key_index, mAppKeyIndex));
- mActionFriendshipCredentialSwitch.setChecked(credentialFlag);
- updateTtlUi(mPublishTtl);
- mPublicationStepsView.setText(getString(R.string.publication_steps, mPublicationSteps));
- mPublicationResolutionView.setText(getResolutionSummary(mPublicationResolution));
- mRetransmitCountView.setText(getString(R.string.retransmit_count, mPublishRetransmitCount));
- mIntervalStepsView.setText(getString(R.string.retransmit_interval_steps, mPublishRetransmitIntervalSteps));
-
- }
-
- private void updateTtlUi(final int ttl) {
- if (MeshParserUtils.isDefaultPublishTtl(ttl)) {
- mPublishTtlView.setText(getString(R.string.uses_default_ttl));
- } else {
- mPublishTtlView.setText(String.valueOf(ttl));
- }
- }
-
- private String getResolutionSummary(final int resolution) {
- switch (resolution) {
- default:
- case MeshParserUtils.RESOLUTION_100_MS:
- return getString(R.string.resolution_summary_100_ms);
- case MeshParserUtils.RESOLUTION_1_S:
- return getString(R.string.resolution_summary_1_s);
- case MeshParserUtils.RESOLUTION_10_S:
- return getString(R.string.resolution_summary_10_s);
- case MeshParserUtils.RESOLUTION_10_M:
- return getString(R.string.resolution_summary_100_m);
- }
-
- }
-
- private void setReturnIntent() {
- Intent returnIntent = new Intent();
- returnIntent.putExtra(RESULT_PUBLISH_ADDRESS, mPublishAddress);
- returnIntent.putExtra(RESULT_APP_KEY_INDEX, mAppKeyIndex);
- returnIntent.putExtra(RESULT_CREDENTIAL_FLAG, mActionFriendshipCredentialSwitch.isChecked());
- returnIntent.putExtra(RESULT_PUBLISH_TTL, mPublishTtl);
- returnIntent.putExtra(RESULT_PUBLICATION_STEPS, mPublicationSteps);
- returnIntent.putExtra(RESULT_PUBLICATION_RESOLUTION, mPublicationResolution);
- returnIntent.putExtra(RESULT_PUBLISH_RETRANSMIT_COUNT, mPublishRetransmitCount);
- returnIntent.putExtra(RESULT_PUBLISH_RETRANSMIT_INTERVAL_STEPS, mPublishRetransmitIntervalSteps);
- setResult(Activity.RESULT_OK, returnIntent);
- finish();
- }
-}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/SettingsFragment.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/SettingsFragment.java
index e139b6535..9fb552d00 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/SettingsFragment.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/SettingsFragment.java
@@ -24,16 +24,10 @@
import android.Manifest;
import android.annotation.SuppressLint;
-import android.arch.lifecycle.ViewModelProvider;
-import android.arch.lifecycle.ViewModelProviders;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.v4.app.Fragment;
-import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
@@ -45,48 +39,36 @@
import android.widget.Toast;
import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Locale;
import javax.inject.Inject;
-import no.nordicsemi.android.meshprovisioner.transport.ApplicationKey;
-import no.nordicsemi.android.meshprovisioner.transport.NetworkKey;
-import no.nordicsemi.android.meshprovisioner.utils.MeshParserUtils;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.core.content.ContextCompat;
+import androidx.fragment.app.Fragment;
+import androidx.lifecycle.ViewModelProvider;
+import androidx.lifecycle.ViewModelProviders;
import no.nordicsemi.android.nrfmeshprovisioner.di.Injectable;
-import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentFlags;
-import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentGlobalNetworkName;
-import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentGlobalTtl;
-import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentIvIndex;
-import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentKeyIndex;
import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentMeshExportMsg;
import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentMeshImport;
import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentMeshImportMsg;
-import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentNetworkKey;
+import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentNetworkName;
import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentPermissionRationale;
import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentResetNetwork;
-import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentSourceAddress;
-import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentUnicastAddress;
+import no.nordicsemi.android.nrfmeshprovisioner.keys.AppKeysActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.keys.NetKeysActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.provisioners.ProvisionersActivity;
import no.nordicsemi.android.nrfmeshprovisioner.utils.Utils;
import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.SharedViewModel;
import static android.app.Activity.RESULT_OK;
-import static no.nordicsemi.android.nrfmeshprovisioner.ManageAppKeysActivity.RESULT_APP_KEY_LIST_SIZE;
import static no.nordicsemi.android.nrfmeshprovisioner.viewmodels.NrfMeshRepository.EXPORT_PATH;
public class SettingsFragment extends Fragment implements Injectable,
- DialogFragmentGlobalNetworkName.DialogFragmentNetworkNameListener,
- DialogFragmentGlobalTtl.DialogFragmentGlobalTtlListener,
- DialogFragmentNetworkKey.DialogFragmentNetworkKeyListener,
- DialogFragmentKeyIndex.DialogFragmentKeyIndexListener,
- DialogFragmentFlags.DialogFragmentFlagsListener,
- DialogFragmentIvIndex.DialogFragmentIvIndexListener,
- DialogFragmentUnicastAddress.DialogFragmentUnicastAddressListener,
- DialogFragmentSourceAddress.DialogFragmentSourceAddressListener,
+ DialogFragmentNetworkName.DialogFragmentNetworkNameListener,
DialogFragmentResetNetwork.DialogFragmentResetNetworkListener,
DialogFragmentMeshImport.DialogFragmentNetworkImportListener,
-DialogFragmentPermissionRationale.StoragePermissionListener {
+ DialogFragmentPermissionRationale.StoragePermissionListener {
private static final int REQUEST_STORAGE_PERMISSION = 2023; // random number
private static final int READ_FILE_REQUEST_CODE = 42;
@@ -96,7 +78,6 @@ public class SettingsFragment extends Fragment implements Injectable,
@Inject
ViewModelProvider.Factory mViewModelFactory;
- private TextView manageAppKeysView;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
@@ -107,135 +88,81 @@ public void onCreate(@Nullable Bundle savedInstanceState) {
@SuppressWarnings("ConstantConditions")
@Nullable
@Override
- public View onCreateView(@NonNull final LayoutInflater inflater, @Nullable final ViewGroup container, @Nullable final Bundle savedInstanceState) {
+ public View onCreateView(@NonNull final LayoutInflater inflater,
+ @Nullable final ViewGroup container, @Nullable final Bundle savedInstanceState) {
@SuppressLint("InflateParams") final View rootView = inflater.inflate(R.layout.fragment_settings, null);
-
mViewModel = ViewModelProviders.of(getActivity(), mViewModelFactory).get(SharedViewModel.class);
// Set up views
final View containerNetworkName = rootView.findViewById(R.id.container_network_name);
- containerNetworkName.findViewById(R.id.image).setBackground(ContextCompat.getDrawable(getContext(), R.drawable.ic_lan_black_alpha_24dp));
+ containerNetworkName.findViewById(R.id.image)
+ .setBackground(ContextCompat.getDrawable(requireContext(), R.drawable.ic_label_black_alpha_24dp));
final TextView networkNameTitle = containerNetworkName.findViewById(R.id.title);
- networkNameTitle.setText(R.string.summary_global_network_name);
+ networkNameTitle.setText(R.string.title_network_name);
final TextView networkNameView = containerNetworkName.findViewById(R.id.text);
+ networkNameView.setVisibility(View.VISIBLE);
containerNetworkName.setOnClickListener(v -> {
- final DialogFragmentGlobalNetworkName dialogFragmentNetworkKey = DialogFragmentGlobalNetworkName.newInstance(networkNameView.getText().toString());
- dialogFragmentNetworkKey.show(getChildFragmentManager(), null);
- });
-
- final View containerGlobalTtl = rootView.findViewById(R.id.container_global_ttl);
- containerGlobalTtl.findViewById(R.id.image).setBackground(ContextCompat.getDrawable(getContext(), R.drawable.ic_timer));
- final TextView globalTtlTitle = containerGlobalTtl.findViewById(R.id.title);
- globalTtlTitle.setText(R.string.summary_global_ttl);
- final TextView globalTtlView = containerGlobalTtl.findViewById(R.id.text);
- containerGlobalTtl.setOnClickListener(v -> {
- final DialogFragmentGlobalTtl dialogFragmentGlobalTtl = DialogFragmentGlobalTtl.newInstance(globalTtlView.getText().toString());
- dialogFragmentGlobalTtl.show(getChildFragmentManager(), null);
- });
-
- final View containerSourceAddress = rootView.findViewById(R.id.container_src_address);
- containerSourceAddress.findViewById(R.id.image).setBackground(ContextCompat.getDrawable(getContext(), R.drawable.ic_lan_black_alpha_24dp));
- final TextView containerSource = containerSourceAddress.findViewById(R.id.title);
- containerSource.setText(R.string.summary_src_address);
- final TextView sourceAddressView = containerSourceAddress.findViewById(R.id.text);
- containerSourceAddress.setOnClickListener(v -> {
- final byte[] configuratorSrc = mViewModel.getMeshNetworkLiveData().getProvisionerAddress();
- final int src = (configuratorSrc[0] & 0xFF) << 8 | (configuratorSrc[1] & 0xFF);
- final DialogFragmentSourceAddress dialogFragmentSrc = DialogFragmentSourceAddress.newInstance(src);
- dialogFragmentSrc.show(getChildFragmentManager(), null);
- });
-
- final View containerKey = rootView.findViewById(R.id.container_key);
- containerKey.findViewById(R.id.image).setBackground(ContextCompat.getDrawable(getContext(), R.drawable.ic_vpn_key_black_alpha_24dp));
- final TextView keyTitle = containerKey.findViewById(R.id.title);
- keyTitle.setText(R.string.summary_key);
- final TextView keyView = containerKey.findViewById(R.id.text);
- containerKey.setOnClickListener(v -> {
- final NetworkKey networkKey = mViewModel.getMeshNetworkLiveData().getPrimaryNetworkKey();
- final DialogFragmentNetworkKey dialogFragmentNetworkKey = DialogFragmentNetworkKey.newInstance(networkKey);
- dialogFragmentNetworkKey.show(getChildFragmentManager(), null);
- });
-
- final View containerKeyIndex = rootView.findViewById(R.id.container_index);
- containerKeyIndex.findViewById(R.id.image).setBackground(ContextCompat.getDrawable(getContext(), R.drawable.ic_numeric));
- final TextView keyIndexTitle = containerKeyIndex.findViewById(R.id.title);
- keyIndexTitle.setText(R.string.summary_index);
- final TextView keyIndexView = containerKeyIndex.findViewById(R.id.text);
- containerKeyIndex.setOnClickListener(v -> {
- final int keyIndex = mViewModel.getMeshNetworkLiveData().getKeyIndex();
- final DialogFragmentKeyIndex dialogFragmentNetworkKey = DialogFragmentKeyIndex.newInstance(keyIndex);
- dialogFragmentNetworkKey.show(getChildFragmentManager(), null);
- });
-
- final View containerFlags = rootView.findViewById(R.id.container_flags);
- containerFlags.findViewById(R.id.image).setBackground(ContextCompat.getDrawable(getContext(), R.drawable.ic_flag));
- final TextView flagsTitle = containerFlags.findViewById(R.id.title);
- flagsTitle.setText(R.string.summary_flags);
- final TextView flagsView = containerFlags.findViewById(R.id.text);
- containerFlags.setOnClickListener(v -> {
- final int flags = mViewModel.getMeshNetworkLiveData().getFlags();
- final int keyRefreshFlag = MeshParserUtils.getBitValue(flags, 0);
- final int ivUpdateFlag = MeshParserUtils.getBitValue(flags, 1);
- final DialogFragmentFlags dialogFragmentFlags = DialogFragmentFlags.newInstance(keyRefreshFlag, ivUpdateFlag);
- dialogFragmentFlags.show(getChildFragmentManager(), null);
+ final DialogFragmentNetworkName fragment = DialogFragmentNetworkName.
+ newInstance(networkNameView.getText().toString());
+ fragment.show(getChildFragmentManager(), null);
});
- final View containerIVIndex = rootView.findViewById(R.id.container_iv_index);
- containerIVIndex.findViewById(R.id.image).setBackground(ContextCompat.getDrawable(getContext(), R.drawable.ic_list));
- final TextView ivIndexTitle = containerIVIndex.findViewById(R.id.title);
- ivIndexTitle.setText(R.string.title_iv_index);
- final TextView ivIndexView = containerIVIndex.findViewById(R.id.text);
- containerIVIndex.setOnClickListener(v -> {
- final int ivIndex = mViewModel.getMeshNetworkLiveData().getIvIndex();
- final DialogFragmentIvIndex dialogFragmentFlags = DialogFragmentIvIndex.newInstance(ivIndex);
- dialogFragmentFlags.show(getChildFragmentManager(), null);
+ final View containerProvisioner = rootView.findViewById(R.id.container_provisioners);
+ containerProvisioner.findViewById(R.id.image)
+ .setBackground(ContextCompat.getDrawable(requireContext(), R.drawable.ic_folder_provisioner_black_alpha_24dp));
+ final TextView provisionerTitle = containerProvisioner.findViewById(R.id.title);
+ final TextView provisionerSummary = containerProvisioner.findViewById(R.id.text);
+ provisionerSummary.setVisibility(View.VISIBLE);
+ provisionerTitle.setText(R.string.title_provisioners);
+ containerProvisioner.setOnClickListener(v -> {
+ final Intent intent = new Intent(requireContext(), ProvisionersActivity.class);
+ startActivity(intent);
});
- final View containerUnicastAddress = rootView.findViewById(R.id.container_supported_algorithm);
- containerUnicastAddress.findViewById(R.id.image).setBackground(ContextCompat.getDrawable(getContext(), R.drawable.ic_lan_black_alpha_24dp));
- final TextView unicastAddressTitle = containerUnicastAddress.findViewById(R.id.title);
- unicastAddressTitle.setText(R.string.summary_unicast_address);
- final TextView unicastAddressView = containerUnicastAddress.findViewById(R.id.text);
- containerUnicastAddress.setOnClickListener(v -> {
- final int unicastAddress = mViewModel.getMeshNetworkLiveData().getValue().getUnicastAddress();
- final DialogFragmentUnicastAddress dialogFragmentFlags = DialogFragmentUnicastAddress.newInstance(unicastAddress);
- dialogFragmentFlags.show(getChildFragmentManager(), null);
+ final View containerNetKey = rootView.findViewById(R.id.container_net_keys);
+ containerNetKey.findViewById(R.id.image)
+ .setBackground(ContextCompat.getDrawable(requireContext(), R.drawable.ic_folder_key_black_24dp_alpha));
+ final TextView keyTitle = containerNetKey.findViewById(R.id.title);
+ keyTitle.setText(R.string.title_net_keys);
+ final TextView netKeySummary = containerNetKey.findViewById(R.id.text);
+ netKeySummary.setVisibility(View.VISIBLE);
+ containerNetKey.setOnClickListener(v -> {
+ final Intent intent = new Intent(requireContext(), NetKeysActivity.class);
+ intent.putExtra(Utils.EXTRA_DATA, Utils.MANAGE_NET_KEY);
+ startActivity(intent);
});
- final View containerManageAppKeys = rootView.findViewById(R.id.container_app_keys);
- containerManageAppKeys.findViewById(R.id.image).setBackground(ContextCompat.getDrawable(getContext(), R.drawable.ic_folder_key_black_24dp_alpha));
- final TextView manageAppKeys = containerManageAppKeys.findViewById(R.id.title);
- manageAppKeys.setText(R.string.summary_app_keys);
- manageAppKeysView = containerManageAppKeys.findViewById(R.id.text);
- containerManageAppKeys.setOnClickListener(v -> {
- final Intent intent = new Intent(getActivity(), ManageAppKeysActivity.class);
- intent.putExtra(Utils.EXTRA_DATA, Utils.MANAGE_APP_KEY);
- startActivityForResult(intent, ManageAppKeysActivity.MANAGE_APP_KEYS);
+ final View containerAppKey = rootView.findViewById(R.id.container_app_keys);
+ containerAppKey.findViewById(R.id.image).
+ setBackground(ContextCompat.getDrawable(requireContext(), R.drawable.ic_folder_key_black_24dp_alpha));
+ ((TextView) containerAppKey.findViewById(R.id.title)).setText(R.string.title_app_keys);
+ final TextView appKeySummary = containerAppKey.findViewById(R.id.text);
+ appKeySummary.setVisibility(View.VISIBLE);
+ containerAppKey.setOnClickListener(v -> {
+ final Intent intent = new Intent(requireContext(), AppKeysActivity.class);
+ startActivity(intent);
});
final View containerAbout = rootView.findViewById(R.id.container_version);
- containerAbout.findViewById(R.id.image).setBackground(ContextCompat.getDrawable(getContext(), R.drawable.ic_puzzle));
+ containerAbout.setClickable(false);
+ containerAbout.findViewById(R.id.image).
+ setBackground(ContextCompat.getDrawable(requireContext(), R.drawable.ic_puzzle));
final TextView versionTitle = containerAbout.findViewById(R.id.title);
- versionTitle.setText(R.string.summary_verion);
+ versionTitle.setText(R.string.summary_version);
final TextView version = containerAbout.findViewById(R.id.text);
+ version.setVisibility(View.VISIBLE);
try {
- version.setText(getContext().getPackageManager().getPackageInfo(getContext().getPackageName(), 0).versionName);
+ version.setText(getContext().getPackageManager().getPackageInfo(requireContext().getPackageName(), 0).versionName);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
- mViewModel.getMeshNetworkLiveData().observe(this, meshNetworkLiveData -> {
+ mViewModel.getNetworkLiveData().observe(this, meshNetworkLiveData -> {
if (meshNetworkLiveData != null) {
networkNameView.setText(meshNetworkLiveData.getNetworkName());
- globalTtlView.setText(String.valueOf(meshNetworkLiveData.getGlobalTtl()));
- final NetworkKey key = meshNetworkLiveData.getPrimaryNetworkKey();
- keyView.setText(MeshParserUtils.bytesToHex(key.getKey(), false));
- keyIndexView.setText(getString(R.string.hex_format, String.format(Locale.US, "%03X", key.getKeyIndex())));
- flagsView.setText(parseFlagsMessage(meshNetworkLiveData.getFlags()));
- ivIndexView.setText(getString(R.string.hex_format, String.format(Locale.US, "%08X", meshNetworkLiveData.getIvIndex())));
- unicastAddressView.setText(getString(R.string.hex_format, String.format(Locale.US, "%04X", meshNetworkLiveData.getUnicastAddress())));
- manageAppKeysView.setText(getString(R.string.app_key_count, meshNetworkLiveData.getAppKeys().size()));
- sourceAddressView.setText(MeshParserUtils.bytesToHex(meshNetworkLiveData.getProvisionerAddress(), true));
+ netKeySummary.setText(String.valueOf(meshNetworkLiveData.getNetworkKeys().size()));
+ provisionerSummary.setText(String.valueOf(meshNetworkLiveData.getProvisioners().size()));
+ appKeySummary.setText(String.valueOf(meshNetworkLiveData.getAppKeys().size()));
}
});
@@ -260,17 +187,12 @@ public View onCreateView(@NonNull final LayoutInflater inflater, @Nullable final
}
@Override
- public void onStart() {
- super.onStart();
- }
-
- @Override
- public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
+ public void onCreateOptionsMenu(@NonNull final Menu menu, @NonNull final MenuInflater inflater) {
inflater.inflate(R.menu.network_settings, menu);
}
@Override
- public boolean onOptionsItemSelected(final MenuItem item) {
+ public boolean onOptionsItemSelected(@NonNull final MenuItem item) {
final int id = item.getItemId();
switch (id) {
case R.id.action_import_network:
@@ -291,97 +213,35 @@ public boolean onOptionsItemSelected(final MenuItem item) {
return false;
}
+ @SuppressWarnings("ConstantConditions")
@Override
public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
super.onActivityResult(requestCode, resultCode, data);
- switch (requestCode) {
- case ManageAppKeysActivity.MANAGE_APP_KEYS:
- if (resultCode == RESULT_OK) {
- final int size = data.getExtras().getInt(RESULT_APP_KEY_LIST_SIZE);
- manageAppKeysView.setText(getString(R.string.app_key_count, size));
+ if (requestCode == READ_FILE_REQUEST_CODE) {
+ if (resultCode == RESULT_OK) {
+ if (data != null) {
+ final Uri uri = data.getData();
+ mViewModel.getMeshManagerApi().importMeshNetwork(uri);
}
- break;
- case READ_FILE_REQUEST_CODE:
- if (resultCode == RESULT_OK) {
- if (data != null) {
- final Uri uri = data.getData();
- mViewModel.importMeshNetwork(uri);
- }
- } else {
- Log.e(TAG, "Error while opening file browser");
- }
- break;
+ } else {
+ Log.e(TAG, "Error while opening file browser");
+ }
}
}
@Override
public void onRequestPermissionsResult(final int requestCode, @NonNull final String[] permissions, @NonNull final int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
- switch (requestCode){
- case REQUEST_STORAGE_PERMISSION:
- if(PackageManager.PERMISSION_GRANTED != grantResults[0]){
- Toast.makeText(getContext(), getString(R.string.ext_storage_permission_denied), Toast.LENGTH_LONG).show();
- }
- break;
+ if (requestCode == REQUEST_STORAGE_PERMISSION) {
+ if (PackageManager.PERMISSION_GRANTED != grantResults[0]) {
+ Toast.makeText(getContext(), getString(R.string.ext_storage_permission_denied), Toast.LENGTH_LONG).show();
+ }
}
}
- private String parseFlagsMessage(final int flags) {
- final int keyRefreshFlag = MeshParserUtils.getBitValue(flags, 0);
- final int ivUpdateFlag = MeshParserUtils.getBitValue(flags, 1);
- final StringBuilder flagsText = new StringBuilder();
-
- if (keyRefreshFlag == 0)
- flagsText.append(getString(R.string.key_refresh_phase_0)).append(", ");
- else
- flagsText.append(getString(R.string.key_refresh_phase_2)).append(", ");
-
- if (ivUpdateFlag == 0)
- flagsText.append(getString(R.string.normal_operation));
- else
- flagsText.append(getString(R.string.iv_update_active));
-
- return flagsText.toString();
- }
-
- @Override
- public void onNetworkNameEntered(final String networkName) {
- mViewModel.getMeshNetworkLiveData().setNetworkName(networkName);
- }
-
- @Override
- public void onGlobalTtlEntered(final int globalTtl) {
- mViewModel.getMeshNetworkLiveData().setGlobalTtl(globalTtl);
- }
-
- @Override
- public void onNetworkKeyGenerated(final String networkKey) {
- mViewModel.getMeshNetworkLiveData().setPrimaryNetworkKey(networkKey);
- }
-
- @Override
- public void onKeyIndexGenerated(final int keyIndex) {
- mViewModel.getMeshNetworkLiveData().setKeyIndex(keyIndex);
- }
-
- @Override
- public void onFlagsSelected(final int keyRefreshFlag, final int ivUpdateFlag) {
- mViewModel.getMeshNetworkLiveData().setFlags(MeshParserUtils.parseUpdateFlags(keyRefreshFlag, ivUpdateFlag));
- }
-
- @Override
- public void setIvIndex(final int ivIndex) {
- mViewModel.getMeshNetworkLiveData().setIvIndex(ivIndex);
- }
-
- @Override
- public void setUnicastAddress(final int unicastAddress) {
- mViewModel.getMeshNetworkLiveData().setUnicastAddress(unicastAddress);
- }
-
@Override
- public boolean setSourceAddress(final int sourceAddress) {
- return mViewModel.getMeshNetworkLiveData().setProvisionerAddress(sourceAddress);
+ public void onNetworkNameEntered(@NonNull final String name) {
+ mViewModel.getNetworkLiveData().setNetworkName(name);
}
@Override
@@ -403,7 +263,7 @@ public void requestPermission() {
/**
* Fires an intent to spin up the "file chooser" UI to select a file
*/
- public void performFileSearch() {
+ private void performFileSearch() {
final Intent intent;
if (Utils.isKitkatOrAbove()) {
intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
@@ -426,7 +286,7 @@ private void handleNetworkExport() {
fragmentPermissionRationale.show(getChildFragmentManager(), null);
} else {
final File f = new File(EXPORT_PATH);
- if(!f.exists()) {
+ if (!f.exists()) {
f.mkdirs();
}
mViewModel.getMeshManagerApi().exportMeshNetwork(EXPORT_PATH);
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/SplashScreenActivity.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/SplashScreenActivity.java
index a6e23ce08..157decf04 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/SplashScreenActivity.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/SplashScreenActivity.java
@@ -22,11 +22,11 @@
package no.nordicsemi.android.nrfmeshprovisioner;
-import android.arch.lifecycle.ViewModelProvider;
-import android.arch.lifecycle.ViewModelProviders;
+import androidx.lifecycle.ViewModelProvider;
+import androidx.lifecycle.ViewModelProviders;
import android.content.Intent;
import android.os.Bundle;
-import android.support.v7.app.AppCompatActivity;
+import androidx.appcompat.app.AppCompatActivity;
import javax.inject.Inject;
@@ -34,7 +34,7 @@
import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.SplashViewModel;
public class SplashScreenActivity extends AppCompatActivity implements Injectable {
- private static final int DURATION = 1000;
+
@Inject
ViewModelProvider.Factory mViewModelFactory;
@@ -43,7 +43,7 @@ protected void onCreate(final Bundle savedInstanceState) {
setContentView(R.layout.activity_splash_screen);
super.onCreate(savedInstanceState);
final SplashViewModel viewModel = ViewModelProviders.of(SplashScreenActivity.this, mViewModelFactory).get(SplashViewModel.class);
- viewModel.getMeshNetworkLiveData().observe(this,meshNetworkLiveData -> {
+ viewModel.getNetworkLiveData().observe(this, meshNetworkLiveData -> {
if(meshNetworkLiveData != null && meshNetworkLiveData.getMeshNetwork() != null) {
navigateActivity();
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/AddressTypeAdapter.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/AddressTypeAdapter.java
new file mode 100644
index 000000000..a97c40787
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/AddressTypeAdapter.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2018, Nordic Semiconductor
+ * 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 no.nordicsemi.android.nrfmeshprovisioner.adapter;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import butterknife.BindView;
+import butterknife.ButterKnife;
+import no.nordicsemi.android.nrfmeshprovisioner.R;
+import no.nordicsemi.android.nrfmeshprovisioner.utils.AddressTypes;
+
+public class AddressTypeAdapter extends BaseAdapter {
+
+ private final AddressTypes[] mAddressTypes;
+ private final Context mContext;
+
+ public AddressTypeAdapter(@NonNull final Context context,
+ @NonNull final AddressTypes[] addressTypes) {
+ this.mContext = context;
+ mAddressTypes = addressTypes;
+ notifyDataSetChanged();
+ }
+
+ @Override
+ public int getCount() {
+ return mAddressTypes.length;
+ }
+
+ @Override
+ public AddressTypes getItem(final int position) {
+ return mAddressTypes[position];
+ }
+
+ @Override
+ public long getItemId(final int position) {
+ return position;
+ }
+
+ @Override
+ public View getView(final int position, final View convertView, final ViewGroup parent) {
+ View view = convertView;
+ if (mAddressTypes.length > 0) {
+ ViewHolder viewHolder;
+ if (view == null) {
+ view = LayoutInflater.from(mContext).inflate(R.layout.address_type_item, parent, false);
+ viewHolder = new ViewHolder(view);
+ view.setTag(viewHolder);
+ } else {
+ viewHolder = (ViewHolder) view.getTag();
+ }
+
+ final AddressTypes addressType = mAddressTypes[position];
+ if (addressType == AddressTypes.GROUP_ADDRESS) {
+ viewHolder.addressName.setText(R.string.action_groups);
+ } else {
+ viewHolder.addressName.setText(AddressTypes.getTypeName(addressType));
+ }
+ return view;
+ } else {
+ view = LayoutInflater.from(mContext).inflate(R.layout.no_groups_layout, parent, false);
+ return view;
+ }
+ }
+
+ public final class ViewHolder {
+
+ @BindView(R.id.address_name)
+ TextView addressName;
+
+ private ViewHolder(final View view) {
+ ButterKnife.bind(this, view);
+ }
+ }
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/AuthenticationOOBMethodsAdapter.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/AuthenticationOOBMethodsAdapter.java
index 689277948..eaaaf921b 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/AuthenticationOOBMethodsAdapter.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/AuthenticationOOBMethodsAdapter.java
@@ -23,7 +23,7 @@
package no.nordicsemi.android.nrfmeshprovisioner.adapter;
import android.content.Context;
-import android.support.annotation.NonNull;
+import androidx.annotation.NonNull;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -40,8 +40,8 @@
public class AuthenticationOOBMethodsAdapter extends BaseAdapter {
- private final ArrayList mOOBTypes = new ArrayList<>();
private final Context mContext;
+ private final ArrayList mOOBTypes = new ArrayList<>();
/**
* Constructs AuthenticationOOBMethodsAdapter
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/ElementAdapterDetails.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/ElementAdapterDetails.java
deleted file mode 100644
index 0ee410e57..000000000
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/ElementAdapterDetails.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (c) 2018, Nordic Semiconductor
- * 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 no.nordicsemi.android.nrfmeshprovisioner.adapter;
-
-import android.content.Context;
-import android.support.annotation.NonNull;
-import android.support.constraint.ConstraintLayout;
-import android.support.v4.content.ContextCompat;
-import android.support.v7.widget.RecyclerView;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import butterknife.BindView;
-import butterknife.ButterKnife;
-import no.nordicsemi.android.meshprovisioner.models.VendorModel;
-import no.nordicsemi.android.meshprovisioner.transport.Element;
-import no.nordicsemi.android.meshprovisioner.transport.MeshModel;
-import no.nordicsemi.android.meshprovisioner.utils.CompositionDataParser;
-import no.nordicsemi.android.meshprovisioner.utils.MeshAddress;
-import no.nordicsemi.android.nrfmeshprovisioner.R;
-
-public class ElementAdapterDetails extends RecyclerView.Adapter {
-
- private final Context mContext;
- private final List mElements;
- private OnItemClickListener mOnItemClickListener;
-
- public ElementAdapterDetails(@NonNull final Context mContext, @NonNull final List elements) {
- this.mContext = mContext;
- mElements = elements;
- }
-
-
- public void setOnItemClickListener(final ElementAdapterDetails.OnItemClickListener listener) {
- mOnItemClickListener = listener;
- }
-
- @NonNull
- @Override
- public ViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int viewType) {
- final View layoutView = LayoutInflater.from(mContext).inflate(R.layout.element_item_details, parent, false);
- return new ViewHolder(layoutView);
- }
-
- @Override
- public void onBindViewHolder(@NonNull final ViewHolder holder, final int position) {
- final Element element = mElements.get(position);
- holder.mElementContainer.setTag(element);
- final int modelCount = element.getSigModelCount() + element.getVendorModelCount();
- holder.mElementTitle.setText(mContext.getString(R.string.element_address, MeshAddress.formatAddress(element.getElementAddress(), false)));
- holder.mElementSubtitle.setText(mContext.getString(R.string.model_count, modelCount));
-
- final List models = new ArrayList<>(element.getMeshModels().values());
- inflateModelViews(holder, models);
-
- }
-
- private void inflateModelViews(final ElementAdapterDetails.ViewHolder holder, final List models){
- //Remove all child views to avoid duplicating
- holder.mModelContainer.removeAllViews();
- for(MeshModel model : models) {
- final View modelView = LayoutInflater.from(mContext).inflate(R.layout.model_item_details, holder.mElementContainer, false);
- modelView.setTag(model.getModelId());
- final TextView modelNameView = modelView.findViewById(R.id.address);
- final TextView modelIdView = modelView.findViewById(R.id.model_id);
- modelNameView.setText(model.getModelName());
- if(model instanceof VendorModel){
- modelIdView.setText(mContext.getString(R.string.format_vendor_model_id, CompositionDataParser.formatModelIdentifier(model.getModelId(), true)));
- } else {
- modelIdView.setText(mContext.getString(R.string.format_sig_model_id, CompositionDataParser.formatModelIdentifier((short) model.getModelId(), true)));
- }
-
- holder.mModelContainer.addView(modelView);
- }
- }
-
- @Override
- public int getItemCount() {
- return mElements.size();
- }
-
- public boolean isEmpty() {
- return getItemCount() == 0;
- }
-
- @FunctionalInterface
- public interface OnItemClickListener {
- void onItemClick(final int position);
- }
-
- final class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
- @BindView(R.id.element_item_container)
- ConstraintLayout mElementContainer;
- @BindView(R.id.element_title)
- TextView mElementTitle;
- @BindView(R.id.element_subtitle)
- TextView mElementSubtitle;
- @BindView(R.id.element_expand)
- ImageView mElementExpand;
- @BindView(R.id.model_container)
- LinearLayout mModelContainer;
-
- private ViewHolder(final View view) {
- super(view);
- ButterKnife.bind(this, view);
- mElementContainer.setOnClickListener(this);
-
- }
-
- @Override
- public void onClick(final View v) {
- switch (v.getId()){
- case R.id.element_item_container:
- if(mModelContainer.getVisibility() == View.VISIBLE){
- mElementExpand.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.ic_round_expand_more_black_alpha_24dp));
- mModelContainer.setVisibility(View.GONE);
- } else {
- mElementExpand.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.ic_round_expand_less_black_alpha_24dp));
- mModelContainer.setVisibility(View.VISIBLE);
- }
- mOnItemClickListener.onItemClick(getAdapterPosition());
- break;
- default:
- break;
- }
- }
- }
-}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/FilterAddressAdapter.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/FilterAddressAdapter.java
index d0c456027..1c7ff8563 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/FilterAddressAdapter.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/FilterAddressAdapter.java
@@ -22,11 +22,8 @@
package no.nordicsemi.android.nrfmeshprovisioner.adapter;
-import android.arch.lifecycle.LifecycleOwner;
-import android.arch.lifecycle.LiveData;
import android.content.Context;
-import android.support.annotation.NonNull;
-import android.support.v7.widget.RecyclerView;
+import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -34,10 +31,12 @@
import java.util.ArrayList;
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
import butterknife.BindView;
import butterknife.ButterKnife;
-import no.nordicsemi.android.meshprovisioner.transport.ProvisionedMeshNode;
import no.nordicsemi.android.meshprovisioner.utils.AddressArray;
+import no.nordicsemi.android.meshprovisioner.utils.MeshAddress;
import no.nordicsemi.android.meshprovisioner.utils.MeshParserUtils;
import no.nordicsemi.android.meshprovisioner.utils.ProxyFilter;
import no.nordicsemi.android.nrfmeshprovisioner.R;
@@ -45,23 +44,28 @@
public class FilterAddressAdapter extends RecyclerView.Adapter {
- private final ArrayList mAddresses;// = new ArrayList<>();
+ private final ArrayList mAddresses = new ArrayList<>();
private final Context mContext;
private OnItemClickListener mOnItemClickListener;
- public FilterAddressAdapter(@NonNull final Context context, @NonNull final LiveData meshNodeLiveData) {
+ public FilterAddressAdapter(@NonNull final Context context) {
this.mContext = context;
- mAddresses = new ArrayList<>();
- meshNodeLiveData.observe((LifecycleOwner) context, meshNode -> {
- if (meshNode != null) {
- final ProxyFilter proxyFilter = meshNode.getProxyFilter();
- if (proxyFilter != null) {
- mAddresses.clear();
- mAddresses.addAll(proxyFilter.getAddresses());
- notifyDataSetChanged();
- }
- }
- });
+ }
+
+ public void updateData(@NonNull final ProxyFilter filter){
+ mAddresses.clear();
+ mAddresses.addAll(filter.getAddresses());
+ notifyDataSetChanged();
+ }
+
+ public void clearData(){
+ mAddresses.clear();
+ notifyDataSetChanged();
+ }
+
+ public void clearRow(final int position){
+ mAddresses.remove(position);
+ notifyDataSetChanged();
}
public void setOnItemClickListener(final FilterAddressAdapter.OnItemClickListener listener) {
@@ -76,17 +80,15 @@ public FilterAddressAdapter.ViewHolder onCreateViewHolder(@NonNull final ViewGro
}
@Override
- public void onBindViewHolder(@NonNull final FilterAddressAdapter.ViewHolder holder, final int position) {
- if (mAddresses.size() > 0) {
- final byte[] address = mAddresses.get(position).getAddress();
- holder.address.setText(MeshParserUtils.bytesToHex(address, true));
- if (MeshParserUtils.isValidSubscriptionAddress(address)) {
- holder.addressTitle.setText(R.string.title_group_address);
- } else if (MeshParserUtils.isValidUnicastAddress(address)) {
- holder.addressTitle.setText(R.string.title_unicast_address);
- } else {
- holder.addressTitle.setText(R.string.address);
- }
+ public void onBindViewHolder(@NonNull final FilterAddressAdapter.ViewHolder holder, int position) {
+ final byte[] address = mAddresses.get(position).getAddress();
+ holder.address.setText(MeshParserUtils.bytesToHex(address, true));
+ if (MeshAddress.isValidGroupAddress(address)) {
+ holder.addressTitle.setText(R.string.title_group_address);
+ } else if (MeshAddress.isValidUnicastAddress(address)) {
+ holder.addressTitle.setText(R.string.title_unicast_address);
+ } else if (MeshAddress.isValidVirtualAddress(address)) {
+ holder.addressTitle.setText(R.string.virtual_address);
}
}
@@ -113,7 +115,7 @@ public final class ViewHolder extends RemovableViewHolder {
@BindView(R.id.address_id)
TextView addressTitle;
- @BindView(R.id.address)
+ @BindView(R.id.title)
TextView address;
private ViewHolder(final View view) {
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/FilterAddressAdapter1.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/FilterAddressAdapter1.java
index d8fb06117..1b7b68ddb 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/FilterAddressAdapter1.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/FilterAddressAdapter1.java
@@ -23,8 +23,8 @@
package no.nordicsemi.android.nrfmeshprovisioner.adapter;
import android.content.Context;
-import android.support.annotation.NonNull;
-import android.support.v7.widget.RecyclerView;
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -44,7 +44,7 @@ public class FilterAddressAdapter1 extends RecyclerView.Adapter mAddresses;
private final Context mContext;
- public FilterAddressAdapter1(@NonNull final Context context, final ArrayList addresses) {
+ public FilterAddressAdapter1(@NonNull final Context context, @NonNull final ArrayList addresses) {
this.mContext = context;
this.mAddresses = addresses;
}
@@ -85,7 +85,7 @@ public interface OnItemClickListener {
final class ViewHolder extends RecyclerView.ViewHolder {
- @BindView(R.id.address)
+ @BindView(R.id.title)
TextView address;
@BindView(R.id.img_delete)
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/GroupAdapter.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/GroupAdapter.java
index d15c38cef..8d35bce5e 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/GroupAdapter.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/GroupAdapter.java
@@ -23,8 +23,8 @@
package no.nordicsemi.android.nrfmeshprovisioner.adapter;
import android.content.Context;
-import android.support.annotation.NonNull;
-import android.support.v7.widget.RecyclerView;
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -49,19 +49,18 @@ public class GroupAdapter extends RecyclerView.Adapter
private OnItemClickListener mOnItemClickListener;
private MeshNetwork mNetwork;
- public GroupAdapter(final Context context/*, final MeshNetwork meshNetwork, final List groupLiveData*/) {
+ public GroupAdapter(@NonNull final Context context) {
this.mContext = context;
}
- public void updateAdapter(final MeshNetwork meshNetwork, final List groups){
-
+ public void updateAdapter(@NonNull final MeshNetwork meshNetwork, @NonNull final List groups) {
mNetwork = meshNetwork;
mGroups.clear();
mGroups.addAll(groups);
notifyDataSetChanged();
}
- public void setOnItemClickListener(final OnItemClickListener listener) {
+ public void setOnItemClickListener(@NonNull final OnItemClickListener listener) {
mOnItemClickListener = listener;
}
@@ -79,9 +78,10 @@ public void onBindViewHolder(@NonNull final GroupAdapter.ViewHolder holder, fina
if (group != null) {
final List models = mNetwork.getModels(group);
holder.groupName.setText(group.getName());
- final String addressSummary = "Address: " + MeshAddress.formatAddress(group.getGroupAddress(), true);
- holder.groupAddress.setText(addressSummary);
- holder.groupDeviceCount.setText(mContext.getString(R.string.group_device_count, models.size()));
+ holder.groupAddress.setText(mContext.
+ getString(R.string.group_address_summary, MeshAddress.formatAddress(group.getAddress(), true)));
+ holder.groupDeviceCount.setText(mContext.getResources().
+ getQuantityString(R.plurals.device_count, models.size(), models.size()));
}
}
}
@@ -102,10 +102,11 @@ public boolean isEmpty() {
/**
* Returns the number of models associated to the group in a particular position
+ *
* @param position position
*/
- public int getModelCount(final int position){
- if(position >= 0 && !mGroups.isEmpty() && position < mGroups.size()) {
+ public int getModelCount(final int position) {
+ if (position >= 0 && !mGroups.isEmpty() && position < mGroups.size()) {
final Group group = mGroups.get(position);
return mNetwork.getModels(group).size();
}
@@ -130,7 +131,7 @@ private ViewHolder(final View view) {
ButterKnife.bind(this, view);
view.findViewById(R.id.container).setOnClickListener(v -> {
if (mOnItemClickListener != null) {
- mOnItemClickListener.onItemClick(mGroups.get(getAdapterPosition()).getGroupAddress());
+ mOnItemClickListener.onItemClick(mGroups.get(getAdapterPosition()).getAddress());
}
});
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/GroupAdapterSpinner.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/GroupAdapterSpinner.java
index 184271419..75feeb1ad 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/GroupAdapterSpinner.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/GroupAdapterSpinner.java
@@ -23,12 +23,11 @@
package no.nordicsemi.android.nrfmeshprovisioner.adapter;
import android.content.Context;
-import android.support.annotation.NonNull;
+import androidx.annotation.NonNull;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
-import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;
@@ -44,7 +43,6 @@ public class GroupAdapterSpinner extends BaseAdapter {
private final ArrayList mGroups = new ArrayList<>();
private final Context mContext;
- private OnItemClickListener mOnItemClickListener;
public GroupAdapterSpinner(@NonNull final Context context, @NonNull final List groups) {
this.mContext = context;
@@ -53,10 +51,6 @@ public GroupAdapterSpinner(@NonNull final Context context, @NonNull final List mAddresses = new ArrayList<>();
- private OnItemClickListener mOnItemClickListener;
- public GroupAddressAdapter(final BaseModelConfigurationActivity context, final MeshNetwork network, final LiveData meshModelLiveData) {
+ public GroupAddressAdapter(@NonNull final Context context, @NonNull final MeshNetwork network, @NonNull final LiveData meshModelLiveData) {
this.mContext = context;
this.network = network;
- meshModelLiveData.observe(context, meshModel -> {
- if(meshModel != null) {
+ meshModelLiveData.observe((LifecycleOwner) context, meshModel -> {
+ if (meshModel != null) {
final List tempAddresses = meshModel.getSubscribedAddresses();
if (tempAddresses != null) {
mAddresses.clear();
@@ -68,10 +67,6 @@ public GroupAddressAdapter(final BaseModelConfigurationActivity context, final M
});
}
- public void setOnItemClickListener(final GroupAddressAdapter.OnItemClickListener listener) {
- mOnItemClickListener = listener;
- }
-
@NonNull
@Override
public GroupAddressAdapter.ViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int viewType) {
@@ -81,16 +76,20 @@ public GroupAddressAdapter.ViewHolder onCreateViewHolder(@NonNull final ViewGrou
@Override
public void onBindViewHolder(@NonNull final GroupAddressAdapter.ViewHolder holder, final int position) {
- if(mAddresses.size() > 0) {
+ if (mAddresses.size() > 0) {
final int address = mAddresses.get(position);
final Group group = network.getGroup(address);
- if(group != null) {
+ if (group != null) {
holder.icon.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.ic_outline_group_work_black_alpha_24dp));
holder.name.setText(group.getName());
holder.address.setText(MeshAddress.formatAddress(address, true));
- } else {
- holder.address.setText(MeshAddress.formatAddress(address, true));
- }
+ }/* else {
+ if(MeshAddress.isValidVirtualAddress(address)) {
+ holder.icon.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.ic_label_outline_black_alpha_24dp));
+ holder.name.setText(group.getName());
+ holder.address.setText(model.getLabelUUID(address).toString().toUpperCase(Locale.US));
+ }
+ }*/
}
}
@@ -108,28 +107,18 @@ public boolean isEmpty() {
return getItemCount() == 0;
}
- @FunctionalInterface
- public interface OnItemClickListener {
- void onItemClick(final int position, final int address);
- }
-
public final class ViewHolder extends RemovableViewHolder {
@BindView(R.id.icon)
ImageView icon;
@BindView(R.id.address_id)
TextView name;
- @BindView(R.id.address)
+ @BindView(R.id.title)
TextView address;
private ViewHolder(final View view) {
super(view);
ButterKnife.bind(this, view);
- view.findViewById(R.id.removable).setOnClickListener(v -> {
- if (mOnItemClickListener != null) {
- mOnItemClickListener.onItemClick(getAdapterPosition(), mAddresses.get(getAdapterPosition()));
- }
- });
}
}
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/GroupModelAdapter.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/GroupModelAdapter.java
index 75a67510a..90e7c5809 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/GroupModelAdapter.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/GroupModelAdapter.java
@@ -23,10 +23,10 @@
package no.nordicsemi.android.nrfmeshprovisioner.adapter;
import android.content.Context;
-import android.support.annotation.NonNull;
-import android.support.constraint.ConstraintLayout;
-import android.support.v4.content.ContextCompat;
-import android.support.v7.widget.RecyclerView;
+import androidx.annotation.NonNull;
+import androidx.constraintlayout.widget.ConstraintLayout;
+import androidx.core.content.ContextCompat;
+import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -78,7 +78,7 @@ public void updateAdapter(@NonNull final Group group, @NonNull final ArrayList modelEntry : element.getMeshModels().entrySet()) {
final MeshModel model = modelEntry.getValue();
for (Integer address : model.getSubscribedAddresses()) {
- if (mGroup.getGroupAddress() == address) {
+ if (mGroup.getAddress() == address) {
final View view = LayoutInflater.from(mContext).inflate(R.layout.group_model_item, holder.mModelContainer, false);
final ConstraintLayout container = view.findViewById(R.id.container);
final ImageView modelIcon = view.findViewById(R.id.icon);
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/ProvisioningProgressAdapter.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/ProvisioningProgressAdapter.java
index eeb2ff0d7..ffe5c5506 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/ProvisioningProgressAdapter.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/ProvisioningProgressAdapter.java
@@ -23,9 +23,11 @@
package no.nordicsemi.android.nrfmeshprovisioner.adapter;
import android.content.Context;
-import android.support.v4.content.ContextCompat;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.RecyclerView;
+
+import androidx.annotation.NonNull;
+import androidx.core.content.ContextCompat;
+import androidx.lifecycle.Observer;
+import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -45,19 +47,20 @@ public class ProvisioningProgressAdapter extends RecyclerView.Adapter mProgress = new ArrayList<>();
- public ProvisioningProgressAdapter(final AppCompatActivity mContext, final ProvisioningStatusLiveData provisioningProgress) {
+ public ProvisioningProgressAdapter(@NonNull final Context mContext, @NonNull final ProvisioningStatusLiveData provisioningProgress) {
this.mContext = mContext;
this.mProgress.addAll(provisioningProgress.getStateList());
}
+ @NonNull
@Override
- public ProvisioningProgressAdapter.ViewHolder onCreateViewHolder(final ViewGroup parent, final int viewType) {
+ public ProvisioningProgressAdapter.ViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int viewType) {
final View layoutView = LayoutInflater.from(mContext).inflate(R.layout.progress_item, parent, false);
return new ProvisioningProgressAdapter.ViewHolder(layoutView);
}
@Override
- public void onBindViewHolder(final ViewHolder holder, final int position) {
+ public void onBindViewHolder(@NonNull final ViewHolder holder, final int position) {
final ProvisionerProgress provisioningProgress = mProgress.get(position);
if(provisioningProgress != null) {
holder.image.setImageDrawable(ContextCompat.getDrawable(mContext, provisioningProgress.getResId()));
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/SubGroupAdapter.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/SubGroupAdapter.java
index 7631872d3..2ac9a14e0 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/SubGroupAdapter.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/SubGroupAdapter.java
@@ -22,14 +22,7 @@
package no.nordicsemi.android.nrfmeshprovisioner.adapter;
-import android.arch.lifecycle.LifecycleOwner;
-import android.arch.lifecycle.LiveData;
import android.content.Context;
-import android.support.annotation.NonNull;
-import android.support.constraint.ConstraintLayout;
-import android.support.v4.content.ContextCompat;
-import android.support.v7.widget.CardView;
-import android.support.v7.widget.RecyclerView;
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.view.LayoutInflater;
@@ -43,17 +36,25 @@
import java.util.List;
+import androidx.annotation.NonNull;
+import androidx.cardview.widget.CardView;
+import androidx.constraintlayout.widget.ConstraintLayout;
+import androidx.core.content.ContextCompat;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.lifecycle.LiveData;
+import androidx.recyclerview.widget.RecyclerView;
import butterknife.BindView;
import butterknife.ButterKnife;
+import no.nordicsemi.android.meshprovisioner.ApplicationKey;
import no.nordicsemi.android.meshprovisioner.Group;
import no.nordicsemi.android.meshprovisioner.MeshNetwork;
import no.nordicsemi.android.meshprovisioner.models.SigModelParser;
-import no.nordicsemi.android.meshprovisioner.transport.ApplicationKey;
import no.nordicsemi.android.meshprovisioner.transport.MeshModel;
import no.nordicsemi.android.meshprovisioner.utils.CompanyIdentifiers;
import no.nordicsemi.android.meshprovisioner.utils.CompositionDataParser;
import no.nordicsemi.android.meshprovisioner.utils.MeshParserUtils;
import no.nordicsemi.android.nrfmeshprovisioner.R;
+import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.MeshNetworkLiveData;
public class SubGroupAdapter extends RecyclerView.Adapter {
@@ -92,7 +93,7 @@ public void updateAdapterData() {
}
- public void setOnItemClickListener(final SubGroupAdapter.OnItemClickListener listener) {
+ public void setOnItemClickListener(@NonNull final SubGroupAdapter.OnItemClickListener listener) {
mOnItemClickListener = listener;
}
@@ -109,8 +110,7 @@ public void onBindViewHolder(@NonNull final ViewHolder holder, final int positio
final int keyIndex = mGroupedKeyModels.keyAt(position);
holder.groupItemContainer.setTag(keyIndex);
final ApplicationKey key = mMeshNetwork.getAppKey(keyIndex);
- final String keyTitle = key.getName() + " " + keyIndex;
- holder.mGroupAppKeyTitle.setText(keyTitle);
+ holder.mGroupAppKeyTitle.setText(key.getName());
final SparseIntArray groupedModels = mGroupedKeyModels.valueAt(position);
holder.mGroupGrid.setRowCount(1);
//Remove all child views to avoid duplicating
@@ -134,37 +134,35 @@ private void inflateView(@NonNull final ViewHolder holder, final int keyIndex, f
icon.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.ic_domain_nordic_medium_gray_48dp));
view.findViewById(R.id.container_buttons).setVisibility(View.INVISIBLE);
view.findViewById(R.id.container_vendor).setVisibility(View.VISIBLE);
- final TextView modelIdView = view.findViewById(R.id.model_id);
+ final TextView modelIdView = view.findViewById(R.id.subtitle);
modelIdView.setText(CompositionDataParser.formatModelIdentifier(modelId, true));
final TextView companyIdView = view.findViewById(R.id.company_id);
final int companyIdentifier = MeshParserUtils.getCompanyIdentifier(modelId);
companyIdView.setText(String.valueOf(CompanyIdentifiers.getCompanyName((short) companyIdentifier)));
- groupSummary.setText(mContext.getString(R.string.unknown_device_count, modelCount));
+ groupSummary.setText(mContext.getResources().getQuantityString(R.plurals.device_count, modelCount, modelCount));
} else {
switch (modelId) {
case SigModelParser.GENERIC_ON_OFF_SERVER:
- groupSummary.setText(mContext.getString(R.string.light_count, modelCount));
+ groupSummary.setText(mContext.getResources().getQuantityString(R.plurals.light_count, modelCount, modelCount));
break;
case SigModelParser.GENERIC_ON_OFF_CLIENT:
icon.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.ic_light_switch_nordic_medium_grey_48dp));
view.findViewById(R.id.container_buttons).setVisibility(View.INVISIBLE);
- groupSummary.setText(mContext.getString(R.string.switch_count, modelCount));
+ groupSummary.setText(mContext.getResources().getQuantityString(R.plurals.switch_count, modelCount, modelCount));
break;
case SigModelParser.GENERIC_LEVEL_SERVER:
icon.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.ic_lightbulb_level_nordic_sun_outline_48dp));
- groupSummary.setText(mContext.getString(R.string.dimmer_count, modelCount));
+ groupSummary.setText(mContext.getResources().getQuantityString(R.plurals.dimmer_count, modelCount, modelCount));
break;
default:
icon.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.ic_help_outline_nordic_medium_grey_48dp));
view.findViewById(R.id.container_buttons).setVisibility(View.INVISIBLE);
- groupSummary.setText(mContext.getString(R.string.unknown_device_count, modelCount));
+ groupSummary.setText(mContext.getResources().getQuantityString(R.plurals.device_count, modelCount, modelCount));
break;
}
}
- groupContainerCard.setOnClickListener(v -> {
- onSubGroupItemClicked(keyIndex, modelId);
- });
+ groupContainerCard.setOnClickListener(v -> onSubGroupItemClicked(keyIndex, modelId));
on.setOnClickListener(v -> toggleState(keyIndex, modelId, true));
off.setOnClickListener(v -> toggleState(keyIndex, modelId, false));
@@ -201,11 +199,11 @@ public long getItemId(final int position) {
return super.getItemId(position);
}
- public int getModelCount(){
+ public int getModelCount() {
return mModels.size();
}
- public List getModels(){
+ public List getModels() {
return mModels;
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/ble/BleMeshManager.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/ble/BleMeshManager.java
index 06bfab2b4..7e199d85b 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/ble/BleMeshManager.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/ble/BleMeshManager.java
@@ -27,7 +27,7 @@
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.content.Context;
-import android.support.annotation.NonNull;
+import androidx.annotation.NonNull;
import android.util.Log;
import java.lang.reflect.Method;
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/ReconnectActivity.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/ble/ReconnectActivity.java
similarity index 81%
rename from Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/ReconnectActivity.java
rename to Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/ble/ReconnectActivity.java
index 8badba10f..7f40e43ca 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/ReconnectActivity.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/ble/ReconnectActivity.java
@@ -20,27 +20,25 @@
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package no.nordicsemi.android.nrfmeshprovisioner;
+package no.nordicsemi.android.nrfmeshprovisioner.ble;
import android.app.Activity;
-import android.arch.lifecycle.ViewModelProvider;
-import android.arch.lifecycle.ViewModelProviders;
import android.content.Intent;
import android.os.Bundle;
-import android.support.annotation.Nullable;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import javax.inject.Inject;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.Toolbar;
+import androidx.lifecycle.ViewModelProvider;
+import androidx.lifecycle.ViewModelProviders;
import butterknife.BindView;
import butterknife.ButterKnife;
-import no.nordicsemi.android.meshprovisioner.transport.ProxyConfigSetFilterType;
-import no.nordicsemi.android.meshprovisioner.utils.MeshAddress;
-import no.nordicsemi.android.meshprovisioner.utils.ProxyFilterType;
+import no.nordicsemi.android.nrfmeshprovisioner.R;
import no.nordicsemi.android.nrfmeshprovisioner.adapter.ExtendedBluetoothDevice;
import no.nordicsemi.android.nrfmeshprovisioner.di.Injectable;
import no.nordicsemi.android.nrfmeshprovisioner.utils.Utils;
@@ -69,6 +67,7 @@ protected void onCreate(@Nullable final Bundle savedInstanceState) {
final Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
+ //noinspection ConstantConditions
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setTitle(deviceName);
getSupportActionBar().setSubtitle(deviceAddress);
@@ -91,9 +90,6 @@ protected void onCreate(@Nullable final Bundle savedInstanceState) {
returnIntent.putExtra(Utils.EXTRA_DATA, true);
setResult(Activity.RESULT_OK, returnIntent);
finish();
- //We send a proxy whitelist filter message to identify the node we are connected to when reconnecting to the network
- final ProxyConfigSetFilterType setFilterType = new ProxyConfigSetFilterType(new ProxyFilterType(ProxyFilterType.WHITE_LIST_FILTER));
- mReconnectViewModel.getMeshManagerApi().sendMeshMessage(MeshAddress.UNASSIGNED_ADDRESS, setFilterType);
}
});
@@ -101,10 +97,9 @@ protected void onCreate(@Nullable final Bundle savedInstanceState) {
@Override
public boolean onOptionsItemSelected(final MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
+ if (item.getItemId() == android.R.id.home) {
+ onBackPressed();
+ return true;
}
return false;
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/ScannerActivity.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/ble/ScannerActivity.java
similarity index 86%
rename from Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/ScannerActivity.java
rename to Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/ble/ScannerActivity.java
index 98f6bdb11..df61d61ff 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/ScannerActivity.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/ble/ScannerActivity.java
@@ -20,44 +20,46 @@
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package no.nordicsemi.android.nrfmeshprovisioner;
+package no.nordicsemi.android.nrfmeshprovisioner.ble;
import android.Manifest;
import android.app.Activity;
-import android.arch.lifecycle.ViewModelProvider;
-import android.arch.lifecycle.ViewModelProviders;
import android.bluetooth.BluetoothAdapter;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Settings;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.v4.app.ActivityCompat;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.DividerItemDecoration;
-import android.support.v7.widget.LinearLayoutManager;
-import android.support.v7.widget.RecyclerView;
-import android.support.v7.widget.SimpleItemAnimator;
-import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import javax.inject.Inject;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.Toolbar;
+import androidx.core.app.ActivityCompat;
+import androidx.lifecycle.ViewModelProvider;
+import androidx.lifecycle.ViewModelProviders;
+import androidx.recyclerview.widget.DividerItemDecoration;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.recyclerview.widget.SimpleItemAnimator;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
-import no.nordicsemi.android.nrfmeshprovisioner.adapter.DevicesAdapter;
+import no.nordicsemi.android.nrfmeshprovisioner.ProvisioningActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.R;
import no.nordicsemi.android.nrfmeshprovisioner.adapter.ExtendedBluetoothDevice;
-import no.nordicsemi.android.nrfmeshprovisioner.ble.BleMeshManager;
+import no.nordicsemi.android.nrfmeshprovisioner.ble.adapter.DevicesAdapter;
import no.nordicsemi.android.nrfmeshprovisioner.di.Injectable;
import no.nordicsemi.android.nrfmeshprovisioner.utils.Utils;
import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.ScannerLiveData;
import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.ScannerViewModel;
-public class ScannerActivity extends AppCompatActivity implements Injectable, DevicesAdapter.OnItemClickListener {
+public class ScannerActivity extends AppCompatActivity implements Injectable,
+ DevicesAdapter.OnItemClickListener {
private static final int REQUEST_ACCESS_COARSE_LOCATION = 1022; // random number
@Inject
@@ -89,17 +91,16 @@ protected void onCreate(@Nullable final Bundle savedInstanceState) {
// Create view model containing utility methods for scanning
mViewModel = ViewModelProviders.of(this, mViewModelFactory).get(ScannerViewModel.class);
- mViewModel.getScannerRepository().getScannerState().startScanning();
- mViewModel.getScannerRepository().getScannerState().observe(this, this::startScan);
final Toolbar toolbar = findViewById(R.id.toolbar);
+ toolbar.setTitle(R.string.title_scanner);
setSupportActionBar(toolbar);
+ //noinspection ConstantConditions
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
- getSupportActionBar().setTitle(R.string.title_scanner);
if (getIntent() != null) {
mScanWithProxyService = getIntent().getBooleanExtra(Utils.EXTRA_DATA_PROVISIONING_SERVICE, true);
- if(mScanWithProxyService) {
+ if (mScanWithProxyService) {
getSupportActionBar().setSubtitle(R.string.sub_title_scanning_nodes);
} else {
getSupportActionBar().setSubtitle(R.string.sub_title_scanning_proxy_node);
@@ -111,7 +112,10 @@ protected void onCreate(@Nullable final Bundle savedInstanceState) {
recyclerViewDevices.setLayoutManager(new LinearLayoutManager(this));
final DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerViewDevices.getContext(), DividerItemDecoration.VERTICAL);
recyclerViewDevices.addItemDecoration(dividerItemDecoration);
- ((SimpleItemAnimator) recyclerViewDevices.getItemAnimator()).setSupportsChangeAnimations(false);
+
+ final SimpleItemAnimator itemAnimator = (SimpleItemAnimator) recyclerViewDevices.getItemAnimator();
+ if (itemAnimator != null) itemAnimator.setSupportsChangeAnimations(false);
+
final DevicesAdapter adapter = new DevicesAdapter(this, mViewModel.getScannerRepository().getScannerState());
adapter.setOnItemClickListener(this);
recyclerViewDevices.setAdapter(adapter);
@@ -119,6 +123,13 @@ protected void onCreate(@Nullable final Bundle savedInstanceState) {
}
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mViewModel.getScannerRepository().getScannerState().startScanning();
+ mViewModel.getScannerRepository().getScannerState().observe(this, this::startScan);
+ }
+
@Override
protected void onStop() {
super.onStop();
@@ -127,10 +138,9 @@ protected void onStop() {
@Override
public boolean onOptionsItemSelected(final MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
+ if (item.getItemId() == android.R.id.home) {
+ onBackPressed();
+ return true;
}
return false;
}
@@ -163,7 +173,7 @@ public void onItemClick(final ExtendedBluetoothDevice device) {
final Intent intent;
stopScan();
if (mScanWithProxyService) {
- intent = new Intent(this, MeshProvisionerActivity.class);
+ intent = new Intent(this, ProvisioningActivity.class);
intent.putExtra(Utils.EXTRA_DEVICE, device);
startActivityForResult(intent, Utils.PROVISIONING_SUCCESS);
} else {
@@ -176,10 +186,8 @@ public void onItemClick(final ExtendedBluetoothDevice device) {
@Override
public void onRequestPermissionsResult(final int requestCode, @NonNull final String[] permissions, @NonNull final int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
- switch (requestCode) {
- case REQUEST_ACCESS_COARSE_LOCATION:
- mViewModel.getScannerRepository().getScannerState().refresh();
- break;
+ if (requestCode == REQUEST_ACCESS_COARSE_LOCATION) {
+ mViewModel.getScannerRepository().getScannerState().refresh();
}
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/DevicesAdapter.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/ble/adapter/DevicesAdapter.java
similarity index 92%
rename from Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/DevicesAdapter.java
rename to Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/ble/adapter/DevicesAdapter.java
index a1bafa319..edb5037a5 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/DevicesAdapter.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/ble/adapter/DevicesAdapter.java
@@ -20,12 +20,12 @@
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package no.nordicsemi.android.nrfmeshprovisioner.adapter;
+package no.nordicsemi.android.nrfmeshprovisioner.ble.adapter;
import android.content.Context;
-import android.support.annotation.NonNull;
-import android.support.v4.app.FragmentActivity;
-import android.support.v7.widget.RecyclerView;
+import androidx.annotation.NonNull;
+import androidx.fragment.app.FragmentActivity;
+import androidx.recyclerview.widget.RecyclerView;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
@@ -38,6 +38,7 @@
import butterknife.BindView;
import butterknife.ButterKnife;
import no.nordicsemi.android.nrfmeshprovisioner.R;
+import no.nordicsemi.android.nrfmeshprovisioner.adapter.ExtendedBluetoothDevice;
import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.ScannerLiveData;
public class DevicesAdapter extends RecyclerView.Adapter {
@@ -57,7 +58,7 @@ public DevicesAdapter(final FragmentActivity fragmentActivity, final ScannerLive
});
}
- public void setOnItemClickListener(final OnItemClickListener listener) {
+ public void setOnItemClickListener(@NonNull final OnItemClickListener listener) {
mOnItemClickListener = listener;
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/di/ActivitiesModule.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/di/ActivitiesModule.java
index 1d3c18a77..7a647c2d9 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/di/ActivitiesModule.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/di/ActivitiesModule.java
@@ -24,71 +24,115 @@
import dagger.Module;
import dagger.android.ContributesAndroidInjector;
-import no.nordicsemi.android.nrfmeshprovisioner.BaseModelConfigurationActivity;
-import no.nordicsemi.android.nrfmeshprovisioner.ConfigurationServerActivity;
-import no.nordicsemi.android.nrfmeshprovisioner.GenericLevelServerActivity;
-import no.nordicsemi.android.nrfmeshprovisioner.GenericOnOffServerActivity;
import no.nordicsemi.android.nrfmeshprovisioner.GroupControlsActivity;
import no.nordicsemi.android.nrfmeshprovisioner.MainActivity;
-import no.nordicsemi.android.nrfmeshprovisioner.ManageAppKeysActivity;
-import no.nordicsemi.android.nrfmeshprovisioner.MeshProvisionerActivity;
-import no.nordicsemi.android.nrfmeshprovisioner.ModelConfigurationActivity;
-import no.nordicsemi.android.nrfmeshprovisioner.NodeConfigurationActivity;
-import no.nordicsemi.android.nrfmeshprovisioner.NodeDetailsActivity;
-import no.nordicsemi.android.nrfmeshprovisioner.PublicationSettingsActivity;
-import no.nordicsemi.android.nrfmeshprovisioner.ReconnectActivity;
-import no.nordicsemi.android.nrfmeshprovisioner.ScannerActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.ProvisioningActivity;
import no.nordicsemi.android.nrfmeshprovisioner.SplashScreenActivity;
-import no.nordicsemi.android.nrfmeshprovisioner.VendorModelActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.ble.ReconnectActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.ble.ScannerActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.keys.AddAppKeyActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.keys.AddAppKeysActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.keys.AddNetKeyActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.keys.AddNetKeysActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.keys.AppKeysActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.keys.EditAppKeyActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.keys.EditNetKeyActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.keys.NetKeysActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.node.ConfigurationClientActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.node.ConfigurationServerActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.node.GenericLevelServerActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.node.GenericOnOffServerActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.node.ModelConfigurationActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.node.NodeConfigurationActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.node.NodeDetailsActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.node.PublicationSettingsActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.node.VendorModelActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.provisioners.AddProvisionerActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.provisioners.EditProvisionerActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.provisioners.ProvisionersActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.provisioners.RangesActivity;
@Module
abstract class ActivitiesModule {
- @ContributesAndroidInjector()
- abstract SplashScreenActivity contributeSplashScreenActivity();
+ @ContributesAndroidInjector()
+ abstract SplashScreenActivity contributeSplashScreenActivity();
- @ContributesAndroidInjector(modules = FragmentBuildersModule.class)
- abstract MainActivity contributeMainActivity();
+ @ContributesAndroidInjector(modules = FragmentBuildersModule.class)
+ abstract MainActivity contributeMainActivity();
- @ContributesAndroidInjector()
- abstract ManageAppKeysActivity contributeManageAppKeysActivity();
+ @ContributesAndroidInjector()
+ abstract ProvisionersActivity contributeProvisionersActivity();
- @ContributesAndroidInjector()
- abstract MeshProvisionerActivity contributeMeshProvisionerActivity();
+ @ContributesAndroidInjector()
+ abstract AddProvisionerActivity contributeAddProvisionersActivity();
- @ContributesAndroidInjector()
- abstract NodeConfigurationActivity contributeElementConfigurationActivity();
+ @ContributesAndroidInjector()
+ abstract EditProvisionerActivity contributeEditProvisionersActivity();
- @ContributesAndroidInjector()
- abstract BaseModelConfigurationActivity contributeBaseModelConfigurationActivity();
+ @ContributesAndroidInjector()
+ abstract RangesActivity contributeRangesActivity();
- @ContributesAndroidInjector()
- abstract ScannerActivity contributeScannerActivity();
+ @ContributesAndroidInjector()
+ abstract NetKeysActivity contributeNetKeysActivity();
- @ContributesAndroidInjector()
- abstract ReconnectActivity contributeReconnectActivity();
+ @ContributesAndroidInjector()
+ abstract AddNetKeyActivity contributeAddNetKeyActivity();
- @ContributesAndroidInjector()
- abstract NodeDetailsActivity contributeNodeDetailsActivity();
+ @ContributesAndroidInjector()
+ abstract EditNetKeyActivity contributeEditNetKeyActivity();
- @ContributesAndroidInjector()
- abstract GroupControlsActivity contributeGroupControlsActivity();
+ @ContributesAndroidInjector()
+ abstract AppKeysActivity contributeAppKeysActivity();
- @ContributesAndroidInjector()
- abstract PublicationSettingsActivity contributePublicationSettingsActivity();
+ @ContributesAndroidInjector()
+ abstract AddAppKeyActivity contributeAddAppKeyActivity();
- @ContributesAndroidInjector()
- abstract ConfigurationServerActivity contribyteConfigurationServerActivity();
+ @ContributesAndroidInjector()
+ abstract EditAppKeyActivity contributeEditAppKeyActivity();
- @ContributesAndroidInjector()
- abstract GenericOnOffServerActivity contributeGenericOnOffServerActivity();
+ @ContributesAndroidInjector()
+ abstract ProvisioningActivity contributeMeshProvisionerActivity();
- @ContributesAndroidInjector()
- abstract GenericLevelServerActivity contributeGenericLevelServerActivity();
+ @ContributesAndroidInjector()
+ abstract NodeConfigurationActivity contributeElementConfigurationActivity();
- @ContributesAndroidInjector()
- abstract VendorModelActivity contributeVendorModelActivity();
+ @ContributesAndroidInjector()
+ abstract AddAppKeysActivity contributeAddAppKeysActivity();
- @ContributesAndroidInjector()
- abstract ModelConfigurationActivity contributeModelConfigurationActivity();
+ @ContributesAndroidInjector()
+ abstract AddNetKeysActivity contributeAddNetKeysActivity();
+
+ @ContributesAndroidInjector()
+ abstract ScannerActivity contributeScannerActivity();
+
+ @ContributesAndroidInjector()
+ abstract ReconnectActivity contributeReconnectActivity();
+
+ @ContributesAndroidInjector()
+ abstract NodeDetailsActivity contributeNodeDetailsActivity();
+
+ @ContributesAndroidInjector()
+ abstract GroupControlsActivity contributeGroupControlsActivity();
+
+ @ContributesAndroidInjector()
+ abstract PublicationSettingsActivity contributePublicationSettingsActivity();
+
+ @ContributesAndroidInjector()
+ abstract ConfigurationServerActivity contributeConfigurationServerActivity();
+
+ @ContributesAndroidInjector()
+ abstract ConfigurationClientActivity contributeConfigurationClientActivity();
+
+ @ContributesAndroidInjector()
+ abstract GenericOnOffServerActivity contributeGenericOnOffServerActivity();
+
+ @ContributesAndroidInjector()
+ abstract GenericLevelServerActivity contributeGenericLevelServerActivity();
+
+ @ContributesAndroidInjector()
+ abstract VendorModelActivity contributeVendorModelActivity();
+
+ @ContributesAndroidInjector()
+ abstract ModelConfigurationActivity contributeModelConfigurationActivity();
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/di/AppInjector.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/di/AppInjector.java
index cf2c574de..a281d7f82 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/di/AppInjector.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/di/AppInjector.java
@@ -25,9 +25,11 @@
import android.app.Activity;
import android.app.Application;
import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentManager;
-import android.support.v7.app.AppCompatActivity;
+
+import androidx.annotation.NonNull;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+import androidx.appcompat.app.AppCompatActivity;
import dagger.android.AndroidInjection;
import dagger.android.support.AndroidSupportInjection;
@@ -36,11 +38,11 @@
/**
* Helper class to automatically inject fragments if they implement {@link Injectable}.
*/
-public class AppInjector {
+class AppInjector {
private AppInjector() {
}
- public static void init(final MeshApplication application) {
+ static void init(final MeshApplication application) {
DaggerMeshAppComponent.builder()
.contextModule(new ContextModule(application))
.build()
@@ -92,7 +94,7 @@ private static void handleActivity(final Activity activity) {
((AppCompatActivity) activity).getSupportFragmentManager().registerFragmentLifecycleCallbacks(
new FragmentManager.FragmentLifecycleCallbacks() {
@Override
- public void onFragmentCreated(final FragmentManager fm, final Fragment f, final Bundle savedInstanceState) {
+ public void onFragmentCreated(@NonNull final FragmentManager fm, @NonNull final Fragment f, final Bundle savedInstanceState) {
if (f instanceof Injectable) {
AndroidSupportInjection.inject(f);
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/di/BleMeshManagerModule.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/di/BleMeshManagerModule.java
index f97e88e8c..22fc41f9b 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/di/BleMeshManagerModule.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/di/BleMeshManagerModule.java
@@ -30,7 +30,6 @@
import dagger.Provides;
import no.nordicsemi.android.meshprovisioner.MeshManagerApi;
import no.nordicsemi.android.nrfmeshprovisioner.ble.BleMeshManager;
-import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.NetworkInformation;
@Module
class BleMeshManagerModule {
@@ -45,9 +44,4 @@ BleMeshManager provideBleMeshManager(final Context context) {
MeshManagerApi provideMeshManagerApi(final Context context) {
return new MeshManagerApi(context);
}
-
- @Provides
- NetworkInformation provideNetworkInformation(final Context context) {
- return new NetworkInformation(context);
- }
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/di/FragmentBuildersModule.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/di/FragmentBuildersModule.java
index bf92ad9d9..49aa477d1 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/di/FragmentBuildersModule.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/di/FragmentBuildersModule.java
@@ -26,6 +26,7 @@
import dagger.android.ContributesAndroidInjector;
import no.nordicsemi.android.nrfmeshprovisioner.GroupsFragment;
import no.nordicsemi.android.nrfmeshprovisioner.NetworkFragment;
+import no.nordicsemi.android.nrfmeshprovisioner.ProxyFilterFragment;
import no.nordicsemi.android.nrfmeshprovisioner.SettingsFragment;
@Module
@@ -35,5 +36,7 @@ abstract class FragmentBuildersModule {
@ContributesAndroidInjector
abstract GroupsFragment contributeGroupFragment();
@ContributesAndroidInjector
+ abstract ProxyFilterFragment contributeProxyFilterFragment();
+ @ContributesAndroidInjector
abstract SettingsFragment contributeSettingsFragment();
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/di/MeshApplication.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/di/MeshApplication.java
index 32e567a37..19f49b9b6 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/di/MeshApplication.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/di/MeshApplication.java
@@ -24,8 +24,8 @@
import android.app.Activity;
import android.app.Service;
-import android.support.multidex.MultiDexApplication;
-import android.support.v7.app.AppCompatDelegate;
+import androidx.multidex.MultiDexApplication;
+import androidx.appcompat.app.AppCompatDelegate;
import javax.inject.Inject;
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/di/ViewModelModule.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/di/ViewModelModule.java
index 1ab47d187..45de85d7a 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/di/ViewModelModule.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/di/ViewModelModule.java
@@ -22,40 +22,38 @@
package no.nordicsemi.android.nrfmeshprovisioner.di;
-import android.arch.lifecycle.ViewModelProvider;
import android.content.Context;
import javax.inject.Singleton;
+import androidx.annotation.NonNull;
+import androidx.lifecycle.ViewModelProvider;
import dagger.Module;
import dagger.Provides;
import no.nordicsemi.android.meshprovisioner.MeshManagerApi;
import no.nordicsemi.android.nrfmeshprovisioner.ble.BleMeshManager;
-import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.NetworkInformation;
import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.NrfMeshRepository;
import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.ScannerRepository;
import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.ViewModelFactory;
-
@Module(subcomponents = ViewModelSubComponent.class)
class ViewModelModule {
- @Provides
- static ScannerRepository provideScannerRepository(final Context context, final MeshManagerApi meshManagerApi) {
- return new ScannerRepository(context, meshManagerApi);
- }
-
- @Provides
- @Singleton
- static NrfMeshRepository provideNrfMeshRepository(final MeshManagerApi meshManagerApi,
- final NetworkInformation networkInformation,
- final BleMeshManager bleMeshManager) {
- return new NrfMeshRepository(meshManagerApi, networkInformation, bleMeshManager);
- }
-
- @Provides
- @Singleton
- static ViewModelProvider.Factory provideViewModelFactory(final ViewModelSubComponent.Builder viewModelSubComponent) {
- return new ViewModelFactory(viewModelSubComponent.build());
- }
+ @Provides
+ static ScannerRepository provideScannerRepository(@NonNull final Context context, @NonNull final MeshManagerApi meshManagerApi) {
+ return new ScannerRepository(context, meshManagerApi);
+ }
+
+ @Provides
+ @Singleton
+ static NrfMeshRepository provideNrfMeshRepository(@NonNull final MeshManagerApi meshManagerApi,
+ @NonNull final BleMeshManager bleMeshManager) {
+ return new NrfMeshRepository(meshManagerApi, bleMeshManager);
+ }
+
+ @Provides
+ @Singleton
+ static ViewModelProvider.Factory provideViewModelFactory(@NonNull final ViewModelSubComponent.Builder viewModelSubComponent) {
+ return new ViewModelFactory(viewModelSubComponent.build());
+ }
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/di/ViewModelSubComponent.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/di/ViewModelSubComponent.java
index 6ff547c42..c9df8be40 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/di/ViewModelSubComponent.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/di/ViewModelSubComponent.java
@@ -23,12 +23,23 @@
package no.nordicsemi.android.nrfmeshprovisioner.di;
import dagger.Subcomponent;
+import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.AddAppKeyViewModel;
+import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.AddKeysViewModel;
+import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.AddNetKeyViewModel;
+import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.AddProvisionerViewModel;
+import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.AppKeysViewModel;
+import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.EditAppKeyViewModel;
+import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.EditNetKeyViewModel;
+import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.EditProvisionerViewModel;
import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.GroupControlsViewModel;
-import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.ManageAppKeysViewModel;
-import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.MeshProvisionerViewModel;
import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.ModelConfigurationViewModel;
+import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.NetKeysViewModel;
import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.NodeConfigurationViewModel;
+import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.NodeDetailsViewModel;
+import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.ProvisionersViewModel;
+import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.ProvisioningViewModel;
import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.PublicationViewModel;
+import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.RangesViewModel;
import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.ReconnectViewModel;
import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.ScannerViewModel;
import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.SharedViewModel;
@@ -42,18 +53,50 @@
*/
@Subcomponent
public interface ViewModelSubComponent {
- @Subcomponent.Builder
- interface Builder {
- ViewModelSubComponent build();
- }
- SplashViewModel splashViewModel();
- SharedViewModel commonViewModel();
- ScannerViewModel scannerViewModel();
- GroupControlsViewModel groupControlsViewModel();
- ManageAppKeysViewModel manageAppKeysViewModel();
- MeshProvisionerViewModel meshProvisionerViewModel();
- NodeConfigurationViewModel meshConfigurationViewModel();
- ModelConfigurationViewModel modelConfigurationViewModel();
- PublicationViewModel publicationViewModel();
- ReconnectViewModel reconnectViewModule();
+ @Subcomponent.Builder
+ interface Builder {
+ ViewModelSubComponent build();
+ }
+
+ SplashViewModel splashViewModel();
+
+ SharedViewModel commonViewModel();
+
+ ScannerViewModel scannerViewModel();
+
+ GroupControlsViewModel groupControlsViewModel();
+
+ ProvisionersViewModel provisionersViewModel();
+
+ AddProvisionerViewModel addProvisionerViewModel();
+
+ EditProvisionerViewModel editProvisionerViewModel();
+
+ RangesViewModel rangesViewModel();
+
+ NetKeysViewModel netKeysViewModel();
+
+ AddNetKeyViewModel addNetKeyViewModel();
+
+ EditNetKeyViewModel editNetKeyViewModel();
+
+ AppKeysViewModel appKeysViewModel();
+
+ AddAppKeyViewModel addAppKeyViewModel();
+
+ EditAppKeyViewModel editAppKeyViewModel();
+
+ ProvisioningViewModel meshProvisionerViewModel();
+
+ NodeConfigurationViewModel nodeConfigurationViewModel();
+
+ AddKeysViewModel addKeysViewModel();
+
+ NodeDetailsViewModel nodeDetailsViewModel();
+
+ ModelConfigurationViewModel modelConfigurationViewModel();
+
+ PublicationViewModel publicationViewModel();
+
+ ReconnectViewModel reconnectViewModule();
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmenPermissionDenied.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmenPermissionDenied.java
index 073d956a7..8127a53de 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmenPermissionDenied.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmenPermissionDenied.java
@@ -24,8 +24,8 @@
import android.app.Dialog;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v7.app.AlertDialog;
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AlertDialog;
import no.nordicsemi.android.nrfmeshprovisioner.R;
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentAuthenticationInput.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentAuthenticationInput.java
index 408a4f447..935803c26 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentAuthenticationInput.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentAuthenticationInput.java
@@ -23,14 +23,15 @@
package no.nordicsemi.android.nrfmeshprovisioner.dialog;
+import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.design.widget.TextInputEditText;
-import android.support.design.widget.TextInputLayout;
-import android.support.v4.app.DialogFragment;
-import android.support.v7.app.AlertDialog;
+import androidx.annotation.NonNull;
+import com.google.android.material.textfield.TextInputEditText;
+import com.google.android.material.textfield.TextInputLayout;
+import androidx.fragment.app.DialogFragment;
+import androidx.appcompat.app.AlertDialog;
import android.text.Editable;
import android.text.InputFilter;
import android.text.InputType;
@@ -99,11 +100,12 @@ public void onCreate(final Bundle savedInstanceState) {
@NonNull
@Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
+ @SuppressLint("InflateParams")
final View rootView = LayoutInflater.from(getActivity()).inflate(R.layout.dialog_fragment_auth_input, null);
ButterKnife.bind(this, rootView);
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(requireContext()).
- setIcon(R.drawable.ic_lock_open).
+ setIcon(R.drawable.ic_lock_open_black_alpha_24dp).
setTitle(getString(R.string.provisioner_authentication_title)).
setView(rootView);
@@ -245,7 +247,7 @@ private void updateInputOOBUI() {
//noinspection ConstantConditions
final int authInput = MeshParserUtils.unsignedByteToInt(authValue[0]);
if (inputOOBAction == InputOOBAction.PUSH) {
- msg = getString(R.string.provisioner_input_pushes, authInput);
+ msg = getResources().getQuantityString(R.plurals.input_pushes, authInput, authInput);
} else {
msg = getString(authInput);
}
@@ -253,14 +255,12 @@ private void updateInputOOBUI() {
start = msg.indexOf(String.valueOf(authInput));
end = start + String.valueOf(authInput).length();
} else if (inputOOBAction == InputOOBAction.INPUT_NUMERIC) {
- //noinspection ConstantConditions
final String authString = String.valueOf(ByteBuffer.wrap(authValue).getInt());
msg = getString(R.string.provisioner_input_numeric_device, authString);
start = msg.indexOf(authString);
end = start + authString.length();
spannableMessage = new SpannableStringBuilder(msg);
} else {
- //noinspection ConstantConditions
final String authString = new String(authValue);
msg = getString(R.string.provisioner_input_numeric_device, authString);
start = msg.indexOf(authString);
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentConfigStatus.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentConfigStatus.java
index c69cd1c46..d1e7f2e24 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentConfigStatus.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentConfigStatus.java
@@ -24,17 +24,13 @@
import android.app.Dialog;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v7.app.AlertDialog;
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AlertDialog;
import no.nordicsemi.android.nrfmeshprovisioner.R;
public class DialogFragmentConfigStatus extends DialogFragmentMessage {
- public interface DialogFragmentAppKeyBindStatusListener {
- void onAppKeyBindStatusConfirmed();
- }
-
public static DialogFragmentConfigStatus newInstance(final String title, final String message) {
Bundle args = new Bundle();
DialogFragmentConfigStatus fragment = new DialogFragmentConfigStatus();
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentAppKeyAddStatus.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentConfigurationComplete.java
similarity index 76%
rename from Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentAppKeyAddStatus.java
rename to Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentConfigurationComplete.java
index a86ae37ad..5bce6ba5a 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentAppKeyAddStatus.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentConfigurationComplete.java
@@ -24,20 +24,20 @@
import android.app.Dialog;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v7.app.AlertDialog;
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AlertDialog;
import no.nordicsemi.android.nrfmeshprovisioner.R;
-public class DialogFragmentAppKeyAddStatus extends DialogFragmentMessage {
+public class DialogFragmentConfigurationComplete extends DialogFragmentMessage {
- public interface DialogFragmentAppKeyAddStatusListener {
- void onAppKeyAddStatusReceived();
+ public interface ConfigurationCompleteListener {
+ void onConfigurationCompleted();
}
- public static DialogFragmentAppKeyAddStatus newInstance(final String title, final String message) {
+ public static DialogFragmentConfigurationComplete newInstance(final String title, final String message) {
Bundle args = new Bundle();
- DialogFragmentAppKeyAddStatus fragment = new DialogFragmentAppKeyAddStatus();
+ DialogFragmentConfigurationComplete fragment = new DialogFragmentConfigurationComplete();
args.putString(TITLE, title);
args.putString(MESSAGE, message);
fragment.setArguments(args);
@@ -52,10 +52,10 @@ public void onCreate(Bundle savedInstanceState) {
@NonNull
@Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
- alertDialogBuilder = new AlertDialog.Builder(getActivity());
- alertDialogBuilder.setIcon(R.drawable.ic_vpn_key_black_alpha_24dp);
+ alertDialogBuilder = new AlertDialog.Builder(requireContext());
+ alertDialogBuilder.setIcon(R.drawable.ic_done_all_black_alpha_24dp);
alertDialogBuilder.setPositiveButton(getString(R.string.ok), (dialog, which) -> (
- (DialogFragmentAppKeyAddStatusListener)getActivity()).onAppKeyAddStatusReceived());
+ (ConfigurationCompleteListener)requireActivity()).onConfigurationCompleted());
return super.onCreateDialog(savedInstanceState);
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentCreateGroup.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentCreateGroup.java
index 314f4761c..0c8fe6988 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentCreateGroup.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentCreateGroup.java
@@ -22,34 +22,61 @@
package no.nordicsemi.android.nrfmeshprovisioner.dialog;
-import android.app.AlertDialog;
+import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.design.widget.TextInputEditText;
-import android.support.design.widget.TextInputLayout;
-import android.support.v4.app.DialogFragment;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.text.method.KeyListener;
import android.view.LayoutInflater;
import android.view.View;
+import android.widget.AdapterView;
+import android.widget.Button;
+import android.widget.Spinner;
+import android.widget.TextView;
+import com.google.android.material.textfield.TextInputEditText;
+import com.google.android.material.textfield.TextInputLayout;
+
+import java.util.Locale;
+import java.util.UUID;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.DialogFragment;
import butterknife.BindView;
import butterknife.ButterKnife;
+import no.nordicsemi.android.meshprovisioner.Group;
+import no.nordicsemi.android.meshprovisioner.utils.MeshAddress;
import no.nordicsemi.android.meshprovisioner.utils.MeshParserUtils;
+import no.nordicsemi.android.nrfmeshprovisioner.GroupCallbacks;
import no.nordicsemi.android.nrfmeshprovisioner.R;
+import no.nordicsemi.android.nrfmeshprovisioner.adapter.AddressTypeAdapter;
+import no.nordicsemi.android.nrfmeshprovisioner.utils.AddressTypes;
import no.nordicsemi.android.nrfmeshprovisioner.utils.HexKeyListener;
import no.nordicsemi.android.nrfmeshprovisioner.utils.Utils;
+import static android.view.View.GONE;
+import static android.view.View.VISIBLE;
+import static no.nordicsemi.android.nrfmeshprovisioner.utils.AddressTypes.GROUP_ADDRESS;
+import static no.nordicsemi.android.nrfmeshprovisioner.utils.AddressTypes.VIRTUAL_ADDRESS;
+
public class DialogFragmentCreateGroup extends DialogFragment {
- private static final String GROUPS = "GROUPS";
+ private static final AddressTypes[] addressTypes = {GROUP_ADDRESS, VIRTUAL_ADDRESS};
+ private static final String GROUP = "GROUP";
+
//UI Bindings
+ @BindView(R.id.summary)
+ TextView summary;
+ @BindView(R.id.address_types)
+ Spinner addressTypesSpinnerView;
+ @BindView(R.id.group_container)
+ View groupContainer;
@BindView(R.id.group_name_layout)
TextInputLayout groupNameInputLayout;
@BindView(R.id.name_input)
@@ -58,11 +85,15 @@ public class DialogFragmentCreateGroup extends DialogFragment {
TextInputLayout addressInputLayout;
@BindView(R.id.address_input)
TextInputEditText addressInput;
+ @BindView(R.id.label_summary)
+ TextView labelSummary;
+ @BindView(R.id.uuid_label)
+ TextView labelUuidView;
+ private Button mGenerateLabelUUID;
- public interface DialogFragmentCreateGroupListener {
- boolean createGroup(@NonNull final String name, final int address);
- }
+ private AddressTypeAdapter mAdapterSpinner;
+ private Group mGroup;
public static DialogFragmentCreateGroup newInstance() {
return new DialogFragmentCreateGroup();
@@ -76,12 +107,27 @@ public void onCreate(@Nullable final Bundle savedInstanceState) {
@NonNull
@Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
- final View rootView = LayoutInflater.from(getContext()).inflate(R.layout.dialog_fragment_create_group, null);
+ @SuppressLint("InflateParams") final View rootView = LayoutInflater.from(getContext()).inflate(R.layout.dialog_fragment_group_subscription, null);
//Bind ui
ButterKnife.bind(this, rootView);
-
final KeyListener hexKeyListener = new HexKeyListener();
+ if (savedInstanceState == null) {
+ mGroup = ((GroupCallbacks) requireParentFragment()).createGroup();
+ } else {
+ mGroup = savedInstanceState.getParcelable(GROUP);
+ }
+
+ if (mGroup != null) {
+ groupNameInput.setText(mGroup.getName());
+ addressInput.setText(MeshAddress.formatAddress(mGroup.getAddress(), false));
+ }
+ updateGroup();
+
+ mAdapterSpinner = new AddressTypeAdapter(requireContext(), addressTypes);
+ addressTypesSpinnerView.setAdapter(mAdapterSpinner);
+
+ groupContainer.setVisibility(View.GONE);
addressInput.setKeyListener(hexKeyListener);
addressInput.addTextChangedListener(new TextWatcher() {
@Override
@@ -91,6 +137,7 @@ public void beforeTextChanged(final CharSequence s, final int start, final int c
@Override
public void onTextChanged(final CharSequence s, final int start, final int before, final int count) {
+ mGroup = null;
if (TextUtils.isEmpty(s.toString())) {
addressInputLayout.setError(getString(R.string.error_empty_group_address));
} else {
@@ -104,33 +151,109 @@ public void afterTextChanged(final Editable s) {
}
});
- final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getContext()).setView(rootView)
- .setPositiveButton(R.string.ok, null).setNegativeButton(R.string.cancel, null);
+ addressTypesSpinnerView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(final AdapterView> parent, final View view, final int position, final long id) {
+ updateAddress(mAdapterSpinner.getItem(position));
+ }
+
+ @Override
+ public void onNothingSelected(final AdapterView> parent) {
+
+ }
+ });
+
+ final AlertDialog alertDialog = new AlertDialog.Builder(requireContext())
+ .setView(rootView)
+ .setIcon(R.drawable.ic_outline_group_work_black_alpha_24dp)
+ .setTitle(R.string.title_create_group)
+ .setPositiveButton(R.string.ok, null)
+ .setNegativeButton(R.string.cancel, null)
+ .setNeutralButton(R.string.generate_uuid, null).show();
- alertDialogBuilder.setIcon(R.drawable.ic_outline_group_work_black_alpha_24dp);
- alertDialogBuilder.setTitle(R.string.title_create_group);
+ summary.setText(R.string.title_create_group_summary);
- final AlertDialog alertDialog = alertDialogBuilder.show();
alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(v -> {
- final String name = groupNameInput.getEditableText().toString();
- final String address = addressInput.getEditableText().toString();
- if (validateInput(name, address)) {
- if(getParentFragment() != null) {
- if(((DialogFragmentCreateGroupListener) getParentFragment()).createGroup(name, Integer.valueOf(address, 16))) {
+ final String name = groupNameInput.getEditableText().toString().trim();
+ try {
+ final AddressTypes type = (AddressTypes) addressTypesSpinnerView.getSelectedItem();
+ if (type == GROUP_ADDRESS) {
+ if (mGroup == null) {
+ final String address = addressInput.getEditableText().toString().trim();
+ if (validateInput(name, address)) {
+ if (((GroupCallbacks) requireParentFragment()).onGroupAdded(name, Integer.valueOf(address, 16))) {
+ dismiss();
+ } else {
+ addressInputLayout.setError(getString(R.string.error_group_address_in_used));
+ }
+ }
+ } else {
+ if (((GroupCallbacks) requireParentFragment()).onGroupAdded(mGroup)) {
+ dismiss();
+ }
+ }
+ } else {
+
+ final UUID uuid = UUID.fromString(labelUuidView.getText().toString());
+ final Group group = ((GroupCallbacks) requireParentFragment()).createGroup(uuid, name);
+ if (group != null) {
+ if (((GroupCallbacks) requireParentFragment()).onGroupAdded(group)) {
dismiss();
- } else {
- addressInputLayout.setError(getString(R.string.error_group_address_in_used));
}
}
}
+ } catch (IllegalArgumentException ex) {
+ addressInputLayout.setError(ex.getMessage());
+ }
});
+ mGenerateLabelUUID = alertDialog.getButton(DialogInterface.BUTTON_NEUTRAL);
+ mGenerateLabelUUID.setOnClickListener(v -> {
+ final UUID uuid = MeshAddress.generateRandomLabelUUID();
+ labelUuidView.setText(uuid.toString().toUpperCase(Locale.US));
+ final Integer add = MeshAddress.generateVirtualAddress(uuid);
+ addressInput.setText(MeshAddress.formatAddress(add, false));
+ });
return alertDialog;
}
+ @Override
+ public void onSaveInstanceState(@NonNull final Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putParcelable(GROUP, mGroup);
+ }
+
+ private void updateAddress(final AddressTypes addressType) {
+ if (addressType == VIRTUAL_ADDRESS) {
+ labelSummary.setVisibility(VISIBLE);
+ labelUuidView.setVisibility(VISIBLE);
+ mGenerateLabelUUID.setVisibility(VISIBLE);
+ groupNameInputLayout.setEnabled(true);
+ groupNameInputLayout.setError(null);
+ final UUID uuid = UUID.fromString(labelUuidView.getText().toString());
+ final Integer add = MeshAddress.generateVirtualAddress(uuid);
+ addressInput.setText(String.valueOf(add));
+ addressInputLayout.setError(null);
+ addressInputLayout.setEnabled(false);
+ } else {
+ labelSummary.setVisibility(GONE);
+ labelUuidView.setVisibility(GONE);
+ mGenerateLabelUUID.setVisibility(GONE);
+ updateGroup();
+ }
+ }
+
+ private void updateGroup() {
+ if (mGroup == null) {
+ mGroup = ((GroupCallbacks) requireParentFragment()).createGroup();
+ }
+ groupNameInput.setText(mGroup.getName());
+ addressInput.setText(MeshAddress.formatAddress(mGroup.getAddress(), false));
+ }
+
private boolean validateInput(@NonNull final String name, @NonNull final String address) {
try {
- if(TextUtils.isEmpty(name)){
+ if (TextUtils.isEmpty(name)) {
groupNameInputLayout.setError(getString(R.string.error_empty_group_name));
return false;
}
@@ -140,7 +263,7 @@ private boolean validateInput(@NonNull final String name, @NonNull final String
}
final byte[] groupAddress = MeshParserUtils.toByteArray(address);
- if(!MeshParserUtils.isValidSubscriptionAddress(groupAddress)){
+ if (!MeshAddress.isValidSubscriptionAddress(groupAddress)) {
addressInputLayout.setError(getString(R.string.invalid_address_value));
return false;
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentDeleteNode.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentDeleteNode.java
new file mode 100644
index 000000000..660776df0
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentDeleteNode.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2018, Nordic Semiconductor
+ * 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 no.nordicsemi.android.nrfmeshprovisioner.dialog;
+
+import android.app.Dialog;
+import android.os.Bundle;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AlertDialog;
+import no.nordicsemi.android.nrfmeshprovisioner.R;
+import no.nordicsemi.android.nrfmeshprovisioner.utils.Utils;
+
+public class DialogFragmentDeleteNode extends DialogFragmentMessage {
+
+ private int position;
+
+ public interface DialogFragmentDeleteNodeListener {
+ void onNodeDeleteConfirmed(final int position);
+
+ void onNodeDeleteCancelled(final int position);
+ }
+
+ public static DialogFragmentDeleteNode newInstance(final int position) {
+ Bundle args = new Bundle();
+ DialogFragmentDeleteNode fragment = new DialogFragmentDeleteNode();
+ args.putInt(Utils.EXTRA_DATA, position);
+ fragment.setArguments(args);
+ return fragment;
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ if (getArguments() != null) {
+ position = getArguments().getInt(Utils.EXTRA_DATA, -1);
+ }
+ title = getString(R.string.title_delete_node);
+ message = getString(R.string.delete_node_rationale);
+
+ if (savedInstanceState != null) {
+ position = savedInstanceState.getInt(Utils.EXTRA_DATA, -1);
+ }
+ }
+
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(final Bundle savedInstanceState) {
+ alertDialogBuilder = new AlertDialog.Builder(requireActivity());
+ alertDialogBuilder.setIcon(R.drawable.ic_delete_black_alpha_24dp);
+ alertDialogBuilder.setNegativeButton(getString(R.string.no), (dialog, which) ->
+ ((DialogFragmentDeleteNodeListener) requireParentFragment()).onNodeDeleteCancelled(position));
+ alertDialogBuilder.setPositiveButton(getString(R.string.yes), (dialog, which) ->
+ ((DialogFragmentDeleteNodeListener) requireParentFragment()).onNodeDeleteConfirmed(position));
+
+ return super.onCreateDialog(savedInstanceState);
+ }
+
+ @Override
+ public void onSaveInstanceState(@NonNull final Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putInt(Utils.EXTRA_DATA, position);
+ }
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentDisconnected.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentDisconnected.java
index d827679e9..6ef726417 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentDisconnected.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentDisconnected.java
@@ -24,8 +24,8 @@
import android.app.Dialog;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v7.app.AlertDialog;
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AlertDialog;
import no.nordicsemi.android.nrfmeshprovisioner.R;
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentConfigError.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentError.java
similarity index 87%
rename from Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentConfigError.java
rename to Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentError.java
index 154ff59ba..64db668ba 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentConfigError.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentError.java
@@ -24,16 +24,16 @@
import android.app.Dialog;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v7.app.AlertDialog;
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AlertDialog;
import no.nordicsemi.android.nrfmeshprovisioner.R;
-public class DialogFragmentConfigError extends DialogFragmentMessage {
+public class DialogFragmentError extends DialogFragmentMessage {
- public static DialogFragmentConfigError newInstance(final String title, final String message) {
+ public static DialogFragmentError newInstance(@NonNull final String title, @NonNull final String message) {
Bundle args = new Bundle();
- DialogFragmentConfigError fragment = new DialogFragmentConfigError();
+ DialogFragmentError fragment = new DialogFragmentError();
args.putString(TITLE, title);
args.putString(MESSAGE, message);
fragment.setArguments(args);
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentFilterAddAddress.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentFilterAddAddress.java
index 196069ed9..e421c615b 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentFilterAddAddress.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentFilterAddAddress.java
@@ -22,31 +22,35 @@
package no.nordicsemi.android.nrfmeshprovisioner.dialog;
-import android.app.AlertDialog;
+import android.annotation.SuppressLint;
import android.app.Dialog;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.design.widget.TextInputEditText;
-import android.support.design.widget.TextInputLayout;
-import android.support.v4.app.DialogFragment;
-import android.support.v7.widget.DefaultItemAnimator;
-import android.support.v7.widget.LinearLayoutManager;
-import android.support.v7.widget.RecyclerView;
import android.text.Editable;
import android.text.TextWatcher;
import android.text.method.KeyListener;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
+import android.widget.TextView;
import android.widget.Toast;
+import com.google.android.material.textfield.TextInputEditText;
+import com.google.android.material.textfield.TextInputLayout;
+
import java.util.ArrayList;
import java.util.List;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.DialogFragment;
+import androidx.recyclerview.widget.DefaultItemAnimator;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
import butterknife.BindView;
import butterknife.ButterKnife;
import no.nordicsemi.android.meshprovisioner.utils.AddressArray;
+import no.nordicsemi.android.meshprovisioner.utils.MeshAddress;
import no.nordicsemi.android.meshprovisioner.utils.MeshParserUtils;
import no.nordicsemi.android.meshprovisioner.utils.ProxyFilterType;
import no.nordicsemi.android.nrfmeshprovisioner.R;
@@ -91,11 +95,11 @@ public void onCreate(@Nullable final Bundle savedInstanceState) {
@NonNull
@Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
- final View rootView = LayoutInflater.from(getContext()).inflate(R.layout.dialog_fragment_filter_address, null);
+ @SuppressLint("InflateParams") final View rootView = LayoutInflater.from(getContext()).inflate(R.layout.dialog_fragment_filter_address, null);
//Bind ui
ButterKnife.bind(this, rootView);
-
+ final TextView summary = rootView.findViewById(R.id.summary);
if (savedInstanceState != null) {
filterType = savedInstanceState.getParcelable(PROXY_FILTER_KEY);
addresses = savedInstanceState.getParcelableArrayList("AddressList");
@@ -109,7 +113,7 @@ public Dialog onCreateDialog(final Bundle savedInstanceState) {
final Button actionAdd = rootView.findViewById(R.id.action_add);
actionAdd.setOnClickListener(v -> {
- final String addressVal = addressInput.getEditableText().toString();
+ final String addressVal = addressInput.getEditableText().toString().trim();
if (validateInput(addressVal)) {
addressInput.getEditableText().clear();
final byte[] address = MeshParserUtils.toByteArray(addressVal);
@@ -138,22 +142,19 @@ public void afterTextChanged(final Editable s) {
}
});
- return new AlertDialog.Builder(getContext()).setView(rootView)
+ summary.setText(getString(R.string.dialog_summary_filter_address, filterType.getFilterTypeName()));
+
+ return new AlertDialog.Builder(requireContext()).setView(rootView)
.setPositiveButton(R.string.confirm, (dialog, which) -> {
if (!addresses.isEmpty()) {
- if (getParentFragment() == null) {
- ((DialogFragmentFilterAddressListener) requireActivity()).addAddresses(addresses);
- } else {
- ((DialogFragmentFilterAddressListener) getParentFragment()).addAddresses(addresses);
- }
+ ((DialogFragmentFilterAddressListener) requireParentFragment()).addAddresses(addresses);
} else {
Toast.makeText(requireContext(), R.string.error_empty_filter_address, Toast.LENGTH_SHORT).show();
}
})
.setNegativeButton(R.string.cancel, null)
.setIcon(R.drawable.ic_lan_black_alpha_24dp)
- .setTitle(R.string.title_add_address)
- .setMessage(getString(R.string.dialog_summary_filter_address, filterType.getFilterTypeName())).create();
+ .setTitle(R.string.title_add_address).create();
}
@Override
@@ -164,16 +165,14 @@ public void onSaveInstanceState(@NonNull final Bundle outState) {
}
private boolean validateInput(final String input) {
-
try {
-
if (input.length() % 4 != 0 || !input.matches(Utils.HEX_PATTERN)) {
addressInputLayout.setError(getString(R.string.invalid_address_value));
return false;
}
final byte[] address = MeshParserUtils.toByteArray(input);
- if (!MeshParserUtils.isValidUnicastAddress(address) && !MeshParserUtils.isValidFilterAddress(address)) {
+ if (!MeshAddress.isValidProxyFilterAddress(address)) {
addressInputLayout.setError(getString(R.string.invalid_filter_address));
return false;
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentFlags.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentFlags.java
deleted file mode 100644
index 0e889874b..000000000
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentFlags.java
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Copyright (c) 2018, Nordic Semiconductor
- * 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 no.nordicsemi.android.nrfmeshprovisioner.dialog;
-
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.content.DialogInterface;
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.v4.app.DialogFragment;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.RadioButton;
-import android.widget.RadioGroup;
-
-import butterknife.BindView;
-import butterknife.ButterKnife;
-import no.nordicsemi.android.nrfmeshprovisioner.R;
-
-
-public class DialogFragmentFlags extends DialogFragment {
-
- private static final String KEY_REFRESH_FLAG = "KEY_REFRESH_FLAG";
- private static final String IV_UPDATE_FLAG = "IV_UPDATE_FLAG";
- //UI Bindings
- @BindView(R.id.radio_group_refresh_flag)
- RadioGroup radioGroupKeyRefreshFlag;
- @BindView(R.id.radio_group_iv_update_flag)
- RadioGroup radioGroupIVUpdateFlag;
- @BindView(R.id.radio_key_refresh_phase_0)
- RadioButton radioKeyRefreshPhase0;
- @BindView(R.id.radio_key_refresh_phase_2)
- RadioButton radioKeyRefreshPhase2;
- @BindView(R.id.radio_normal_operation)
- RadioButton radioNormalOperation;
- @BindView(R.id.radio_iv_update_active)
- RadioButton radioIvUpdate;
-
- private int mKeyRefreshFlag;
- private int mIvUpdateFlag;
-
- public static DialogFragmentFlags newInstance(final int keyRefreshFlag, final int ivUpdateFlag) {
- DialogFragmentFlags fragmentNetworkKey = new DialogFragmentFlags();
- final Bundle args = new Bundle();
- args.putInt(KEY_REFRESH_FLAG, keyRefreshFlag);
- args.putInt(IV_UPDATE_FLAG, ivUpdateFlag);
- fragmentNetworkKey.setArguments(args);
- return fragmentNetworkKey;
- }
-
- @Override
- public void onCreate(@Nullable final Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- if (getArguments() != null) {
- mKeyRefreshFlag = getArguments().getInt(KEY_REFRESH_FLAG);
- mIvUpdateFlag = getArguments().getInt(IV_UPDATE_FLAG);
- }
- }
-
- @NonNull
- @Override
- public Dialog onCreateDialog(final Bundle savedInstanceState) {
- final View rootView = LayoutInflater.from(getContext()).inflate(R.layout.dialog_fragment_flags_input, null);
-
- //Bind ui
- ButterKnife.bind(this, rootView);
-
- if (mKeyRefreshFlag == 0)
- radioKeyRefreshPhase0.setChecked(true);
- else
- radioKeyRefreshPhase2.setChecked(true);
-
- if (mIvUpdateFlag == 0)
- radioNormalOperation.setChecked(true);
- else
- radioIvUpdate.setChecked(true);
-
-
- radioGroupKeyRefreshFlag.setEnabled(false);
- radioGroupIVUpdateFlag.setEnabled(false);
-
- final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getContext()).setView(rootView)
- .setPositiveButton(R.string.ok, null).setNegativeButton(R.string.cancel, null);
-
- alertDialogBuilder.setIcon(R.drawable.ic_flag);
- alertDialogBuilder.setTitle(R.string.title_flags);
- alertDialogBuilder.setMessage(R.string.dialog_summary_flags);
-
- final AlertDialog alertDialog = alertDialogBuilder.show();
- alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(v -> {
- if (validateInput()) {
- final int keyRefreshFlag = parseKeyRefreshFlag();
- final int ivUpdateFlag = parseIvUpdateFlag();
- if (getParentFragment() == null) {
- ((DialogFragmentFlagsListener) getActivity()).onFlagsSelected(keyRefreshFlag, ivUpdateFlag);
- } else {
- ((DialogFragmentFlagsListener) getParentFragment()).onFlagsSelected(keyRefreshFlag, ivUpdateFlag);
- }
- dismiss();
- }
- });
-
- return alertDialog;
- }
-
- private boolean validateInput() {
-
- int refreshFlagId = radioGroupKeyRefreshFlag.getCheckedRadioButtonId();
- switch (refreshFlagId) {
- case R.id.radio_key_refresh_phase_0:
- case R.id.radio_key_refresh_phase_2:
- break;
- default:
- return false;
- }
-
- int updateFlagId = radioGroupIVUpdateFlag.getCheckedRadioButtonId();
- switch (updateFlagId) {
- case R.id.radio_normal_operation:
- case R.id.radio_iv_update_active:
- break;
- default:
- return false;
- }
- return true;
- }
-
- private int parseKeyRefreshFlag() {
- int refreshFlagId = radioGroupKeyRefreshFlag.getCheckedRadioButtonId();
- switch (refreshFlagId) {
- default:
- case R.id.radio_key_refresh_phase_0:
- return 0;
- case R.id.radio_key_refresh_phase_2:
- return 1;
- }
- }
-
- private int parseIvUpdateFlag() {
- int refreshFlagId = radioGroupIVUpdateFlag.getCheckedRadioButtonId();
- switch (refreshFlagId) {
- default:
- case R.id.radio_normal_operation:
- return 0;
- case R.id.radio_iv_update_active:
- return 1;
- }
- }
-
- public interface DialogFragmentFlagsListener {
-
- void onFlagsSelected(final int keyRefreshFlag, final int ivUpdateFlag);
-
- }
-}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentGroupSubscription.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentGroupSubscription.java
index 9d4d43410..e936c2d38 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentGroupSubscription.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentGroupSubscription.java
@@ -22,41 +22,60 @@
package no.nordicsemi.android.nrfmeshprovisioner.dialog;
-import android.app.AlertDialog;
+import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.design.widget.TextInputEditText;
-import android.support.design.widget.TextInputLayout;
-import android.support.v4.app.DialogFragment;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.text.method.KeyListener;
import android.view.LayoutInflater;
import android.view.View;
+import android.widget.AdapterView;
+import android.widget.Button;
import android.widget.RadioButton;
import android.widget.Spinner;
import android.widget.TextView;
+import com.google.android.material.textfield.TextInputEditText;
+import com.google.android.material.textfield.TextInputLayout;
+
import java.util.ArrayList;
+import java.util.Locale;
+import java.util.UUID;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.DialogFragment;
import butterknife.BindView;
import butterknife.ButterKnife;
import no.nordicsemi.android.meshprovisioner.Group;
import no.nordicsemi.android.meshprovisioner.utils.MeshAddress;
+import no.nordicsemi.android.nrfmeshprovisioner.GroupCallbacks;
import no.nordicsemi.android.nrfmeshprovisioner.R;
+import no.nordicsemi.android.nrfmeshprovisioner.adapter.AddressTypeAdapter;
import no.nordicsemi.android.nrfmeshprovisioner.adapter.GroupAdapterSpinner;
+import no.nordicsemi.android.nrfmeshprovisioner.utils.AddressTypes;
import no.nordicsemi.android.nrfmeshprovisioner.utils.HexKeyListener;
import no.nordicsemi.android.nrfmeshprovisioner.utils.Utils;
+import static android.view.View.GONE;
+import static android.view.View.VISIBLE;
+import static no.nordicsemi.android.nrfmeshprovisioner.utils.AddressTypes.GROUP_ADDRESS;
+import static no.nordicsemi.android.nrfmeshprovisioner.utils.AddressTypes.VIRTUAL_ADDRESS;
public class DialogFragmentGroupSubscription extends DialogFragment {
+ private static final AddressTypes[] addressTypes = {GROUP_ADDRESS, VIRTUAL_ADDRESS};
private static final String GROUPS = "GROUPS";
+ private static final String GROUP = "GROUP";
//UI Bindings
+ @BindView(R.id.address_types)
+ Spinner addressTypesSpinnerView;
+ @BindView(R.id.group_container)
+ View groupContainer;
@BindView(R.id.radio_select_group)
RadioButton selectGroup;
@BindView(R.id.radio_create_group)
@@ -73,16 +92,17 @@ public class DialogFragmentGroupSubscription extends DialogFragment {
TextInputEditText addressInput;
@BindView(R.id.no_groups_configured)
TextView noGroups;
+ @BindView(R.id.label_summary)
+ TextView labelSummary;
+ @BindView(R.id.uuid_label)
+ TextView labelUuidView;
- private ArrayList mGroups;
-
+ private Button mGenerateLabelUUID;
- public interface DialogFragmentSubscriptionAddressListener {
+ private AddressTypeAdapter mAdapterSpinner;
- void setGroupSubscription(@NonNull final String name, final int address);
- void setGroupSubscription(@NonNull final Group group);
-
- }
+ private ArrayList mGroups;
+ private Group mGroup;
public static DialogFragmentGroupSubscription newInstance(final ArrayList groups) {
final DialogFragmentGroupSubscription fragment = new DialogFragmentGroupSubscription();
@@ -103,10 +123,16 @@ public void onCreate(@Nullable final Bundle savedInstanceState) {
@NonNull
@Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
- final View rootView = LayoutInflater.from(getContext()).inflate(R.layout.dialog_fragment_group_subscription, null);
+ @SuppressLint("InflateParams") final View rootView = LayoutInflater.from(getContext()).
+ inflate(R.layout.dialog_fragment_group_subscription, null);
//Bind ui
ButterKnife.bind(this, rootView);
+ if (savedInstanceState == null) {
+ mGroup = ((GroupCallbacks) requireActivity()).createGroup();
+ } else {
+ mGroup = savedInstanceState.getParcelable(GROUP);
+ }
selectGroup.setOnCheckedChangeListener((buttonView, isChecked) -> {
groupNameInputLayout.setEnabled(!isChecked);
@@ -124,12 +150,21 @@ public Dialog onCreateDialog(final Bundle savedInstanceState) {
addressInputLayout.setError(null);
groups.setEnabled(!isChecked);
selectGroup.setChecked(!isChecked);
+ if (isChecked) {
+ if (mGroup != null) {
+ groupNameInput.setText(mGroup.getName());
+ addressInput.setText(MeshAddress.formatAddress(mGroup.getAddress(), false));
+ }
+ }
});
+ mAdapterSpinner = new AddressTypeAdapter(requireContext(), addressTypes);
+ addressTypesSpinnerView.setAdapter(mAdapterSpinner);
+
final GroupAdapterSpinner adapter = new GroupAdapterSpinner(requireContext(), mGroups);
groups.setAdapter(adapter);
- if(mGroups.isEmpty()){
+ if (mGroups.isEmpty()) {
selectGroup.setEnabled(false);
groups.setEnabled(false);
createGroup.setChecked(true);
@@ -138,6 +173,20 @@ public Dialog onCreateDialog(final Bundle savedInstanceState) {
createGroup.setChecked(false);
}
+ updateGroup();
+
+ addressTypesSpinnerView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(final AdapterView> parent, final View view, final int position, final long id) {
+ updateAddress(mAdapterSpinner.getItem(position));
+ }
+
+ @Override
+ public void onNothingSelected(final AdapterView> parent) {
+
+ }
+ });
+
final KeyListener hexKeyListener = new HexKeyListener();
addressInput.setKeyListener(hexKeyListener);
addressInput.addTextChangedListener(new TextWatcher() {
@@ -148,6 +197,7 @@ public void beforeTextChanged(final CharSequence s, final int start, final int c
@Override
public void onTextChanged(final CharSequence s, final int start, final int before, final int count) {
+ mGroup = null;
if (TextUtils.isEmpty(s.toString())) {
addressInputLayout.setError(getString(R.string.error_empty_group_address));
} else {
@@ -161,34 +211,109 @@ public void afterTextChanged(final Editable s) {
}
});
- final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getContext()).setView(rootView)
- .setPositiveButton(R.string.ok, null).setNegativeButton(R.string.cancel, null);
-
- alertDialogBuilder.setIcon(R.drawable.ic_subscribe_black_alpha_24dp);
- alertDialogBuilder.setTitle(R.string.title_subscribe_group);
+ final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(requireContext())
+ .setIcon(R.drawable.ic_subscribe_black_alpha_24dp)
+ .setTitle(R.string.title_subscribe_group)
+ .setView(rootView)
+ .setPositiveButton(R.string.ok, null)
+ .setNegativeButton(R.string.cancel, null)
+ .setNeutralButton(R.string.generate_uuid, null);
final AlertDialog alertDialog = alertDialogBuilder.show();
alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(v -> {
- if(createGroup.isChecked()) {
- final String name = groupNameInput.getEditableText().toString();
- final String address = addressInput.getEditableText().toString();
- if (validateInput(name, address)) {
- ((DialogFragmentSubscriptionAddressListener) requireActivity()).setGroupSubscription(name, Integer.valueOf(address, 16));
- dismiss();
+ final AddressTypes type = (AddressTypes) addressTypesSpinnerView.getSelectedItem();
+ try {
+ if (type == GROUP_ADDRESS) {
+ if (createGroup.isChecked()) {
+ if (mGroup != null) {
+ if (((GroupCallbacks) requireActivity()).onGroupAdded(mGroup)) {
+ dismiss();
+ }
+ } else {
+ final String name = groupNameInput.getEditableText().toString().trim();
+ final String address = addressInput.getEditableText().toString().trim();
+ if (validateInput(name, address)) {
+ if ((((GroupCallbacks) requireActivity())).
+ onGroupAdded(name, Integer.valueOf(address, 16))) {
+ dismiss();
+ }
+ }
+ }
+ } else {
+ final Group group = (Group) groups.getSelectedItem();
+ ((GroupCallbacks) requireActivity()).subscribe(group);
+ dismiss();
+ }
+ } else {
+ final UUID uuid = UUID.fromString(labelUuidView.getText().toString().trim());
+ final String name = groupNameInput.getEditableText().toString().trim();
+ final Group group = ((GroupCallbacks) requireActivity()).createGroup(uuid, name);
+ if (group != null) {
+ if (((GroupCallbacks) requireActivity()).onGroupAdded(group)) {
+ dismiss();
+ }
+ }
}
- } else {
- final Group group = (Group) groups.getSelectedItem();
- ((DialogFragmentSubscriptionAddressListener) requireActivity()).setGroupSubscription(group);
- dismiss();
+ } catch (IllegalArgumentException ex) {
+ addressInputLayout.setError(ex.getMessage());
}
});
+ mGenerateLabelUUID = alertDialog.getButton(DialogInterface.BUTTON_NEUTRAL);
+ mGenerateLabelUUID.setOnClickListener(v -> {
+ final UUID uuid = MeshAddress.generateRandomLabelUUID();
+ labelUuidView.setText(uuid.toString().toUpperCase(Locale.US));
+ generateVirtualAddress(uuid);
+ });
+
return alertDialog;
}
+ @Override
+ public void onSaveInstanceState(@NonNull final Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putParcelable(GROUP, mGroup);
+ }
+
+ private void updateAddress(@NonNull final AddressTypes addressType) {
+ if (addressType == VIRTUAL_ADDRESS) {
+ labelSummary.setVisibility(VISIBLE);
+ labelUuidView.setVisibility(VISIBLE);
+ mGenerateLabelUUID.setVisibility(VISIBLE);
+ groupContainer.setVisibility(GONE);
+ groupNameInputLayout.setEnabled(true);
+ groupNameInputLayout.setError(null);
+ addressInputLayout.setError(null);
+ addressInputLayout.setEnabled(false);
+ generateVirtualAddress(UUID.fromString(labelUuidView.getText().toString()));
+ } else {
+ groupContainer.setVisibility(VISIBLE);
+ labelSummary.setVisibility(GONE);
+ labelUuidView.setVisibility(GONE);
+ mGenerateLabelUUID.setVisibility(GONE);
+ updateGroup();
+ }
+ }
+
+ private void generateVirtualAddress(@NonNull final UUID uuid) {
+ final Integer add = MeshAddress.generateVirtualAddress(uuid);
+ addressInput.setText(MeshAddress.formatAddress(add, false));
+ }
+
+ private void updateGroup() {
+ if (mGroup == null) {
+ mGroup = ((GroupCallbacks) requireActivity()).createGroup();
+ }
+
+ if (mGroup != null) {
+ groupNameInput.setText(mGroup.getName());
+ addressInput.setText(MeshAddress.formatAddress(mGroup.getAddress(), false));
+ }
+ }
+
private boolean validateInput(@NonNull final String name, @NonNull final String address) {
try {
- if(TextUtils.isEmpty(name)){
+ if (TextUtils.isEmpty(name)) {
groupNameInputLayout.setError(getString(R.string.error_empty_group_name));
return false;
}
@@ -198,13 +323,13 @@ private boolean validateInput(@NonNull final String name, @NonNull final String
}
final int groupAddress = Integer.valueOf(address, 16);
- if(!MeshAddress.isValidGroupAddress(groupAddress)){
+ if (!MeshAddress.isValidGroupAddress(groupAddress)) {
addressInputLayout.setError(getString(R.string.invalid_address_value));
return false;
}
- for(Group group : mGroups) {
- if(groupAddress == group.getGroupAddress()){
+ for (Group group : mGroups) {
+ if (groupAddress == group.getAddress()) {
addressInputLayout.setError(getString(R.string.error_group_address_in_used));
return false;
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentIvIndex.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentIvIndex.java
deleted file mode 100644
index 59c9bcc13..000000000
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentIvIndex.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (c) 2018, Nordic Semiconductor
- * 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 no.nordicsemi.android.nrfmeshprovisioner.dialog;
-
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.content.DialogInterface;
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.design.widget.TextInputEditText;
-import android.support.design.widget.TextInputLayout;
-import android.support.v4.app.DialogFragment;
-import android.text.Editable;
-import android.text.TextUtils;
-import android.text.TextWatcher;
-import android.text.method.KeyListener;
-import android.view.LayoutInflater;
-import android.view.View;
-
-import java.util.Locale;
-
-import butterknife.BindView;
-import butterknife.ButterKnife;
-import no.nordicsemi.android.meshprovisioner.utils.MeshParserUtils;
-import no.nordicsemi.android.nrfmeshprovisioner.R;
-import no.nordicsemi.android.nrfmeshprovisioner.utils.HexKeyListener;
-import no.nordicsemi.android.nrfmeshprovisioner.utils.Utils;
-
-
-public class DialogFragmentIvIndex extends DialogFragment {
-
- private static final String IV_INDEX = "IV_INDEX";
- //UI Bindings
- @BindView(R.id.text_input_layout)
- TextInputLayout ivIndexInputLayout;
- @BindView(R.id.text_input)
- TextInputEditText ivIndexInput;
-
- private int mIvIndex;
-
- public static DialogFragmentIvIndex newInstance(final int ivIndex) {
- DialogFragmentIvIndex fragmentIvIndex = new DialogFragmentIvIndex();
- final Bundle args = new Bundle();
- args.putInt(IV_INDEX, ivIndex);
- fragmentIvIndex.setArguments(args);
- return fragmentIvIndex;
- }
-
- @Override
- public void onCreate(@Nullable final Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- if (getArguments() != null) {
- mIvIndex = getArguments().getInt(IV_INDEX);
- }
- }
-
- @NonNull
- @Override
- public Dialog onCreateDialog(final Bundle savedInstanceState) {
- final View rootView = LayoutInflater.from(getContext()).inflate(R.layout.dialog_fragment_ivindex_input, null);
-
- //Bind ui
- ButterKnife.bind(this, rootView);
-
- final KeyListener hexKeyListener = new HexKeyListener();
- final String ivIndex = String.format(Locale.US, "%08X", mIvIndex);
- ivIndexInputLayout.setHint(getString(R.string.hint_iv_index));
- ivIndexInput.setText(ivIndex);
- ivIndexInput.setKeyListener(hexKeyListener);
- ivIndexInput.setSelection(ivIndex.length());
- ivIndexInput.addTextChangedListener(new TextWatcher() {
- @Override
- public void beforeTextChanged(final CharSequence s, final int start, final int count, final int after) {
-
- }
-
- @Override
- public void onTextChanged(final CharSequence s, final int start, final int before, final int count) {
- if (TextUtils.isEmpty(s.toString())) {
- ivIndexInputLayout.setError(getString(R.string.error_empty_iv_index));
- } else {
- ivIndexInputLayout.setError(null);
- }
- }
-
- @Override
- public void afterTextChanged(final Editable s) {
-
- }
- });
-
- final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getContext()).setView(rootView)
- .setPositiveButton(R.string.ok, null).setNegativeButton(R.string.cancel, null);
-
- alertDialogBuilder.setIcon(R.drawable.ic_list);
- alertDialogBuilder.setTitle(R.string.title_iv_index);
- alertDialogBuilder.setMessage(R.string.dialog_summary_iv_index);
-
- final AlertDialog alertDialog = alertDialogBuilder.show();
- alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(v -> {
- final String ivIndexInput = this.ivIndexInput.getText().toString();
- if (validateInput(ivIndexInput)) {
- if (getParentFragment() == null) {
- ((DialogFragmentIvIndexListener) getActivity()).setIvIndex(Integer.parseInt(ivIndexInput, 16));
- } else {
- ((DialogFragmentIvIndexListener) getParentFragment()).setIvIndex(Integer.parseInt(ivIndexInput, 16));
- }
- dismiss();
- }
- });
-
- return alertDialog;
- }
-
- private boolean validateInput(final String input) {
-
- try {
-
- if(!input.matches(Utils.HEX_PATTERN)) {
- ivIndexInputLayout.setError(getString(R.string.invalid_hex_value));
- return false;
- }
- if (MeshParserUtils.validateIvIndexInput(getContext(), input)) {
- return true;
- }
- } catch (IllegalArgumentException ex) {
- ivIndexInputLayout.setError(ex.getMessage());
- }
-
- return false;
- }
-
- public interface DialogFragmentIvIndexListener {
-
- void setIvIndex(final int ivIndex);
-
- }
-}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentKeyIndex.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentKeyIndex.java
deleted file mode 100644
index 77fc8fe9e..000000000
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentKeyIndex.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (c) 2018, Nordic Semiconductor
- * 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 no.nordicsemi.android.nrfmeshprovisioner.dialog;
-
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.content.DialogInterface;
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.design.widget.TextInputEditText;
-import android.support.design.widget.TextInputLayout;
-import android.support.v4.app.DialogFragment;
-import android.text.Editable;
-import android.text.TextUtils;
-import android.text.TextWatcher;
-import android.text.method.KeyListener;
-import android.view.LayoutInflater;
-import android.view.View;
-
-import java.util.Locale;
-
-import butterknife.BindView;
-import butterknife.ButterKnife;
-import no.nordicsemi.android.meshprovisioner.utils.MeshParserUtils;
-import no.nordicsemi.android.nrfmeshprovisioner.R;
-import no.nordicsemi.android.nrfmeshprovisioner.utils.HexKeyListener;
-import no.nordicsemi.android.nrfmeshprovisioner.utils.Utils;
-
-
-public class DialogFragmentKeyIndex extends DialogFragment {
-
- private static final String KEY_INDEX = "KEY_INDEX";
- //UI Bindings
- @BindView(R.id.text_input_layout)
- TextInputLayout keyIndexInputLayout;
- @BindView(R.id.text_input)
- TextInputEditText keyIndexInput;
-
- private int mKeyIndex;
-
- public static DialogFragmentKeyIndex newInstance(final int networkKeyIndex) {
- DialogFragmentKeyIndex fragmentNetworkKey = new DialogFragmentKeyIndex();
- final Bundle args = new Bundle();
- args.putInt(KEY_INDEX, networkKeyIndex);
- fragmentNetworkKey.setArguments(args);
- return fragmentNetworkKey;
- }
-
- @Override
- public void onCreate(@Nullable final Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- if (getArguments() != null) {
- mKeyIndex = getArguments().getInt(KEY_INDEX);
- }
- }
-
- @NonNull
- @Override
- public Dialog onCreateDialog(final Bundle savedInstanceState) {
- final View rootView = LayoutInflater.from(getContext()).inflate(R.layout.dialog_fragment_key_index_input, null);
-
- //Bind ui
- ButterKnife.bind(this, rootView);
-
- final KeyListener hexKeyListener = new HexKeyListener();
- keyIndexInputLayout.setHint(getString((R.string.hint_key_index)));
- final String netKeyIndex = String.format(Locale.US, "%03X", mKeyIndex);
- keyIndexInput.setKeyListener(hexKeyListener);
- keyIndexInput.setText(netKeyIndex);
- keyIndexInput.setSelection(netKeyIndex.length());
- keyIndexInput.addTextChangedListener(new TextWatcher() {
- @Override
- public void beforeTextChanged(final CharSequence s, final int start, final int count, final int after) {
-
- }
-
- @Override
- public void onTextChanged(final CharSequence s, final int start, final int before, final int count) {
- if (TextUtils.isEmpty(s.toString())) {
- keyIndexInputLayout.setError(getString(R.string.error_empty_key_index));
- } else {
- keyIndexInputLayout.setError(null);
- }
- }
-
- @Override
- public void afterTextChanged(final Editable s) {
-
- }
- });
-
- final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getContext()).setView(rootView)
- .setPositiveButton(R.string.ok, null).setNegativeButton(R.string.cancel, null);
-
- alertDialogBuilder.setIcon(R.drawable.ic_numeric);
- alertDialogBuilder.setTitle(R.string.title_key_index);
- alertDialogBuilder.setMessage(R.string.dialog_summary_key_index);
-
- final AlertDialog alertDialog = alertDialogBuilder.show();
- alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(v -> {
- final String keyIndex = keyIndexInput.getText().toString();
- if (validateInput(keyIndex)) {
- if ((getParentFragment()) == null) {
- ((DialogFragmentKeyIndexListener) getActivity()).onKeyIndexGenerated(Integer.valueOf(keyIndex));
- } else {
- ((DialogFragmentKeyIndexListener) getParentFragment()).onKeyIndexGenerated(Integer.valueOf(keyIndex));
- }
- dismiss();
- }
- });
-
- return alertDialog;
- }
-
- private boolean validateInput(final String input) {
- try {
-
- if(!input.matches(Utils.HEX_PATTERN)) {
- keyIndexInputLayout.setError(getString(R.string.invalid_hex_value));
- return false;
- }
-
- if (MeshParserUtils.validateKeyIndexInput(getContext(), input)) {
- return true;
- }
- } catch (IllegalArgumentException ex) {
- keyIndexInputLayout.setError(ex.getMessage());
- }
- return false;
- }
-
- public interface DialogFragmentKeyIndexListener {
-
- void onKeyIndexGenerated(final int keyIndex);
-
- }
-}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentMeshExportMsg.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentMeshExportMsg.java
index 22b418298..6fe40272f 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentMeshExportMsg.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentMeshExportMsg.java
@@ -24,8 +24,8 @@
import android.app.Dialog;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v7.app.AlertDialog;
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AlertDialog;
import no.nordicsemi.android.nrfmeshprovisioner.R;
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentMeshImport.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentMeshImport.java
index dd8501df8..f5cc8a215 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentMeshImport.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentMeshImport.java
@@ -24,8 +24,8 @@
import android.app.Dialog;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v7.app.AlertDialog;
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AlertDialog;
import no.nordicsemi.android.nrfmeshprovisioner.R;
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentMeshImportMsg.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentMeshImportMsg.java
index d7588acc8..64482d6cd 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentMeshImportMsg.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentMeshImportMsg.java
@@ -24,8 +24,8 @@
import android.app.Dialog;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v7.app.AlertDialog;
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AlertDialog;
import no.nordicsemi.android.nrfmeshprovisioner.R;
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentMessage.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentMessage.java
index d0e6cc660..3a6256e71 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentMessage.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentMessage.java
@@ -25,13 +25,13 @@
import android.app.Dialog;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v4.app.DialogFragment;
-import android.support.v7.app.AlertDialog;
+import androidx.annotation.NonNull;
+import androidx.fragment.app.DialogFragment;
+import androidx.appcompat.app.AlertDialog;
public class DialogFragmentMessage extends DialogFragment {
- protected static final String ICON_RES_ID = "ICON_RES_ID";
+ static final String ICON_RES_ID = "ICON_RES_ID";
protected static final String TITLE = "TITLE";
protected static final String MESSAGE = "MESSAGE";
protected AlertDialog.Builder alertDialogBuilder;
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentGlobalNetworkName.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentNetworkName.java
similarity index 78%
rename from Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentGlobalNetworkName.java
rename to Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentNetworkName.java
index 95e6fffdf..ad36ee939 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentGlobalNetworkName.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentNetworkName.java
@@ -22,26 +22,29 @@
package no.nordicsemi.android.nrfmeshprovisioner.dialog;
-import android.app.AlertDialog;
+import androidx.appcompat.app.AlertDialog;
+
+import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.design.widget.TextInputEditText;
-import android.support.design.widget.TextInputLayout;
-import android.support.v4.app.DialogFragment;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import com.google.android.material.textfield.TextInputEditText;
+import com.google.android.material.textfield.TextInputLayout;
+import androidx.fragment.app.DialogFragment;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
+import android.widget.TextView;
import butterknife.BindView;
import butterknife.ButterKnife;
import no.nordicsemi.android.nrfmeshprovisioner.R;
-public class DialogFragmentGlobalNetworkName extends DialogFragment {
+public class DialogFragmentNetworkName extends DialogFragment {
private static final String NETWORK_NAME = "NETWORK_NAME";
@@ -53,8 +56,8 @@ public class DialogFragmentGlobalNetworkName extends DialogFragment {
private String mNetworkName;
- public static DialogFragmentGlobalNetworkName newInstance(final String networkName) {
- DialogFragmentGlobalNetworkName fragmentNetworkKey = new DialogFragmentGlobalNetworkName();
+ public static DialogFragmentNetworkName newInstance(final String networkName) {
+ DialogFragmentNetworkName fragmentNetworkKey = new DialogFragmentNetworkName();
final Bundle args = new Bundle();
args.putString(NETWORK_NAME, networkName);
fragmentNetworkKey.setArguments(args);
@@ -72,10 +75,12 @@ public void onCreate(@Nullable final Bundle savedInstanceState) {
@NonNull
@Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
- final View rootView = LayoutInflater.from(getContext()).inflate(R.layout.dialog_fragment_name, null);
+ @SuppressLint("InflateParams") final View rootView = LayoutInflater
+ .from(getContext()).inflate(R.layout.dialog_fragment_name, null);
//Bind ui
ButterKnife.bind(this, rootView);
+ final TextView summary = rootView.findViewById(R.id.summary);
networkNameInputLayout.setHint(getString(R.string.hint_global_network_name));
networkNameInput.setText(mNetworkName);
networkNameInput.addTextChangedListener(new TextWatcher() {
@@ -87,7 +92,7 @@ public void beforeTextChanged(final CharSequence s, final int start, final int c
@Override
public void onTextChanged(final CharSequence s, final int start, final int before, final int count) {
if (TextUtils.isEmpty(s.toString())) {
- networkNameInputLayout.setError(getString(R.string.error_empty_network_key));
+ networkNameInputLayout.setError(getString(R.string.error_empty_name));
} else {
networkNameInputLayout.setError(null);
}
@@ -99,19 +104,19 @@ public void afterTextChanged(final Editable s) {
}
});
- final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getContext()).setView(rootView)
+ final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(requireContext()).setView(rootView)
.setPositiveButton(R.string.ok, null).setNegativeButton(R.string.cancel, null);
- alertDialogBuilder.setIcon(R.drawable.ic_lan_black_alpha_24dp);
+ alertDialogBuilder.setIcon(R.drawable.ic_label_black_alpha_24dp);
alertDialogBuilder.setTitle(R.string.title_network_name);
- alertDialogBuilder.setMessage(R.string.summary_network_name);
+ summary.setText(R.string.summary_network_name);
final AlertDialog alertDialog = alertDialogBuilder.show();
alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(v -> {
- final String networkKey = networkNameInput.getText().toString();
+ final String networkKey = networkNameInput.getEditableText().toString().trim();
if (validateInput(networkKey)) {
if(getParentFragment() == null) {
- ((DialogFragmentNetworkNameListener) getActivity()).onNetworkNameEntered(networkKey);
+ ((DialogFragmentNetworkNameListener) requireActivity()).onNetworkNameEntered(networkKey);
} else {
((DialogFragmentNetworkNameListener) getParentFragment()).onNetworkNameEntered(networkKey);
}
@@ -124,7 +129,7 @@ public void afterTextChanged(final Editable s) {
private boolean validateInput(final String input) {
if(TextUtils.isEmpty(input)){
- networkNameInputLayout.setError(getString(R.string.error_empty_network_name));
+ networkNameInputLayout.setError(getString(R.string.error_empty_name));
return false;
}
@@ -133,7 +138,7 @@ private boolean validateInput(final String input) {
public interface DialogFragmentNetworkNameListener {
- void onNetworkNameEntered(final String networkKey);
+ void onNetworkNameEntered(@NonNull final String name);
}
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentPermissionRationale.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentPermissionRationale.java
index 2aa1426a8..40d9347a3 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentPermissionRationale.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentPermissionRationale.java
@@ -27,8 +27,8 @@
import android.net.Uri;
import android.os.Bundle;
import android.provider.Settings;
-import android.support.annotation.NonNull;
-import android.support.v7.app.AlertDialog;
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AlertDialog;
import no.nordicsemi.android.nrfmeshprovisioner.R;
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentProvisioningFailedError.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentProvisioningFailedError.java
index e82cf5d12..af86f7b85 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentProvisioningFailedError.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentProvisioningFailedError.java
@@ -24,8 +24,8 @@
import android.app.Dialog;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v7.app.AlertDialog;
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AlertDialog;
import no.nordicsemi.android.nrfmeshprovisioner.R;
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentProxySet.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentProxySet.java
index f679803d4..8a5ccc4bc 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentProxySet.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentProxySet.java
@@ -24,8 +24,8 @@
import android.app.Dialog;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v7.app.AlertDialog;
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AlertDialog;
import no.nordicsemi.android.meshprovisioner.transport.ConfigProxySet;
import no.nordicsemi.android.nrfmeshprovisioner.R;
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentPublishAddress.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentPublishAddress.java
deleted file mode 100644
index 21083b41c..000000000
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentPublishAddress.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (c) 2018, Nordic Semiconductor
- * 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 no.nordicsemi.android.nrfmeshprovisioner.dialog;
-
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.content.DialogInterface;
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.design.widget.TextInputEditText;
-import android.support.design.widget.TextInputLayout;
-import android.support.v4.app.DialogFragment;
-import android.text.Editable;
-import android.text.TextUtils;
-import android.text.TextWatcher;
-import android.text.method.KeyListener;
-import android.view.LayoutInflater;
-import android.view.View;
-
-import butterknife.BindView;
-import butterknife.ButterKnife;
-import no.nordicsemi.android.meshprovisioner.utils.MeshParserUtils;
-import no.nordicsemi.android.nrfmeshprovisioner.R;
-import no.nordicsemi.android.nrfmeshprovisioner.utils.HexKeyListener;
-import no.nordicsemi.android.nrfmeshprovisioner.utils.Utils;
-
-
-public class DialogFragmentPublishAddress extends DialogFragment {
-
- private static final String PUBLISH_ADDRESS = "PUBLISH_ADDRESS";
- private byte[] mPublishAddress;
-
- //UI Bindings
- @BindView(R.id.text_input_layout)
- TextInputLayout unicastAddressInputLayout;
- @BindView(R.id.text_input)
- TextInputEditText unicastAddressInput;
-
- public static DialogFragmentPublishAddress newInstance(final byte[] publishAddress) {
- DialogFragmentPublishAddress fragmentPublishAddress = new DialogFragmentPublishAddress();
- final Bundle args = new Bundle();
- args.putByteArray(PUBLISH_ADDRESS, publishAddress);
- fragmentPublishAddress.setArguments(args);
- return fragmentPublishAddress;
- }
-
- @Override
- public void onCreate(@Nullable final Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- if(getArguments() != null) {
- mPublishAddress = getArguments().getByteArray(PUBLISH_ADDRESS);
- }
- }
-
- @NonNull
- @Override
- public Dialog onCreateDialog(final Bundle savedInstanceState) {
- final View rootView = LayoutInflater.from(getContext()).inflate(R.layout.dialog_fragment_address_input, null);
-
- //Bind ui
- ButterKnife.bind(this, rootView);
- final String publishAddress;
- if(mPublishAddress != null) {
- publishAddress = MeshParserUtils.bytesToHex(mPublishAddress, false);
- unicastAddressInput.setText(publishAddress);
- }
-
- final KeyListener hexKeyListener = new HexKeyListener();
- unicastAddressInputLayout.setHint(getString((R.string.hint_publish_address)));
- unicastAddressInput.setKeyListener(hexKeyListener);
- unicastAddressInput.addTextChangedListener(new TextWatcher() {
- @Override
- public void beforeTextChanged(final CharSequence s, final int start, final int count, final int after) {
-
- }
-
- @Override
- public void onTextChanged(final CharSequence s, final int start, final int before, final int count) {
- if (TextUtils.isEmpty(s.toString())) {
- unicastAddressInputLayout.setError(getString(R.string.error_empty_publish_address));
- } else {
- unicastAddressInputLayout.setError(null);
- }
- }
-
- @Override
- public void afterTextChanged(final Editable s) {
-
- }
- });
-
- final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getContext()).setView(rootView)
- .setPositiveButton(R.string.ok, null).setNegativeButton(R.string.cancel, null);
-
- alertDialogBuilder.setIcon(R.drawable.ic_lan_black_alpha_24dp);
- alertDialogBuilder.setTitle(R.string.title_publish_address);
- alertDialogBuilder.setMessage(R.string.dialog_summary_publish_address);
-
- final AlertDialog alertDialog = alertDialogBuilder.show();
- alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(v -> {
- final String pubAddress = unicastAddressInput.getText().toString();
- if (validateInput(pubAddress)) {
- if (getParentFragment() == null) {
- ((DialogFragmentPublishAddressListener) getActivity()).setPublishAddress(MeshParserUtils.toByteArray(pubAddress));
- } else {
- ((DialogFragmentPublishAddressListener) getParentFragment()).setPublishAddress(MeshParserUtils.toByteArray(pubAddress));
- }
- dismiss();
- }
- });
-
- return alertDialog;
- }
-
- private boolean validateInput(final String input) {
-
- try {
-
- if(input.length() % 4 != 0 || !input.matches(Utils.HEX_PATTERN)) {
- unicastAddressInputLayout.setError(getString(R.string.invalid_address_value));
- return false;
- }
- } catch (IllegalArgumentException ex) {
- unicastAddressInputLayout.setError(ex.getMessage());
- return false;
- }
-
- return true;
- }
-
- public interface DialogFragmentPublishAddressListener {
-
- void setPublishAddress(final byte[] publishAddress);
-
- }
-}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentResetNetwork.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentResetNetwork.java
index 11e91caf6..fc29e2f7c 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentResetNetwork.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentResetNetwork.java
@@ -24,8 +24,8 @@
import android.app.Dialog;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v7.app.AlertDialog;
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AlertDialog;
import no.nordicsemi.android.nrfmeshprovisioner.R;
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentSelectOOBType.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentSelectOOBType.java
index 28ce8d7f6..5f7992cab 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentSelectOOBType.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentSelectOOBType.java
@@ -22,12 +22,14 @@
package no.nordicsemi.android.nrfmeshprovisioner.dialog;
-import android.app.AlertDialog;
+import androidx.appcompat.app.AlertDialog;
+
+import android.annotation.SuppressLint;
import android.app.Dialog;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.v4.app.DialogFragment;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.DialogFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.AdapterView;
@@ -114,7 +116,7 @@ public void onCreate(@Nullable final Bundle savedInstanceState) {
@NonNull
@Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
- final View rootView = LayoutInflater.from(getContext()).inflate(R.layout.dialog_fragment_select_oob_type, null);
+ @SuppressLint("InflateParams") final View rootView = LayoutInflater.from(getContext()).inflate(R.layout.dialog_fragment_select_oob_type, null);
//Bind ui
ButterKnife.bind(this, rootView);
@@ -162,7 +164,7 @@ public void onNothingSelected(final AdapterView> parent) {
}
});
- final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getContext()).
+ final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(requireContext()).
setView(rootView).
setIcon(R.drawable.ic_oob_lock_outline).
setTitle(R.string.title_select_oob).
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentTransactionStatus.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentTransactionStatus.java
index a25a2085f..57b40d8e5 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentTransactionStatus.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentTransactionStatus.java
@@ -24,8 +24,8 @@
import android.app.Dialog;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v7.app.AlertDialog;
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AlertDialog;
import no.nordicsemi.android.nrfmeshprovisioner.R;
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentUnicastAddress.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentUnicastAddress.java
index 63d6099dc..fbc2787de 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentUnicastAddress.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentUnicastAddress.java
@@ -22,24 +22,25 @@
package no.nordicsemi.android.nrfmeshprovisioner.dialog;
-import android.app.AlertDialog;
+import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.design.widget.TextInputEditText;
-import android.support.design.widget.TextInputLayout;
-import android.support.v4.app.DialogFragment;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.text.method.KeyListener;
import android.view.LayoutInflater;
import android.view.View;
+import android.widget.TextView;
-import java.util.Locale;
+import com.google.android.material.textfield.TextInputEditText;
+import com.google.android.material.textfield.TextInputLayout;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.DialogFragment;
import butterknife.BindView;
import butterknife.ButterKnife;
import no.nordicsemi.android.meshprovisioner.utils.MeshAddress;
@@ -51,6 +52,8 @@
public class DialogFragmentUnicastAddress extends DialogFragment {
private static final String UNICAST_ADDRESS = "UNICAST_ADDRESS";
+ private static final String ELEMENT_COUNT = "ELEMENT_COUNT";
+
//UI Bindings
@BindView(R.id.text_input_layout)
TextInputLayout unicastAddressInputLayout;
@@ -58,11 +61,13 @@ public class DialogFragmentUnicastAddress extends DialogFragment {
TextInputEditText unicastAddressInput;
private int mUnicastAddress;
+ private int mElementCount;
- public static DialogFragmentUnicastAddress newInstance(final int unicastAddress) {
+ public static DialogFragmentUnicastAddress newInstance(final int unicastAddress, final int elementCount) {
DialogFragmentUnicastAddress fragmentIvIndex = new DialogFragmentUnicastAddress();
final Bundle args = new Bundle();
args.putInt(UNICAST_ADDRESS, unicastAddress);
+ args.putInt(ELEMENT_COUNT, elementCount);
fragmentIvIndex.setArguments(args);
return fragmentIvIndex;
}
@@ -72,19 +77,20 @@ public void onCreate(@Nullable final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mUnicastAddress = getArguments().getInt(UNICAST_ADDRESS);
+ mElementCount = getArguments().getInt(ELEMENT_COUNT);
}
}
@NonNull
@Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
- final View rootView = LayoutInflater.from(getContext()).inflate(R.layout.dialog_fragment_address_input, null);
+ @SuppressLint("InflateParams") final View rootView = LayoutInflater.from(getContext()).inflate(R.layout.dialog_fragment_address_input, null);
//Bind ui
ButterKnife.bind(this, rootView);
-
+ final TextView summary = rootView.findViewById(R.id.summary);
final KeyListener hexKeyListener = new HexKeyListener();
- final String unicastAddress = String.format(Locale.US, "%04X", mUnicastAddress);
+ final String unicastAddress = MeshAddress.formatAddress(mUnicastAddress, false);
unicastAddressInputLayout.setHint(getString((R.string.hint_unicast_address)));
unicastAddressInput.setText(unicastAddress);
unicastAddressInput.setSelection(unicastAddress.length());
@@ -110,23 +116,36 @@ public void afterTextChanged(final Editable s) {
}
});
- final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getContext()).setView(rootView)
- .setPositiveButton(R.string.ok, null).setNegativeButton(R.string.cancel, null);
+ final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(requireContext())
+ .setIcon(R.drawable.ic_lan_black_alpha_24dp)
+ .setTitle(R.string.title_unicast_address)
+ .setView(rootView)
+ .setPositiveButton(R.string.ok, null)
+ .setNegativeButton(R.string.cancel, null)
+ .setNeutralButton(R.string.automatic, null);
- alertDialogBuilder.setIcon(R.drawable.ic_lan_black_alpha_24dp);
- alertDialogBuilder.setTitle(R.string.title_unicast_address);
- alertDialogBuilder.setMessage(R.string.dialog_summary_unicast_address);
+ summary.setText(R.string.dialog_summary_unicast_address);
final AlertDialog alertDialog = alertDialogBuilder.show();
alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(v -> {
- final String unicast = unicastAddressInput.getEditableText().toString();
- if (validateInput(unicast)) {
- if (getParentFragment() == null) {
- ((DialogFragmentUnicastAddressListener) getActivity()).setUnicastAddress(Integer.parseInt(unicast, 16));
- } else {
- ((DialogFragmentUnicastAddressListener) getParentFragment()).setUnicastAddress(Integer.parseInt(unicast, 16));
+ final String unicast = unicastAddressInput.getEditableText().toString().trim();
+ try {
+ if (validateInput(unicast)) {
+ if (((DialogFragmentUnicastAddressListener) requireActivity()).setUnicastAddress(Integer.parseInt(unicast, 16))) {
+ dismiss();
+ }
}
- dismiss();
+ } catch (IllegalArgumentException ex) {
+ unicastAddressInputLayout.setError(ex.getMessage());
+ }
+ });
+
+ alertDialog.getButton(DialogInterface.BUTTON_NEUTRAL).setOnClickListener(v -> {
+ try {
+ final int unicast = ((DialogFragmentUnicastAddressListener) requireActivity()).getNextUnicastAddress(mElementCount);
+ unicastAddressInput.setText(MeshAddress.formatAddress(unicast, false));
+ } catch (IllegalArgumentException ex) {
+ unicastAddressInputLayout.setError(ex.getMessage());
}
});
@@ -137,13 +156,13 @@ private boolean validateInput(final String input) {
try {
- if(input.length() % 4 != 0 || !input.matches(Utils.HEX_PATTERN)) {
+ if (input.length() % 4 != 0 || !input.matches(Utils.HEX_PATTERN)) {
unicastAddressInputLayout.setError(getString(R.string.invalid_address_value));
return false;
}
final int unicastAddress = Integer.parseInt(input, 16);
- if(!MeshAddress.isValidUnicastAddress(unicastAddress)) {
+ if (!MeshAddress.isValidUnicastAddress(unicastAddress)) {
unicastAddressInputLayout.setError("Unicast address must range from 0x0001 - 0x7FFFF");
return false;
}
@@ -156,7 +175,9 @@ private boolean validateInput(final String input) {
public interface DialogFragmentUnicastAddressListener {
- void setUnicastAddress(final int unicastAddress);
+ boolean setUnicastAddress(final int unicastAddress);
+
+ int getNextUnicastAddress(final int elementCount);
}
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/NetKeyListener.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/NetKeyListener.java
new file mode 100644
index 000000000..019a54749
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/NetKeyListener.java
@@ -0,0 +1,11 @@
+package no.nordicsemi.android.nrfmeshprovisioner.dialog;
+
+import androidx.annotation.NonNull;
+import no.nordicsemi.android.meshprovisioner.NetworkKey;
+
+public interface NetKeyListener {
+
+ void onKeyUpdated(@NonNull final NetworkKey key);
+
+ void onKeyNameUpdated(@NonNull final String nodeName);
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/AddAppKeyActivity.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/AddAppKeyActivity.java
new file mode 100644
index 000000000..671a5c23b
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/AddAppKeyActivity.java
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 2018, Nordic Semiconductor
+ * 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 no.nordicsemi.android.nrfmeshprovisioner.keys;
+
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.TextView;
+
+import com.google.android.material.snackbar.Snackbar;
+
+import javax.inject.Inject;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.Toolbar;
+import androidx.coordinatorlayout.widget.CoordinatorLayout;
+import androidx.core.content.ContextCompat;
+import androidx.lifecycle.ViewModelProvider;
+import androidx.lifecycle.ViewModelProviders;
+import androidx.recyclerview.widget.DefaultItemAnimator;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import butterknife.BindView;
+import butterknife.ButterKnife;
+import no.nordicsemi.android.meshprovisioner.ApplicationKey;
+import no.nordicsemi.android.meshprovisioner.MeshNetwork;
+import no.nordicsemi.android.meshprovisioner.NetworkKey;
+import no.nordicsemi.android.meshprovisioner.utils.MeshParserUtils;
+import no.nordicsemi.android.nrfmeshprovisioner.R;
+import no.nordicsemi.android.nrfmeshprovisioner.di.Injectable;
+import no.nordicsemi.android.nrfmeshprovisioner.keys.adapter.ManageBoundNetKeyAdapter;
+import no.nordicsemi.android.nrfmeshprovisioner.keys.dialogs.DialogFragmentEditAppKey;
+import no.nordicsemi.android.nrfmeshprovisioner.keys.dialogs.DialogFragmentKeyName;
+import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.AddAppKeyViewModel;
+
+public class AddAppKeyActivity extends AppCompatActivity implements Injectable,
+ MeshKeyListener,
+ ManageBoundNetKeyAdapter.OnItemClickListener {
+
+ private static final String APPLICATION_KEY = "APPLICATION_KEY";
+ @Inject
+ ViewModelProvider.Factory mViewModelFactory;
+
+ @BindView(R.id.container)
+ CoordinatorLayout container;
+ TextView nameView;
+ TextView keyView;
+ TextView keyIndexView;
+
+ private AddAppKeyViewModel mViewModel;
+ private ApplicationKey appKey;
+
+ @Override
+ protected void onCreate(@Nullable final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_edit_key);
+ mViewModel = ViewModelProviders.of(this, mViewModelFactory).get(AddAppKeyViewModel.class);
+ ButterKnife.bind(this);
+
+ if (savedInstanceState == null) {
+ final MeshNetwork network = mViewModel.getMeshManagerApi().getMeshNetwork();
+ if (network != null) {
+ appKey = network.createAppKey();
+ }
+ } else {
+ appKey = savedInstanceState.getParcelable(APPLICATION_KEY);
+ }
+
+ //Bind ui
+ final Toolbar toolbar = findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+ //noinspection ConstantConditions
+ getSupportActionBar().setTitle(R.string.title_add_app_key);
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+ getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_close_white_24dp);
+
+ final View containerKey = findViewById(R.id.container_key);
+ containerKey.findViewById(R.id.image).
+ setBackground(ContextCompat.getDrawable(this, R.drawable.ic_vpn_key_black_alpha_24dp));
+ ((TextView) containerKey.findViewById(R.id.title)).setText(R.string.title_app_key);
+ keyView = containerKey.findViewById(R.id.text);
+ keyView.setVisibility(View.VISIBLE);
+
+ final View containerKeyName = findViewById(R.id.container_key_name);
+ containerKeyName.findViewById(R.id.image).
+ setBackground(ContextCompat.getDrawable(this, R.drawable.ic_label_black_alpha_24dp));
+ ((TextView) containerKeyName.findViewById(R.id.title)).setText(R.string.name);
+ nameView = containerKeyName.findViewById(R.id.text);
+ nameView.setVisibility(View.VISIBLE);
+
+ final View containerKeyIndex = findViewById(R.id.container_key_index);
+ containerKeyIndex.setClickable(false);
+ containerKeyIndex.findViewById(R.id.image).
+ setBackground(ContextCompat.getDrawable(this, R.drawable.ic_index));
+ ((TextView) containerKeyIndex.findViewById(R.id.title)).setText(R.string.title_key_index);
+ keyIndexView = containerKeyIndex.findViewById(R.id.text);
+ keyIndexView.setVisibility(View.VISIBLE);
+
+ findViewById(R.id.net_key_container).setVisibility(View.VISIBLE);
+
+ final RecyclerView netKeysRecyclerView = findViewById(R.id.recycler_view_keys);
+ netKeysRecyclerView.setLayoutManager(new LinearLayoutManager(this));
+ netKeysRecyclerView.setItemAnimator(new DefaultItemAnimator());
+ final ManageBoundNetKeyAdapter adapter = new ManageBoundNetKeyAdapter(this, mViewModel.getNetworkLiveData().getNetworkKeys(), appKey);
+ adapter.setOnItemClickListener(this);
+ netKeysRecyclerView.setAdapter(adapter);
+
+ containerKey.setOnClickListener(v -> {
+ if (appKey != null) {
+ final DialogFragmentEditAppKey fragment = DialogFragmentEditAppKey.newInstance(appKey.getKeyIndex(), appKey);
+ fragment.show(getSupportFragmentManager(), null);
+ }
+ });
+
+ containerKeyName.setOnClickListener(v -> {
+ if (appKey != null) {
+ final DialogFragmentKeyName fragment = DialogFragmentKeyName.newInstance(appKey.getName());
+ fragment.show(getSupportFragmentManager(), null);
+ }
+ });
+
+ updateUi();
+ }
+
+ private void updateUi() {
+ if (appKey != null) {
+ keyView.setText(MeshParserUtils.bytesToHex(appKey.getKey(), false));
+ nameView.setText(appKey.getName());
+ keyIndexView.setText(String.valueOf(appKey.getKeyIndex()));
+ }
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(final Menu menu) {
+ getMenuInflater().inflate(R.menu.menu_save, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(final MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ case R.id.action_save:
+ if (save()) {
+ onBackPressed();
+ }
+ return true;
+ }
+ return false;
+ }
+
+ private boolean save() {
+ final MeshNetwork network = mViewModel.getMeshManagerApi().getMeshNetwork();
+ if (network != null) {
+ return network.addAppKey(appKey);
+ }
+ return false;
+ }
+
+ @Override
+ protected void onSaveInstanceState(@NonNull final Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putParcelable(APPLICATION_KEY, appKey);
+ }
+
+ @Override
+ public boolean onKeyNameUpdated(@NonNull final String name) {
+ if (appKey != null) {
+ appKey.setName(name);
+ nameView.setText(name);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean onKeyUpdated(final int position, @NonNull final String key) {
+ if (appKey != null) {
+ this.appKey.setKey(MeshParserUtils.toByteArray(key));
+ keyView.setText(key);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public ApplicationKey updateBoundNetKeyIndex(final int position, @NonNull final NetworkKey networkKey) {
+ final ApplicationKey key = appKey;
+ key.setBoundNetKeyIndex(networkKey.getKeyIndex());
+ final MeshNetwork network = mViewModel.getMeshManagerApi().getMeshNetwork();
+ if (network != null) {
+ try {
+ if (network.updateAppKey(key)) {
+ appKey = key;
+ return key;
+ }
+ } catch (IllegalArgumentException ex) {
+ mViewModel.displaySnackBar(this, container, ex.getMessage(), Snackbar.LENGTH_LONG);
+ }
+ }
+ return appKey;
+ }
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/AddAppKeysActivity.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/AddAppKeysActivity.java
new file mode 100644
index 000000000..fd58454a8
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/AddAppKeysActivity.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2018, Nordic Semiconductor
+ * 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 no.nordicsemi.android.nrfmeshprovisioner.keys;
+
+import android.os.Bundle;
+import android.view.View;
+
+import com.google.android.material.snackbar.Snackbar;
+
+import java.util.List;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import no.nordicsemi.android.meshprovisioner.ApplicationKey;
+import no.nordicsemi.android.meshprovisioner.NetworkKey;
+import no.nordicsemi.android.meshprovisioner.NodeKey;
+import no.nordicsemi.android.meshprovisioner.transport.ConfigAppKeyAdd;
+import no.nordicsemi.android.meshprovisioner.transport.ConfigAppKeyDelete;
+import no.nordicsemi.android.meshprovisioner.transport.ConfigAppKeyGet;
+import no.nordicsemi.android.meshprovisioner.transport.MeshMessage;
+import no.nordicsemi.android.meshprovisioner.transport.ProvisionedMeshNode;
+import no.nordicsemi.android.nrfmeshprovisioner.R;
+import no.nordicsemi.android.nrfmeshprovisioner.di.Injectable;
+import no.nordicsemi.android.nrfmeshprovisioner.keys.adapter.AddedAppKeyAdapter;
+
+public class AddAppKeysActivity extends AddKeysActivity implements Injectable,
+ AddedAppKeyAdapter.OnItemClickListener {
+ private AddedAppKeyAdapter adapter;
+
+ @Override
+ protected void onCreate(@Nullable final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ //noinspection ConstantConditions
+ getSupportActionBar().setTitle(R.string.title_added_app_keys);
+ mEmptyView = findViewById(R.id.empty_app_keys);
+ adapter = new AddedAppKeyAdapter(this,
+ mViewModel.getNetworkLiveData().getMeshNetwork().getAppKeys(), mViewModel.getSelectedMeshNode());
+ enableAdapterClickListener(true);
+ recyclerViewKeys.setAdapter(adapter);
+ setUpObserver();
+ }
+
+ @Override
+ public void onItemClick(@NonNull final ApplicationKey appKey) {
+ if (!checkConnectivity())
+ return;
+ final MeshMessage meshMessage;
+ final String message;
+ final NetworkKey networkKey = mViewModel.getNetworkLiveData().getMeshNetwork().getNetKey(appKey.getBoundNetKeyIndex());
+ if (!mViewModel.isAppKeyAdded(appKey.getKeyIndex())) {
+ message = getString(R.string.adding_app_key);
+ meshMessage = new ConfigAppKeyAdd(networkKey, appKey);
+ } else {
+ message = getString(R.string.deleting_app_key);
+ meshMessage = new ConfigAppKeyDelete(networkKey, appKey);
+ }
+ mViewModel.displaySnackBar(this, container, message, Snackbar.LENGTH_SHORT);
+ sendMessage(meshMessage);
+ }
+
+ @Override
+ public void onRefresh() {
+ super.onRefresh();
+ final ProvisionedMeshNode node = mViewModel.getSelectedMeshNode().getValue();
+ if (node != null) {
+ for (NodeKey key : node.getAddedNetKeys()) {
+ final NetworkKey networkKey = mViewModel.getNetworkLiveData().getMeshNetwork().getNetKey(key.getIndex());
+ final ConfigAppKeyGet configAppKeyGet = new ConfigAppKeyGet(networkKey);
+ mViewModel.getMessageQueue().add(configAppKeyGet);
+ }
+ sendMessage(mViewModel.getMessageQueue().peek());
+ }
+ }
+
+ protected void setUpObserver() {
+ mViewModel.getNetworkLiveData().observe(this, networkLiveData -> {
+ if (networkLiveData != null) {
+ final List keys = networkLiveData.getAppKeys();
+ if (keys != null) {
+ mEmptyView.setVisibility(keys.isEmpty() ? View.VISIBLE : View.GONE);
+ }
+ }
+ });
+ }
+
+ @Override
+ void enableAdapterClickListener(final boolean enable) {
+ adapter.setOnItemClickListener(enable ? this : null);
+ }
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/AddKeysActivity.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/AddKeysActivity.java
new file mode 100644
index 000000000..c2c63f36d
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/AddKeysActivity.java
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) 2018, Nordic Semiconductor
+ * 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 no.nordicsemi.android.nrfmeshprovisioner.keys;
+
+import android.os.Bundle;
+import android.os.Handler;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.ProgressBar;
+
+import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton;
+import com.google.android.material.snackbar.Snackbar;
+
+import javax.inject.Inject;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.Toolbar;
+import androidx.coordinatorlayout.widget.CoordinatorLayout;
+import androidx.lifecycle.ViewModelProvider;
+import androidx.lifecycle.ViewModelProviders;
+import androidx.recyclerview.widget.DefaultItemAnimator;
+import androidx.recyclerview.widget.DividerItemDecoration;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
+import butterknife.BindView;
+import butterknife.ButterKnife;
+import no.nordicsemi.android.meshprovisioner.transport.ConfigAppKeyList;
+import no.nordicsemi.android.meshprovisioner.transport.ConfigAppKeyStatus;
+import no.nordicsemi.android.meshprovisioner.transport.ConfigNetKeyStatus;
+import no.nordicsemi.android.meshprovisioner.transport.MeshMessage;
+import no.nordicsemi.android.meshprovisioner.transport.ProvisionedMeshNode;
+import no.nordicsemi.android.nrfmeshprovisioner.R;
+import no.nordicsemi.android.nrfmeshprovisioner.di.Injectable;
+import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentError;
+import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentConfigStatus;
+import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentTransactionStatus;
+import no.nordicsemi.android.nrfmeshprovisioner.utils.Utils;
+import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.AddKeysViewModel;
+
+public abstract class AddKeysActivity extends AppCompatActivity implements Injectable, SwipeRefreshLayout.OnRefreshListener {
+
+ @Inject
+ ViewModelProvider.Factory mViewModelFactory;
+
+ @BindView(R.id.container)
+ protected CoordinatorLayout container;
+ @BindView(R.id.recycler_view_keys)
+ protected RecyclerView recyclerViewKeys;
+ @BindView(R.id.fab_add)
+ protected ExtendedFloatingActionButton fab;
+ @BindView(R.id.configuration_progress_bar)
+ protected ProgressBar mProgressbar;
+ @BindView(R.id.swipe_refresh)
+ protected SwipeRefreshLayout mSwipe;
+
+ protected Handler mHandler;
+ protected View mEmptyView;
+
+ protected AddKeysViewModel mViewModel;
+ protected boolean mIsConnected;
+
+ abstract void enableAdapterClickListener(final boolean enable);
+
+ @Override
+ protected void onCreate(@Nullable final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mViewModel = ViewModelProviders.of(this, mViewModelFactory).get(AddKeysViewModel.class);
+ setContentView(R.layout.activity_add_keys);
+ ButterKnife.bind(this);
+ mHandler = new Handler();
+ final Toolbar toolbar = findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+ //noinspection ConstantConditions
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+ mSwipe.setOnRefreshListener(this);
+ recyclerViewKeys.setLayoutManager(new LinearLayoutManager(this));
+ final DividerItemDecoration dividerItemDecoration =
+ new DividerItemDecoration(recyclerViewKeys.getContext(), DividerItemDecoration.VERTICAL);
+ recyclerViewKeys.addItemDecoration(dividerItemDecoration);
+ recyclerViewKeys.setItemAnimator(new DefaultItemAnimator());
+ fab.hide();
+
+ mViewModel.getMeshMessage().observe(this, meshMessage -> {
+ if (meshMessage instanceof ConfigNetKeyStatus) {
+ final ConfigNetKeyStatus status = (ConfigNetKeyStatus) meshMessage;
+ if (status.isSuccessful()) {
+ mViewModel.displaySnackBar(this, container, getString(R.string.operation_success), Snackbar.LENGTH_SHORT);
+ } else {
+ showDialogFragment(getString(R.string.title_netkey_status), status.getStatusCodeName());
+ }
+ } else if (meshMessage instanceof ConfigAppKeyStatus) {
+ final ConfigAppKeyStatus status = (ConfigAppKeyStatus) meshMessage;
+ if (status.isSuccessful()) {
+ mViewModel.displaySnackBar(this, container, getString(R.string.operation_success), Snackbar.LENGTH_SHORT);
+ } else {
+ showDialogFragment(getString(R.string.title_appkey_status), status.getStatusCodeName());
+ }
+ } else if (meshMessage instanceof ConfigAppKeyList) {
+ final ConfigAppKeyList status = (ConfigAppKeyList) meshMessage;
+ if (!mViewModel.getMessageQueue().isEmpty())
+ mViewModel.getMessageQueue().remove();
+ if (status.isSuccessful()) {
+ handleStatuses();
+ } else {
+ showDialogFragment(getString(R.string.title_appkey_status), status.getStatusCodeName());
+ }
+ }
+ hideProgressBar();
+ });
+
+ mViewModel.isConnectedToProxy().observe(this, isConnected -> {
+ if (isConnected != null) {
+ mIsConnected = isConnected;
+ hideProgressBar();
+ }
+ invalidateOptionsMenu();
+ });
+
+ final Boolean isConnectedToNetwork = mViewModel.isConnectedToProxy().getValue();
+ if (isConnectedToNetwork != null) {
+ mIsConnected = isConnectedToNetwork;
+ }
+ invalidateOptionsMenu();
+
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(final Menu menu) {
+ if (mIsConnected) {
+ getMenuInflater().inflate(R.menu.disconnect, menu);
+ } else {
+ getMenuInflater().inflate(R.menu.connect, menu);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(final MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ case R.id.action_connect:
+ mViewModel.navigateToScannerActivity(this, false, Utils.CONNECT_TO_NETWORK, false);
+ return true;
+ case R.id.action_disconnect:
+ mViewModel.disconnect();
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ @Override
+ public void onBackPressed() {
+ super.onBackPressed();
+ if (isFinishing()) {
+ mHandler.removeCallbacksAndMessages(null);
+ }
+ }
+
+ private void showDialogFragment(@NonNull final String title, @NonNull final String message) {
+ if (getSupportFragmentManager().findFragmentByTag(Utils.DIALOG_FRAGMENT_KEY_STATUS) == null) {
+ final DialogFragmentConfigStatus fragmentKeyStatus = DialogFragmentConfigStatus.newInstance(title, message);
+ fragmentKeyStatus.show(getSupportFragmentManager(), Utils.DIALOG_FRAGMENT_KEY_STATUS);
+ }
+ }
+
+ @SuppressWarnings("BooleanMethodIsAlwaysInverted")
+ protected final boolean checkConnectivity() {
+ if (!mIsConnected) {
+ mViewModel.displayDisconnectedSnackBar(this, container);
+ return false;
+ }
+ return true;
+ }
+
+ protected final void showProgressbar() {
+ mHandler.postDelayed(mOperationTimeout, Utils.MESSAGE_TIME_OUT);
+ disableClickableViews();
+ mProgressbar.setVisibility(View.VISIBLE);
+ }
+
+ protected final void hideProgressBar() {
+ mSwipe.setRefreshing(false);
+ enableClickableViews();
+ mProgressbar.setVisibility(View.INVISIBLE);
+ mHandler.removeCallbacks(mOperationTimeout);
+ }
+
+ private final Runnable mOperationTimeout = () -> {
+ hideProgressBar();
+ mViewModel.getMessageQueue().clear();
+ DialogFragmentTransactionStatus fragmentMessage = DialogFragmentTransactionStatus.newInstance(getString(R.string.title_transaction_failed), getString(R.string.operation_timed_out));
+ fragmentMessage.show(getSupportFragmentManager(), null);
+ };
+
+ protected void enableClickableViews() {
+ enableAdapterClickListener(true);
+ recyclerViewKeys.setEnabled(true);
+ recyclerViewKeys.setClickable(true);
+ }
+
+ protected void disableClickableViews() {
+ enableAdapterClickListener(false);
+ recyclerViewKeys.setEnabled(false);
+ recyclerViewKeys.setClickable(false);
+ }
+
+ private void handleStatuses() {
+ final MeshMessage message = mViewModel.getMessageQueue().peek();
+ if (message != null) {
+ sendMessage(message);
+ } else {
+ mViewModel.displaySnackBar(this, container, getString(R.string.operation_success), Snackbar.LENGTH_SHORT);
+ }
+ }
+
+ protected void sendMessage(final MeshMessage meshMessage) {
+ try {
+ if (!checkConnectivity())
+ return;
+ showProgressbar();
+ final ProvisionedMeshNode node = mViewModel.getSelectedMeshNode().getValue();
+ if (node != null) {
+ mViewModel.getMeshManagerApi().createMeshPdu(node.getUnicastAddress(), meshMessage);
+ }
+ } catch (IllegalArgumentException ex) {
+ hideProgressBar();
+ final DialogFragmentError message = DialogFragmentError.
+ newInstance(getString(R.string.title_error), ex.getMessage());
+ message.show(getSupportFragmentManager(), null);
+ }
+ }
+
+ @Override
+ public void onRefresh() {
+ if (!checkConnectivity()) {
+ mSwipe.setRefreshing(false);
+ }
+ }
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/AddNetKeyActivity.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/AddNetKeyActivity.java
new file mode 100644
index 000000000..5811908e9
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/AddNetKeyActivity.java
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2018, Nordic Semiconductor
+ * 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 no.nordicsemi.android.nrfmeshprovisioner.keys;
+
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.TextView;
+
+import javax.inject.Inject;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.Toolbar;
+import androidx.core.content.ContextCompat;
+import androidx.lifecycle.ViewModelProvider;
+import androidx.lifecycle.ViewModelProviders;
+import no.nordicsemi.android.meshprovisioner.MeshNetwork;
+import no.nordicsemi.android.meshprovisioner.NetworkKey;
+import no.nordicsemi.android.meshprovisioner.utils.MeshParserUtils;
+import no.nordicsemi.android.nrfmeshprovisioner.R;
+import no.nordicsemi.android.nrfmeshprovisioner.di.Injectable;
+import no.nordicsemi.android.nrfmeshprovisioner.keys.dialogs.DialogFragmentEditNetKey;
+import no.nordicsemi.android.nrfmeshprovisioner.keys.dialogs.DialogFragmentKeyName;
+import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.AddNetKeyViewModel;
+
+public class AddNetKeyActivity extends AppCompatActivity implements Injectable, MeshKeyListener {
+
+ private static final String APPLICATION_KEY = "APPLICATION_KEY";
+ @Inject
+ ViewModelProvider.Factory mViewModelFactory;
+ private TextView nameView;
+ private TextView keyView;
+ private TextView keyIndexView;
+
+ private AddNetKeyViewModel mViewModel;
+ private NetworkKey netKey;
+
+ @Override
+ protected void onCreate(@Nullable final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_edit_key);
+ mViewModel = ViewModelProviders.of(this, mViewModelFactory).get(AddNetKeyViewModel.class);
+
+ //Bind ui
+ final Toolbar toolbar = findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+ //noinspection ConstantConditions
+ getSupportActionBar().setTitle(R.string.title_add_net_key);
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+ getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_close_white_24dp);
+
+ final View containerKey = findViewById(R.id.container_key);
+ containerKey.findViewById(R.id.image).
+ setBackground(ContextCompat.getDrawable(this, R.drawable.ic_vpn_key_black_alpha_24dp));
+ ((TextView) containerKey.findViewById(R.id.title)).setText(R.string.title_net_key);
+ keyView = containerKey.findViewById(R.id.text);
+ keyView.setVisibility(View.VISIBLE);
+
+ final View containerKeyName = findViewById(R.id.container_key_name);
+ containerKeyName.findViewById(R.id.image).
+ setBackground(ContextCompat.getDrawable(this, R.drawable.ic_label_black_alpha_24dp));
+ ((TextView) containerKeyName.findViewById(R.id.title)).setText(R.string.name);
+ nameView = containerKeyName.findViewById(R.id.text);
+ nameView.setVisibility(View.VISIBLE);
+
+ final View containerKeyIndex = findViewById(R.id.container_key_index);
+ containerKeyIndex.setClickable(false);
+ containerKeyIndex.findViewById(R.id.image).
+ setBackground(ContextCompat.getDrawable(this, R.drawable.ic_index));
+ ((TextView) containerKeyIndex.findViewById(R.id.title)).setText(R.string.title_key_index);
+ keyIndexView = containerKeyIndex.findViewById(R.id.text);
+ keyIndexView.setVisibility(View.VISIBLE);
+
+ containerKey.setOnClickListener(v -> {
+ if (netKey != null) {
+ final DialogFragmentEditNetKey fragment = DialogFragmentEditNetKey.newInstance(netKey.getKeyIndex(), netKey);
+ fragment.show(getSupportFragmentManager(), null);
+ }
+ });
+
+ containerKeyName.setOnClickListener(v -> {
+ if (netKey != null) {
+ final DialogFragmentKeyName fragment = DialogFragmentKeyName.newInstance(netKey.getName());
+ fragment.show(getSupportFragmentManager(), null);
+ }
+ });
+
+ if (savedInstanceState == null) {
+ final MeshNetwork network = mViewModel.getMeshManagerApi().getMeshNetwork();
+ if (network != null) {
+ netKey = network.createNetworkKey();
+ }
+ } else {
+ netKey = savedInstanceState.getParcelable(APPLICATION_KEY);
+ }
+ updateUi();
+ }
+
+ private void updateUi(){
+ if (netKey != null) {
+ keyView.setText(MeshParserUtils.bytesToHex(netKey.getKey(), false));
+ nameView.setText(netKey.getName());
+ keyIndexView.setText(String.valueOf(netKey.getKeyIndex()));
+ }
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(final Menu menu) {
+ getMenuInflater().inflate(R.menu.menu_save, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(final MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ case R.id.action_save:
+ if (save()) {
+ onBackPressed();
+ }
+ return true;
+ }
+ return false;
+ }
+
+ private boolean save() {
+ final MeshNetwork network = mViewModel.getMeshManagerApi().getMeshNetwork();
+ if (network != null) {
+ return network.addNetKey(netKey);
+ }
+ return false;
+ }
+
+ @Override
+ protected void onSaveInstanceState(@NonNull final Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putParcelable(APPLICATION_KEY, netKey);
+ }
+
+ @Override
+ public boolean onKeyNameUpdated(@NonNull final String name) {
+ if (netKey != null) {
+ netKey.setName(name);
+ nameView.setText(name);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean onKeyUpdated(final int position, @NonNull final String key) {
+ if(netKey != null) {
+ this.netKey.setKey(MeshParserUtils.toByteArray(key));
+ keyView.setText(key);
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/AddNetKeysActivity.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/AddNetKeysActivity.java
new file mode 100644
index 000000000..f5495e5bf
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/AddNetKeysActivity.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2018, Nordic Semiconductor
+ * 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 no.nordicsemi.android.nrfmeshprovisioner.keys;
+
+import android.os.Bundle;
+
+import com.google.android.material.snackbar.Snackbar;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import no.nordicsemi.android.meshprovisioner.NetworkKey;
+import no.nordicsemi.android.meshprovisioner.transport.ConfigNetKeyAdd;
+import no.nordicsemi.android.meshprovisioner.transport.ConfigNetKeyDelete;
+import no.nordicsemi.android.meshprovisioner.transport.ConfigNetKeyGet;
+import no.nordicsemi.android.meshprovisioner.transport.MeshMessage;
+import no.nordicsemi.android.nrfmeshprovisioner.R;
+import no.nordicsemi.android.nrfmeshprovisioner.di.Injectable;
+import no.nordicsemi.android.nrfmeshprovisioner.keys.adapter.AddedNetKeyAdapter;
+
+public class AddNetKeysActivity extends AddKeysActivity implements Injectable,
+ AddedNetKeyAdapter.OnItemClickListener {
+ private AddedNetKeyAdapter adapter;
+
+ @Override
+ protected void onCreate(@Nullable final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ //noinspection ConstantConditions
+ getSupportActionBar().setTitle(R.string.title_added_net_keys);
+ mEmptyView = findViewById(R.id.empty_net_keys);
+ adapter = new AddedNetKeyAdapter(this,
+ mViewModel.getNetworkLiveData().getMeshNetwork().getNetKeys(), mViewModel.getSelectedMeshNode());
+ enableAdapterClickListener(true);
+ recyclerViewKeys.setAdapter(adapter);
+ }
+
+ @Override
+ public void onItemClick(@NonNull final NetworkKey networkKey) {
+ if (!checkConnectivity())
+ return;
+ final MeshMessage meshMessage;
+ final String message;
+ if (!mViewModel.isNetKeyAdded(networkKey.getKeyIndex())) {
+ meshMessage = new ConfigNetKeyAdd(networkKey);
+ message = getString(R.string.adding_net_key);
+ } else {
+ meshMessage = new ConfigNetKeyDelete(networkKey);
+ message = getString(R.string.deleting_net_key);
+ }
+ mViewModel.displaySnackBar(this, container, message, Snackbar.LENGTH_SHORT);
+ sendMessage(meshMessage);
+ }
+
+ @Override
+ public void onRefresh() {
+ super.onRefresh();
+ final ConfigNetKeyGet configNetKeyGet = new ConfigNetKeyGet();
+ sendMessage(configNetKeyGet);
+ }
+
+ @Override
+ void enableAdapterClickListener(final boolean enable) {
+ adapter.setOnItemClickListener(enable ? this : null);
+ }
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/AppKeysActivity.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/AppKeysActivity.java
new file mode 100644
index 000000000..f66c789b6
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/AppKeysActivity.java
@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 2018, Nordic Semiconductor
+ * 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 no.nordicsemi.android.nrfmeshprovisioner.keys;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.TextView;
+
+import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton;
+import com.google.android.material.snackbar.Snackbar;
+
+import java.util.List;
+
+import javax.inject.Inject;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.Toolbar;
+import androidx.coordinatorlayout.widget.CoordinatorLayout;
+import androidx.lifecycle.ViewModelProvider;
+import androidx.lifecycle.ViewModelProviders;
+import androidx.recyclerview.widget.DefaultItemAnimator;
+import androidx.recyclerview.widget.DividerItemDecoration;
+import androidx.recyclerview.widget.ItemTouchHelper;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import butterknife.BindView;
+import butterknife.ButterKnife;
+import no.nordicsemi.android.meshprovisioner.ApplicationKey;
+import no.nordicsemi.android.meshprovisioner.MeshNetwork;
+import no.nordicsemi.android.meshprovisioner.NodeKey;
+import no.nordicsemi.android.meshprovisioner.transport.ProvisionedMeshNode;
+import no.nordicsemi.android.nrfmeshprovisioner.R;
+import no.nordicsemi.android.nrfmeshprovisioner.di.Injectable;
+import no.nordicsemi.android.nrfmeshprovisioner.keys.adapter.ManageAppKeyAdapter;
+import no.nordicsemi.android.nrfmeshprovisioner.utils.Utils;
+import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.AppKeysViewModel;
+import no.nordicsemi.android.nrfmeshprovisioner.widgets.ItemTouchHelperAdapter;
+import no.nordicsemi.android.nrfmeshprovisioner.widgets.RemovableItemTouchHelperCallback;
+import no.nordicsemi.android.nrfmeshprovisioner.widgets.RemovableViewHolder;
+
+public class AppKeysActivity extends AppCompatActivity implements Injectable,
+ ManageAppKeyAdapter.OnItemClickListener,
+ ItemTouchHelperAdapter {
+
+ public static final String RESULT_APP_KEY = "RESULT_KEY";
+ public static final String RESULT_APP_KEY_INDEX = "RESULT_APP_KEY_INDEX";
+ public static final String RESULT_APP_KEY_LIST_SIZE = "RESULT_APP_KEY_LIST_SIZE";
+ public static final String EDIT_APP_KEY = "EDIT_APP_KEY";
+
+ @Inject
+ ViewModelProvider.Factory mViewModelFactory;
+
+ //UI Bindings
+ @BindView(R.id.empty_app_keys)
+ View mEmptyView;
+ @BindView(R.id.container)
+ CoordinatorLayout container;
+
+ private AppKeysViewModel mViewModel;
+ private ManageAppKeyAdapter mAdapter;
+
+ @Override
+ protected void onCreate(@Nullable final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_app_keys);
+ mViewModel = ViewModelProviders.of(this, mViewModelFactory).get(AppKeysViewModel.class);
+
+ //Bind ui
+ ButterKnife.bind(this);
+
+ final Toolbar toolbar = findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+ //noinspection ConstantConditions
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+
+ final ExtendedFloatingActionButton fab = findViewById(R.id.fab_add);
+ final RecyclerView appKeysRecyclerView = findViewById(R.id.recycler_view_keys);
+ appKeysRecyclerView.setLayoutManager(new LinearLayoutManager(this));
+ final DividerItemDecoration dividerItemDecoration =
+ new DividerItemDecoration(appKeysRecyclerView.getContext(), DividerItemDecoration.VERTICAL);
+ appKeysRecyclerView.addItemDecoration(dividerItemDecoration);
+ appKeysRecyclerView.setItemAnimator(new DefaultItemAnimator());
+
+ final Bundle bundle = getIntent().getExtras();
+ if (bundle != null) {
+ switch (bundle.getInt(Utils.EXTRA_DATA)) {
+ case Utils.MANAGE_APP_KEY:
+ break;
+ case Utils.ADD_APP_KEY:
+ getSupportActionBar().setTitle(R.string.title_select_app_key);
+ fab.hide();
+ mAdapter = new ManageAppKeyAdapter(this, mViewModel.getNetworkLiveData());
+ mAdapter.setOnItemClickListener(this);
+ appKeysRecyclerView.setAdapter(mAdapter);
+ setUpObserver();
+ break;
+ case Utils.BIND_APP_KEY:
+ case Utils.PUBLICATION_APP_KEY:
+ getSupportActionBar().setTitle(R.string.title_select_app_key);
+ fab.hide();
+ //Get selected mesh node
+ final ProvisionedMeshNode node = mViewModel.getSelectedMeshNode().getValue();
+ if (node != null) {
+ final List applicationKeys = node.getAddedAppKeys();
+ if (!applicationKeys.isEmpty()) {
+ mAdapter = new ManageAppKeyAdapter(this, mViewModel.getNetworkLiveData().getAppKeys(), applicationKeys);
+ mAdapter.setOnItemClickListener(this);
+ appKeysRecyclerView.setAdapter(mAdapter);
+ } else {
+ final TextView textView = mEmptyView.findViewById(R.id.rationale);
+ textView.setText(R.string.no_added_app_keys_rationale);
+ mEmptyView.setVisibility(View.VISIBLE);
+ }
+ }
+ break;
+ }
+ } else {
+ getSupportActionBar().setTitle(R.string.title_manage_app_keys);
+ final ItemTouchHelper.Callback itemTouchHelperCallback = new RemovableItemTouchHelperCallback(this);
+ final ItemTouchHelper itemTouchHelper = new ItemTouchHelper(itemTouchHelperCallback);
+ itemTouchHelper.attachToRecyclerView(appKeysRecyclerView);
+ mAdapter = new ManageAppKeyAdapter(this, mViewModel.getNetworkLiveData());
+ mAdapter.setOnItemClickListener(this);
+ appKeysRecyclerView.setAdapter(mAdapter);
+ setUpObserver();
+ }
+
+
+ fab.setOnClickListener(v -> {
+ final Intent intent = new Intent(this, AddAppKeyActivity.class);
+ startActivity(intent);
+ });
+
+ appKeysRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
+ @Override
+ public void onScrolled(@NonNull final RecyclerView recyclerView, final int dx, final int dy) {
+ super.onScrolled(recyclerView, dx, dy);
+ final LinearLayoutManager m = (LinearLayoutManager) recyclerView.getLayoutManager();
+ if (m != null) {
+ if (m.findFirstCompletelyVisibleItemPosition() == 0) {
+ fab.extend(true);
+ } else {
+ fab.shrink(true);
+ }
+ }
+ }
+ });
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(final MenuItem item) {
+ if (item.getItemId() == android.R.id.home) {
+ onBackPressed();
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void onBackPressed() {
+ final Bundle bundle = getIntent().getExtras();
+ if (bundle != null) {
+ if (bundle.getInt(Utils.EXTRA_DATA) == Utils.MANAGE_APP_KEY) {
+ Intent returnIntent = new Intent();
+ returnIntent.putExtra(RESULT_APP_KEY_LIST_SIZE, mAdapter.getItemCount());
+ setResult(Activity.RESULT_OK, returnIntent);
+ finish();
+ }
+ }
+ super.onBackPressed();
+ }
+
+ @Override
+ public void onItemClick(final int position, @NonNull final ApplicationKey appKey) {
+ final Bundle bundle = getIntent().getExtras();
+ if (bundle != null) {
+ switch (bundle.getInt(Utils.EXTRA_DATA)) {
+ case Utils.ADD_APP_KEY:
+ case Utils.BIND_APP_KEY:
+ case Utils.PUBLICATION_APP_KEY:
+ Intent returnIntent = new Intent();
+ returnIntent.putExtra(RESULT_APP_KEY_INDEX, position);
+ returnIntent.putExtra(RESULT_APP_KEY, appKey);
+ setResult(Activity.RESULT_OK, returnIntent);
+ finish();
+
+ }
+ } else {
+ final Intent intent = new Intent(this, EditAppKeyActivity.class);
+ intent.putExtra(EDIT_APP_KEY, appKey.getKeyIndex());
+ startActivity(intent);
+ }
+ }
+
+ @Override
+ public void onItemDismiss(final RemovableViewHolder viewHolder) {
+ final ApplicationKey key = (ApplicationKey) viewHolder.getSwipeableView().getTag();
+ try {
+ final MeshNetwork network = mViewModel.getNetworkLiveData().getMeshNetwork();
+ if (network.removeAppKey(key)) {
+ displaySnackBar(key);
+ // Show the empty view
+ final boolean empty = mAdapter.getItemCount() == 0;
+ if (empty) {
+ mEmptyView.setVisibility(View.VISIBLE);
+ }
+ }
+ } catch (Exception ex) {
+ mAdapter.notifyDataSetChanged();
+ mViewModel.displaySnackBar(this, container, ex.getMessage(), Snackbar.LENGTH_LONG);
+ }
+ }
+
+ @Override
+ public void onItemDismissFailed(final RemovableViewHolder viewHolder) {
+ //Do nothing
+ }
+
+ private void setUpObserver() {
+ mViewModel.getNetworkLiveData().observe(this, networkLiveData -> {
+ if (networkLiveData != null) {
+ final List keys = networkLiveData.getAppKeys();
+ if (keys != null) {
+ mEmptyView.setVisibility(keys.isEmpty() ? View.VISIBLE : View.GONE);
+ }
+ }
+ });
+ }
+
+ private void displaySnackBar(@NonNull final ApplicationKey appKey) {
+ Snackbar.make(container, getString(R.string.app_key_deleted), Snackbar.LENGTH_LONG)
+ .setAction(getString(R.string.undo), view -> {
+ mEmptyView.setVisibility(View.INVISIBLE);
+ mViewModel.getNetworkLiveData().getMeshNetwork().addAppKey(appKey);
+ })
+ .setActionTextColor(getResources().getColor(R.color.colorPrimaryDark))
+ .show();
+ }
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/EditAppKeyActivity.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/EditAppKeyActivity.java
new file mode 100644
index 000000000..3e728bb30
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/EditAppKeyActivity.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2018, Nordic Semiconductor
+ * 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 no.nordicsemi.android.nrfmeshprovisioner.keys;
+
+import android.os.Bundle;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.TextView;
+
+import com.google.android.material.snackbar.Snackbar;
+
+import javax.inject.Inject;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.Toolbar;
+import androidx.core.content.ContextCompat;
+import androidx.lifecycle.ViewModelProvider;
+import androidx.lifecycle.ViewModelProviders;
+import androidx.recyclerview.widget.DefaultItemAnimator;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import butterknife.BindView;
+import butterknife.ButterKnife;
+import no.nordicsemi.android.meshprovisioner.ApplicationKey;
+import no.nordicsemi.android.meshprovisioner.MeshNetwork;
+import no.nordicsemi.android.meshprovisioner.NetworkKey;
+import no.nordicsemi.android.meshprovisioner.utils.MeshParserUtils;
+import no.nordicsemi.android.nrfmeshprovisioner.R;
+import no.nordicsemi.android.nrfmeshprovisioner.di.Injectable;
+import no.nordicsemi.android.nrfmeshprovisioner.keys.adapter.ManageBoundNetKeyAdapter;
+import no.nordicsemi.android.nrfmeshprovisioner.keys.dialogs.DialogFragmentEditAppKey;
+import no.nordicsemi.android.nrfmeshprovisioner.keys.dialogs.DialogFragmentKeyName;
+import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.EditAppKeyViewModel;
+
+public class EditAppKeyActivity extends AppCompatActivity implements Injectable,
+ MeshKeyListener,
+ ManageBoundNetKeyAdapter.OnItemClickListener {
+
+ @Inject
+ ViewModelProvider.Factory mViewModelFactory;
+ @BindView(R.id.container)
+ View container;
+
+ private EditAppKeyViewModel mViewModel;
+ private ApplicationKey appKey;
+
+ @Override
+ protected void onCreate(@Nullable final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_edit_key);
+ mViewModel = ViewModelProviders.of(this, mViewModelFactory).get(EditAppKeyViewModel.class);
+ ButterKnife.bind(this);
+ //noinspection ConstantConditions
+ final int index = getIntent().getExtras().getInt(AppKeysActivity.EDIT_APP_KEY);
+ appKey = mViewModel.getNetworkLiveData().getMeshNetwork().getAppKey(index);
+
+ //Bind ui
+ final Toolbar toolbar = findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+ //noinspection ConstantConditions
+ getSupportActionBar().setTitle(R.string.title_edit_app_key);
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+
+ final View containerKey = findViewById(R.id.container_key);
+ containerKey.findViewById(R.id.image).
+ setBackground(ContextCompat.getDrawable(this, R.drawable.ic_lock_open_black_alpha_24dp));
+ ((TextView) containerKey.findViewById(R.id.title)).setText(R.string.title_app_key);
+ final TextView keyView = containerKey.findViewById(R.id.text);
+ keyView.setVisibility(View.VISIBLE);
+
+ final View containerKeyName = findViewById(R.id.container_key_name);
+ containerKeyName.findViewById(R.id.image).
+ setBackground(ContextCompat.getDrawable(this, R.drawable.ic_label_black_alpha_24dp));
+ ((TextView) containerKeyName.findViewById(R.id.title)).setText(R.string.name);
+ final TextView name = containerKeyName.findViewById(R.id.text);
+ name.setVisibility(View.VISIBLE);
+
+ final View containerKeyIndex = findViewById(R.id.container_key_index);
+ containerKeyIndex.setClickable(false);
+ containerKeyIndex.findViewById(R.id.image).
+ setBackground(ContextCompat.getDrawable(this, R.drawable.ic_index));
+ ((TextView) containerKeyIndex.findViewById(R.id.title)).setText(R.string.title_key_index);
+ final TextView keyIndexView = containerKeyIndex.findViewById(R.id.text);
+ keyIndexView.setVisibility(View.VISIBLE);
+
+ findViewById(R.id.net_key_container).setVisibility(View.VISIBLE);
+ final RecyclerView netKeysRecyclerView = findViewById(R.id.recycler_view_keys);
+ netKeysRecyclerView.setLayoutManager(new LinearLayoutManager(this));
+ netKeysRecyclerView.setItemAnimator(new DefaultItemAnimator());
+ final ManageBoundNetKeyAdapter mAdapter = new ManageBoundNetKeyAdapter(this, mViewModel.getNetworkLiveData().getNetworkKeys(), appKey);
+ mAdapter.setOnItemClickListener(this);
+ netKeysRecyclerView.setAdapter(mAdapter);
+
+ containerKey.setOnClickListener(v -> {
+ if (appKey != null) {
+ final DialogFragmentEditAppKey fragment = DialogFragmentEditAppKey.newInstance(appKey.getKeyIndex(), appKey);
+ fragment.show(getSupportFragmentManager(), null);
+ }
+ });
+
+ containerKeyName.setOnClickListener(v -> {
+ if (appKey != null) {
+ final DialogFragmentKeyName fragment = DialogFragmentKeyName.newInstance(appKey.getName());
+ fragment.show(getSupportFragmentManager(), null);
+ }
+ });
+
+ mViewModel.getNetworkLiveData().observe(this, meshNetworkLiveData -> {
+ if (appKey != null) {
+ this.appKey = meshNetworkLiveData.getMeshNetwork().getAppKey(appKey.getKeyIndex());
+ keyView.setText(MeshParserUtils.bytesToHex(appKey.getKey(), false));
+ name.setText(appKey.getName());
+ keyIndexView.setText(String.valueOf(appKey.getKeyIndex()));
+ }
+ });
+
+ if (savedInstanceState == null) {
+ keyView.setText(MeshParserUtils.bytesToHex(appKey.getKey(), false));
+ name.setText(appKey.getName());
+ }
+ keyIndexView.setText(String.valueOf(appKey.getKeyIndex()));
+
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(final MenuItem item) {
+ if (item.getItemId() == android.R.id.home) {
+ onBackPressed();
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean onKeyNameUpdated(@NonNull final String name) {
+ if (appKey != null) {
+ final MeshNetwork network = mViewModel.getMeshManagerApi().getMeshNetwork();
+ if (network != null) {
+ appKey.setName(name);
+ return network.updateAppKey(appKey);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean onKeyUpdated(final int position, @NonNull final String key) {
+ final MeshNetwork network = mViewModel.getMeshManagerApi().getMeshNetwork();
+ if (network != null) {
+ return network.updateAppKey(appKey, key);
+ }
+ return false;
+ }
+
+ @Override
+ public ApplicationKey updateBoundNetKeyIndex(final int position, @NonNull final NetworkKey networkKey) {
+ try {
+ final ApplicationKey key = appKey.clone();
+ key.setBoundNetKeyIndex(networkKey.getKeyIndex());
+ final MeshNetwork network = mViewModel.getMeshManagerApi().getMeshNetwork();
+ if (network != null) {
+ try {
+ if (network.updateAppKey(key)) {
+ appKey = key;
+ return key;
+ }
+ } catch (IllegalArgumentException ex) {
+ displaySnackBar(ex.getMessage());
+ }
+ }
+ } catch (CloneNotSupportedException e) {
+ e.printStackTrace();
+ }
+ return appKey;
+ }
+
+ private void displaySnackBar(final String message) {
+ Snackbar.make(container, message, Snackbar.LENGTH_LONG)
+ .show();
+ }
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/EditNetKeyActivity.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/EditNetKeyActivity.java
new file mode 100644
index 000000000..b80091325
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/EditNetKeyActivity.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2018, Nordic Semiconductor
+ * 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 no.nordicsemi.android.nrfmeshprovisioner.keys;
+
+import android.os.Bundle;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.TextView;
+
+import javax.inject.Inject;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.Toolbar;
+import androidx.core.content.ContextCompat;
+import androidx.lifecycle.ViewModelProvider;
+import androidx.lifecycle.ViewModelProviders;
+import no.nordicsemi.android.meshprovisioner.MeshNetwork;
+import no.nordicsemi.android.meshprovisioner.NetworkKey;
+import no.nordicsemi.android.meshprovisioner.utils.MeshParserUtils;
+import no.nordicsemi.android.nrfmeshprovisioner.R;
+import no.nordicsemi.android.nrfmeshprovisioner.di.Injectable;
+import no.nordicsemi.android.nrfmeshprovisioner.keys.dialogs.DialogFragmentEditNetKey;
+import no.nordicsemi.android.nrfmeshprovisioner.keys.dialogs.DialogFragmentKeyName;
+import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.EditNetKeyViewModel;
+
+public class EditNetKeyActivity extends AppCompatActivity implements Injectable, MeshKeyListener {
+
+ @Inject
+ ViewModelProvider.Factory mViewModelFactory;
+
+ private EditNetKeyViewModel mViewModel;
+ private NetworkKey networkKey;
+
+ @Override
+ protected void onCreate(@Nullable final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_edit_key);
+ mViewModel = ViewModelProviders.of(this, mViewModelFactory).get(EditNetKeyViewModel.class);
+
+ //noinspection ConstantConditions
+ final int index = getIntent().getExtras().getInt(NetKeysActivity.EDIT_NET_KEY);
+ networkKey = mViewModel.getNetworkLiveData().getMeshNetwork().getNetKey(index);
+
+ //Bind ui
+ final Toolbar toolbar = findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+ //noinspection ConstantConditions
+ getSupportActionBar().setTitle(R.string.title_edit_net_key);
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+
+ final View containerKey = findViewById(R.id.container_key);
+ containerKey.findViewById(R.id.image).
+ setBackground(ContextCompat.getDrawable(this, R.drawable.ic_lock_open_black_alpha_24dp));
+ ((TextView) containerKey.findViewById(R.id.title)).setText(R.string.title_net_key);
+ final TextView keyView = containerKey.findViewById(R.id.text);
+ keyView.setVisibility(View.VISIBLE);
+
+ final View containerKeyName = findViewById(R.id.container_key_name);
+ containerKeyName.findViewById(R.id.image).
+ setBackground(ContextCompat.getDrawable(this, R.drawable.ic_label_black_alpha_24dp));
+ ((TextView) containerKeyName.findViewById(R.id.title)).setText(R.string.name);
+ final TextView name = containerKeyName.findViewById(R.id.text);
+ name.setVisibility(View.VISIBLE);
+
+ final View containerKeyIndex = findViewById(R.id.container_key_index);
+ containerKeyIndex.setClickable(false);
+ containerKeyIndex.findViewById(R.id.image).
+ setBackground(ContextCompat.getDrawable(this, R.drawable.ic_index));
+ ((TextView) containerKeyIndex.findViewById(R.id.title)).setText(R.string.title_key_index);
+ final TextView keyIndexView = containerKeyIndex.findViewById(R.id.text);
+ keyIndexView.setVisibility(View.VISIBLE);
+
+ containerKey.setOnClickListener(v -> {
+ if (networkKey != null) {
+ final DialogFragmentEditNetKey fragment = DialogFragmentEditNetKey.newInstance(networkKey.getKeyIndex(), networkKey);
+ fragment.show(getSupportFragmentManager(), null);
+ }
+ });
+
+ containerKeyName.setOnClickListener(v -> {
+ if (networkKey != null) {
+ final DialogFragmentKeyName fragment = DialogFragmentKeyName.newInstance(networkKey.getName());
+ fragment.show(getSupportFragmentManager(), null);
+ }
+ });
+
+ mViewModel.getNetworkLiveData().observe(this, meshNetworkLiveData -> {
+ if (networkKey != null) {
+ this.networkKey = meshNetworkLiveData.getMeshNetwork().getNetKey(networkKey.getKeyIndex());
+ keyView.setText(MeshParserUtils.bytesToHex(networkKey.getKey(), false));
+ name.setText(networkKey.getName());
+ keyIndexView.setText(String.valueOf(networkKey.getKeyIndex()));
+ }
+ });
+
+ if (savedInstanceState == null) {
+ keyView.setText(MeshParserUtils.bytesToHex(networkKey.getKey(), false));
+ name.setText(networkKey.getName());
+ }
+ keyIndexView.setText(String.valueOf(networkKey.getKeyIndex()));
+
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(final MenuItem item) {
+ if (item.getItemId() == android.R.id.home) {
+ onBackPressed();
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean onKeyNameUpdated(@NonNull final String name) {
+ if (networkKey != null) {
+ final MeshNetwork network = mViewModel.getMeshManagerApi().getMeshNetwork();
+ if (network != null) {
+ return network.updateNetKey(networkKey, name);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean onKeyUpdated(final int position, @NonNull final String key) {
+ final MeshNetwork network = mViewModel.getMeshManagerApi().getMeshNetwork();
+ if (network != null) {
+ return network.updateNetKey(networkKey, key);
+ }
+ return false;
+ }
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/MeshKeyListener.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/MeshKeyListener.java
new file mode 100644
index 000000000..0011e5259
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/MeshKeyListener.java
@@ -0,0 +1,23 @@
+package no.nordicsemi.android.nrfmeshprovisioner.keys;
+
+import androidx.annotation.NonNull;
+
+public interface MeshKeyListener {
+
+ /**
+ * Invoked when the name of the key has been changed
+ *
+ * @param name Name
+ * @return true if the name was set or false otherwise
+ */
+ boolean onKeyNameUpdated(@NonNull final String name);
+
+ /**
+ * Invoked when the name of the key has been changed
+ *
+ * @param position position of the key in the list
+ * @param key Updated key
+ * @return true if the key was updated or false otherwise
+ */
+ boolean onKeyUpdated(final int position, @NonNull final String key);
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/NetKeysActivity.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/NetKeysActivity.java
new file mode 100644
index 000000000..58b164b1e
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/NetKeysActivity.java
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2018, Nordic Semiconductor
+ * 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 no.nordicsemi.android.nrfmeshprovisioner.keys;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.ScrollView;
+import android.widget.TextView;
+
+import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton;
+import com.google.android.material.snackbar.Snackbar;
+
+import javax.inject.Inject;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.Toolbar;
+import androidx.cardview.widget.CardView;
+import androidx.coordinatorlayout.widget.CoordinatorLayout;
+import androidx.core.content.ContextCompat;
+import androidx.lifecycle.ViewModelProvider;
+import androidx.lifecycle.ViewModelProviders;
+import androidx.recyclerview.widget.DefaultItemAnimator;
+import androidx.recyclerview.widget.ItemTouchHelper;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import butterknife.BindView;
+import butterknife.ButterKnife;
+import no.nordicsemi.android.meshprovisioner.MeshNetwork;
+import no.nordicsemi.android.meshprovisioner.NetworkKey;
+import no.nordicsemi.android.meshprovisioner.utils.MeshParserUtils;
+import no.nordicsemi.android.nrfmeshprovisioner.R;
+import no.nordicsemi.android.nrfmeshprovisioner.di.Injectable;
+import no.nordicsemi.android.nrfmeshprovisioner.keys.adapter.ManageNetKeyAdapter;
+import no.nordicsemi.android.nrfmeshprovisioner.utils.Utils;
+import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.NetKeysViewModel;
+import no.nordicsemi.android.nrfmeshprovisioner.widgets.ItemTouchHelperAdapter;
+import no.nordicsemi.android.nrfmeshprovisioner.widgets.RemovableItemTouchHelperCallback;
+import no.nordicsemi.android.nrfmeshprovisioner.widgets.RemovableViewHolder;
+
+public class NetKeysActivity extends AppCompatActivity implements Injectable,
+ ManageNetKeyAdapter.OnItemClickListener,
+ ItemTouchHelperAdapter {
+
+ public static final String EDIT_NET_KEY = "EDIT_NET_KEY";
+
+ @Inject
+ ViewModelProvider.Factory mViewModelFactory;
+
+ //UI Bindings
+ @BindView(R.id.container)
+ CoordinatorLayout container;
+ @BindView(R.id.scroll_container)
+ ScrollView scrollView;
+ @BindView(R.id.sub_net_key_card)
+ CardView mSubNetKeyCard;
+ @BindView(R.id.recycler_view_keys)
+ RecyclerView netKeysRecyclerView;
+ @BindView(R.id.fab_add)
+ ExtendedFloatingActionButton fab;
+ @BindView(R.id.container_primary_net_key)
+ View containerKey;
+ @BindView(R.id.div3)
+ View divider;
+ @BindView(R.id.delete_hint)
+ View deleteHint;
+
+ private NetKeysViewModel mViewModel;
+ private ManageNetKeyAdapter mAdapter;
+
+ @Override
+ protected void onCreate(@Nullable final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_net_keys);
+ mViewModel = ViewModelProviders.of(this, mViewModelFactory).get(NetKeysViewModel.class);
+
+ //Bind ui
+ ButterKnife.bind(this);
+
+ final Toolbar toolbar = findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+ //noinspection ConstantConditions
+ getSupportActionBar().setTitle(R.string.title_manage_net_keys);
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+
+ containerKey.findViewById(R.id.image).
+ setBackground(ContextCompat.getDrawable(this, R.drawable.ic_vpn_key_black_alpha_24dp));
+ final TextView keyTitle = containerKey.findViewById(R.id.title);
+ final TextView keyView = containerKey.findViewById(R.id.text);
+ keyView.setVisibility(View.VISIBLE);
+
+ netKeysRecyclerView.setLayoutManager(new LinearLayoutManager(this));
+ netKeysRecyclerView.setItemAnimator(new DefaultItemAnimator());
+
+ final ItemTouchHelper.Callback itemTouchHelperCallback = new RemovableItemTouchHelperCallback(this);
+ final ItemTouchHelper itemTouchHelper = new ItemTouchHelper(itemTouchHelperCallback);
+ mAdapter = new ManageNetKeyAdapter(this, mViewModel.getNetworkLiveData());
+ mAdapter.setOnItemClickListener(this);
+ netKeysRecyclerView.setAdapter(mAdapter);
+
+ mViewModel.getNetworkLiveData().observe(this, meshNetworkLiveData -> {
+ final MeshNetwork network = meshNetworkLiveData.getMeshNetwork();
+ if (network != null) {
+ final NetworkKey networkKey = network.getPrimaryNetworkKey();
+ if (networkKey != null) {
+ keyTitle.setText(networkKey.getName());
+ keyView.setText(MeshParserUtils.bytesToHex(networkKey.getKey(), false));
+
+ if (network.getNetKeys().size() > 1) {
+ mSubNetKeyCard.setVisibility(View.VISIBLE);
+ } else {
+ mSubNetKeyCard.setVisibility(View.GONE);
+ }
+ }
+ }
+ });
+
+ final Bundle bundle = getIntent().getExtras();
+ if (bundle != null) {
+ switch (bundle.getInt(Utils.EXTRA_DATA)) {
+ case Utils.MANAGE_NET_KEY:
+ setUpClickListeners();
+ itemTouchHelper.attachToRecyclerView(netKeysRecyclerView);
+ break;
+ case Utils.ADD_NET_KEY:
+ getSupportActionBar().setTitle(R.string.title_select_net_key);
+ divider.setVisibility(View.GONE);
+ deleteHint.setVisibility(View.GONE);
+ fab.hide();
+ mAdapter = new ManageNetKeyAdapter(this, mViewModel.getNetworkLiveData());
+ mAdapter.setOnItemClickListener(this);
+ netKeysRecyclerView.setAdapter(mAdapter);
+ break;
+ }
+
+ }
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(final MenuItem item) {
+ if (item.getItemId() == android.R.id.home) {
+ onBackPressed();
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void onItemClick(final int position, @NonNull final NetworkKey networkKey) {
+ final Intent intent = new Intent(this, EditNetKeyActivity.class);
+ intent.putExtra(EDIT_NET_KEY, networkKey.getKeyIndex());
+ startActivity(intent);
+ }
+
+ @Override
+ public void onItemDismiss(final RemovableViewHolder viewHolder) {
+ final NetworkKey key = (NetworkKey) viewHolder.getSwipeableView().getTag();
+ try {
+ if (removeNetKey(key)) {
+ displaySnackBar(key);
+ }
+ } catch (Exception ex) {
+ mAdapter.notifyDataSetChanged();
+ mViewModel.displaySnackBar(this, container, ex.getMessage(), Snackbar.LENGTH_LONG);
+ }
+ }
+
+ @Override
+ public void onItemDismissFailed(final RemovableViewHolder viewHolder) {
+
+ }
+
+ private void displaySnackBar(@NonNull final NetworkKey networkKey) {
+ Snackbar.make(container, getString(R.string.net_key_deleted), Snackbar.LENGTH_LONG)
+ .setAction(getString(R.string.undo), view -> addNetKey(networkKey))
+ .setActionTextColor(getResources().getColor(R.color.colorPrimaryDark))
+ .show();
+ }
+
+ @SuppressWarnings("UnusedReturnValue")
+ private boolean addNetKey(@NonNull final NetworkKey networkKey) {
+ final MeshNetwork network = mViewModel.getMeshManagerApi().getMeshNetwork();
+ if (network != null) {
+ return network.addNetKey(networkKey);
+ }
+ return false;
+ }
+
+ private boolean removeNetKey(@NonNull final NetworkKey networkKey) {
+ final MeshNetwork network = mViewModel.getMeshManagerApi().getMeshNetwork();
+ if (network != null) {
+ return network.removeNetKey(networkKey);
+ }
+ return false;
+ }
+
+ private void setUpClickListeners() {
+ containerKey.setOnClickListener(v -> {
+ final Intent intent = new Intent(this, EditNetKeyActivity.class);
+ intent.putExtra(EDIT_NET_KEY, 0);
+ startActivity(intent);
+ });
+
+ fab.setOnClickListener(v -> {
+ final Intent intent = new Intent(this, AddNetKeyActivity.class);
+ startActivity(intent);
+ });
+
+ scrollView.getViewTreeObserver().addOnScrollChangedListener(() -> {
+ if (scrollView.getScrollY() == 0) {
+ fab.extend(true);
+ } else {
+ fab.shrink(true);
+ }
+ });
+ }
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/AddedAppKeyAdapter.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/adapter/AddedAppKeyAdapter.java
similarity index 64%
rename from Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/AddedAppKeyAdapter.java
rename to Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/adapter/AddedAppKeyAdapter.java
index 8d570bde4..c16e04025 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/AddedAppKeyAdapter.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/adapter/AddedAppKeyAdapter.java
@@ -20,27 +20,29 @@
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package no.nordicsemi.android.nrfmeshprovisioner.adapter;
+package no.nordicsemi.android.nrfmeshprovisioner.keys.adapter;
-import android.arch.lifecycle.LiveData;
import android.content.Context;
-import android.support.annotation.NonNull;
-import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.CheckBox;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import androidx.annotation.NonNull;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.lifecycle.LiveData;
+import androidx.recyclerview.widget.RecyclerView;
import butterknife.BindView;
import butterknife.ButterKnife;
-import no.nordicsemi.android.meshprovisioner.transport.ApplicationKey;
+import no.nordicsemi.android.meshprovisioner.ApplicationKey;
+import no.nordicsemi.android.meshprovisioner.NodeKey;
import no.nordicsemi.android.meshprovisioner.transport.ProvisionedMeshNode;
import no.nordicsemi.android.meshprovisioner.utils.MeshParserUtils;
-import no.nordicsemi.android.nrfmeshprovisioner.NodeConfigurationActivity;
import no.nordicsemi.android.nrfmeshprovisioner.R;
import no.nordicsemi.android.nrfmeshprovisioner.utils.Utils;
import no.nordicsemi.android.nrfmeshprovisioner.widgets.RemovableViewHolder;
@@ -48,18 +50,28 @@
public class AddedAppKeyAdapter extends RecyclerView.Adapter {
private final List appKeys = new ArrayList<>();
+ private final List addedAppKeys = new ArrayList<>();
private final Context mContext;
private OnItemClickListener mOnItemClickListener;
- public AddedAppKeyAdapter(final NodeConfigurationActivity activity, final LiveData meshNodeLiveData) {
- this.mContext = activity.getApplicationContext();
- meshNodeLiveData.observe(activity, meshNode -> {
- if (meshNode != null) {
- appKeys.clear();
- appKeys.addAll(meshNode.getAddedApplicationKeys().values());
- Collections.sort(appKeys, Utils.appKeyComparator);
- notifyDataSetChanged();
+ public AddedAppKeyAdapter(@NonNull final Context context,
+ @NonNull final List appKeys,
+ @NonNull final LiveData meshNodeLiveData) {
+ this.mContext = context;
+ this.appKeys.clear();
+ this.appKeys.addAll(appKeys);
+ Collections.sort(this.appKeys, Utils.appKeyComparator);
+ meshNodeLiveData.observe((LifecycleOwner) context, meshNode -> {
+ addedAppKeys.clear();
+ for (NodeKey nodeKey : meshNode.getAddedAppKeys()) {
+ for (ApplicationKey applicationKey : appKeys) {
+ if (nodeKey.getIndex() == applicationKey.getKeyIndex()) {
+ addedAppKeys.add(applicationKey);
+ }
+ }
}
+ Collections.sort(addedAppKeys, Utils.appKeyComparator);
+ notifyDataSetChanged();
});
}
@@ -70,17 +82,20 @@ public void setOnItemClickListener(final AddedAppKeyAdapter.OnItemClickListener
@NonNull
@Override
public AddedAppKeyAdapter.ViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int viewType) {
- final View layoutView = LayoutInflater.from(mContext).inflate(R.layout.app_key_item, parent, false);
+ final View layoutView = LayoutInflater.from(mContext).inflate(R.layout.row_item_key, parent, false);
return new AddedAppKeyAdapter.ViewHolder(layoutView);
}
@Override
public void onBindViewHolder(@NonNull final AddedAppKeyAdapter.ViewHolder holder, final int position) {
- if (appKeys.size() > 0) {
- final ApplicationKey key = appKeys.get(position);
- holder.appKeyId.setText(mContext.getString(R.string.app_key_item, key.getKeyIndex()));
- final String appKey = MeshParserUtils.bytesToHex(key.getKey(), false);
- holder.appKey.setText(appKey.toUpperCase());
+ final ApplicationKey key = appKeys.get(position);
+ holder.keyName.setText(key.getName());
+ final String appKey = MeshParserUtils.bytesToHex(key.getKey(), false);
+ holder.key.setText(appKey.toUpperCase());
+ if (addedAppKeys.contains(key)) {
+ holder.check.setChecked(true);
+ } else {
+ holder.check.setChecked(false);
}
}
@@ -100,20 +115,22 @@ public boolean isEmpty() {
@FunctionalInterface
public interface OnItemClickListener {
- void onItemClick(final ApplicationKey appKey);
+ void onItemClick(@NonNull final ApplicationKey appKey);
}
final class ViewHolder extends RemovableViewHolder {
- @BindView(R.id.app_key_id)
- TextView appKeyId;
- @BindView(R.id.app_key)
- TextView appKey;
+ @BindView(R.id.title)
+ TextView keyName;
+ @BindView(R.id.subtitle)
+ TextView key;
+ @BindView(R.id.check)
+ CheckBox check;
private ViewHolder(final View view) {
super(view);
ButterKnife.bind(this, view);
- view.findViewById(R.id.removable).setOnClickListener(v -> {
+ check.setOnClickListener(v -> {
if (mOnItemClickListener != null) {
final ApplicationKey key = appKeys.get(getAdapterPosition());
mOnItemClickListener.onItemClick(key);
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/adapter/AddedNetKeyAdapter.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/adapter/AddedNetKeyAdapter.java
new file mode 100644
index 000000000..d47abb50b
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/adapter/AddedNetKeyAdapter.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2018, Nordic Semiconductor
+ * 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 no.nordicsemi.android.nrfmeshprovisioner.keys.adapter;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.CheckBox;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import androidx.annotation.NonNull;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.lifecycle.LiveData;
+import androidx.recyclerview.widget.RecyclerView;
+import butterknife.BindView;
+import butterknife.ButterKnife;
+import no.nordicsemi.android.meshprovisioner.NetworkKey;
+import no.nordicsemi.android.meshprovisioner.NodeKey;
+import no.nordicsemi.android.meshprovisioner.transport.ProvisionedMeshNode;
+import no.nordicsemi.android.meshprovisioner.utils.MeshParserUtils;
+import no.nordicsemi.android.nrfmeshprovisioner.R;
+import no.nordicsemi.android.nrfmeshprovisioner.utils.Utils;
+import no.nordicsemi.android.nrfmeshprovisioner.widgets.RemovableViewHolder;
+
+public class AddedNetKeyAdapter extends RecyclerView.Adapter {
+
+ private final List netKeys = new ArrayList<>();
+ private final List addedNetKeys = new ArrayList<>();
+ private final Context mContext;
+ private OnItemClickListener mOnItemClickListener;
+
+ public AddedNetKeyAdapter(@NonNull final Context context,
+ @NonNull final List netKeys,
+ @NonNull final LiveData meshNodeLiveData) {
+ this.mContext = context;
+ this.netKeys.addAll(netKeys);
+ Collections.sort(this.netKeys, Utils.netKeyComparator);
+ meshNodeLiveData.observe((LifecycleOwner) context, meshNode -> {
+ addedNetKeys.clear();
+ for (NodeKey nodeKey : meshNode.getAddedNetKeys()) {
+ for (NetworkKey networkKey : netKeys) {
+ if (nodeKey.getIndex() == networkKey.getKeyIndex()) {
+ addedNetKeys.add(networkKey);
+ }
+ }
+ }
+ Collections.sort(addedNetKeys, Utils.netKeyComparator);
+ notifyDataSetChanged();
+ });
+ }
+
+ public void setOnItemClickListener(final AddedNetKeyAdapter.OnItemClickListener listener) {
+ mOnItemClickListener = listener;
+ }
+
+ @NonNull
+ @Override
+ public AddedNetKeyAdapter.ViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int viewType) {
+ final View layoutView = LayoutInflater.from(mContext).inflate(R.layout.row_item_key, parent, false);
+ return new AddedNetKeyAdapter.ViewHolder(layoutView);
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull final AddedNetKeyAdapter.ViewHolder holder, final int position) {
+ final NetworkKey key = netKeys.get(position);
+ holder.keyName.setText(key.getName());
+ final String appKey = MeshParserUtils.bytesToHex(key.getKey(), false);
+ holder.key.setText(appKey.toUpperCase());
+ if (addedNetKeys.contains(key)) {
+ holder.check.setChecked(true);
+ } else {
+ holder.check.setChecked(false);
+ }
+ }
+
+ @Override
+ public long getItemId(final int position) {
+ return position;
+ }
+
+ @Override
+ public int getItemCount() {
+ return netKeys.size();
+ }
+
+ public boolean isEmpty() {
+ return getItemCount() == 0;
+ }
+
+ @FunctionalInterface
+ public interface OnItemClickListener {
+ void onItemClick(final NetworkKey appKey);
+ }
+
+ final class ViewHolder extends RemovableViewHolder {
+
+ @BindView(R.id.title)
+ TextView keyName;
+ @BindView(R.id.subtitle)
+ TextView key;
+ @BindView(R.id.check)
+ CheckBox check;
+
+ private ViewHolder(final View view) {
+ super(view);
+ ButterKnife.bind(this, view);
+ check.setOnClickListener(v -> {
+ if (mOnItemClickListener != null) {
+ check.setChecked(!check.isChecked());
+ final NetworkKey key = netKeys.get(getAdapterPosition());
+ mOnItemClickListener.onItemClick(key);
+ }
+ });
+ }
+ }
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/BoundAppKeysAdapter.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/adapter/BoundAppKeysAdapter.java
similarity index 58%
rename from Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/BoundAppKeysAdapter.java
rename to Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/adapter/BoundAppKeysAdapter.java
index 22f3f680b..42840ffb7 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/BoundAppKeysAdapter.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/adapter/BoundAppKeysAdapter.java
@@ -20,82 +20,71 @@
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package no.nordicsemi.android.nrfmeshprovisioner.adapter;
+package no.nordicsemi.android.nrfmeshprovisioner.keys.adapter;
-import android.arch.lifecycle.LiveData;
import android.content.Context;
-import android.support.annotation.NonNull;
-import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.Map;
+import java.util.Collections;
+import java.util.List;
+import androidx.annotation.NonNull;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.lifecycle.LiveData;
+import androidx.recyclerview.widget.RecyclerView;
import butterknife.BindView;
import butterknife.ButterKnife;
-import no.nordicsemi.android.meshprovisioner.transport.ApplicationKey;
+import no.nordicsemi.android.meshprovisioner.ApplicationKey;
import no.nordicsemi.android.meshprovisioner.transport.MeshModel;
import no.nordicsemi.android.meshprovisioner.utils.MeshParserUtils;
-import no.nordicsemi.android.nrfmeshprovisioner.BaseModelConfigurationActivity;
import no.nordicsemi.android.nrfmeshprovisioner.R;
+import no.nordicsemi.android.nrfmeshprovisioner.utils.Utils;
import no.nordicsemi.android.nrfmeshprovisioner.widgets.RemovableViewHolder;
public class BoundAppKeysAdapter extends RecyclerView.Adapter {
- private final ArrayList mAppKeys = new ArrayList<>();
+ private final ArrayList appKeys = new ArrayList<>();
private final Context mContext;
- private Map mBoundAppKeys = new LinkedHashMap<>();
- private OnItemClickListener mOnItemClickListener;
-
- public BoundAppKeysAdapter(final BaseModelConfigurationActivity activity, final LiveData meshModelLiveData) {
- this.mContext = activity;
- meshModelLiveData.observe(activity, meshModel -> {
- if(meshModel != null) {
- if (meshModel.getBoundApplicationKeys() != null) {
- mBoundAppKeys.putAll(meshModel.getBoundApplicationKeys());
- mAppKeys.clear();
- mAppKeys.addAll(meshModel.getBoundApplicationKeys().values());
- notifyDataSetChanged();
+
+ public BoundAppKeysAdapter(@NonNull final Context context,
+ @NonNull final List appKeys,
+ @NonNull final LiveData meshModelLiveData) {
+ this.mContext = context;
+ meshModelLiveData.observe((LifecycleOwner) context, meshModel -> {
+ if (meshModel != null) {
+ this.appKeys.clear();
+ for (Integer index : meshModel.getBoundAppKeyIndexes()) {
+ for (ApplicationKey applicationKey : appKeys) {
+ if (index == applicationKey.getKeyIndex()) {
+ this.appKeys.add(applicationKey);
+ }
+ }
}
+ Collections.sort(this.appKeys, Utils.appKeyComparator);
+ notifyDataSetChanged();
}
});
}
- public void setOnItemClickListener(final BoundAppKeysAdapter.OnItemClickListener listener) {
- mOnItemClickListener = listener;
- }
-
@NonNull
@Override
public BoundAppKeysAdapter.ViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int viewType) {
- final View layoutView = LayoutInflater.from(mContext).inflate(R.layout.bound_app_key_item, parent, false);
+ final View layoutView = LayoutInflater.from(mContext).inflate(R.layout.removable_row_item, parent, false);
return new BoundAppKeysAdapter.ViewHolder(layoutView);
}
@Override
public void onBindViewHolder(@NonNull final BoundAppKeysAdapter.ViewHolder holder, final int position) {
- if(mAppKeys.size() > 0) {
- final ApplicationKey applicationKey = mAppKeys.get(position);
+ if (appKeys.size() > 0) {
+ final ApplicationKey applicationKey = appKeys.get(position);
final String appKey = MeshParserUtils.bytesToHex(applicationKey.getKey(), false);
- final Integer appKeyIndex = applicationKey.getKeyIndex();
- if(appKeyIndex != null) {
- holder.appKeyId.setText(mContext.getString(R.string.app_key_index_item, appKeyIndex));
- holder.appKey.setText(appKey.toUpperCase());
- }
- }
- }
-
- private Integer getAppKeyIndex(final String appKey){
- for(Integer key : mBoundAppKeys.keySet()){
- if(mBoundAppKeys.get(key).equals(appKey)){
- return key;
- }
+ holder.appKeyName.setText(applicationKey.getName());
+ holder.appKey.setText(appKey.toUpperCase());
}
- return null;
}
@Override
@@ -105,7 +94,7 @@ public long getItemId(final int position) {
@Override
public int getItemCount() {
- return mAppKeys.size();
+ return appKeys.size();
}
public boolean isEmpty() {
@@ -113,8 +102,8 @@ public boolean isEmpty() {
}
public ApplicationKey getAppKey(final int position) {
- if(!mAppKeys.isEmpty()){
- return mAppKeys.get(position);
+ if (!appKeys.isEmpty()) {
+ return appKeys.get(position);
}
return null;
}
@@ -126,19 +115,14 @@ public interface OnItemClickListener {
public final class ViewHolder extends RemovableViewHolder {
- @BindView(R.id.app_key_id)
- TextView appKeyId;
- @BindView(R.id.app_key)
+ @BindView(R.id.title)
+ TextView appKeyName;
+ @BindView(R.id.subtitle)
TextView appKey;
private ViewHolder(final View view) {
super(view);
ButterKnife.bind(this, view);
- view.findViewById(R.id.removable).setOnClickListener(v -> {
- if (mOnItemClickListener != null) {
- mOnItemClickListener.onItemClick(getAdapterPosition(), mAppKeys.get(getAdapterPosition()));
- }
- });
}
}
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/ManageAppKeyAdapter.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/adapter/ManageAppKeyAdapter.java
similarity index 76%
rename from Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/ManageAppKeyAdapter.java
rename to Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/adapter/ManageAppKeyAdapter.java
index 92dbf70ad..6f6022fc9 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/ManageAppKeyAdapter.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/adapter/ManageAppKeyAdapter.java
@@ -20,11 +20,9 @@
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package no.nordicsemi.android.nrfmeshprovisioner.adapter;
+package no.nordicsemi.android.nrfmeshprovisioner.keys.adapter;
import android.content.Context;
-import android.support.annotation.NonNull;
-import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -34,11 +32,14 @@
import java.util.Collections;
import java.util.List;
+import androidx.annotation.NonNull;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.recyclerview.widget.RecyclerView;
import butterknife.BindView;
import butterknife.ButterKnife;
-import no.nordicsemi.android.meshprovisioner.transport.ApplicationKey;
+import no.nordicsemi.android.meshprovisioner.ApplicationKey;
+import no.nordicsemi.android.meshprovisioner.NodeKey;
import no.nordicsemi.android.meshprovisioner.utils.MeshParserUtils;
-import no.nordicsemi.android.nrfmeshprovisioner.ManageAppKeysActivity;
import no.nordicsemi.android.nrfmeshprovisioner.R;
import no.nordicsemi.android.nrfmeshprovisioner.utils.Utils;
import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.MeshNetworkLiveData;
@@ -50,10 +51,9 @@ public class ManageAppKeyAdapter extends RecyclerView.Adapter {
- //noinspection ConstantConditions
+ public ManageAppKeyAdapter(@NonNull final Context context, @NonNull final MeshNetworkLiveData meshNetworkLiveData) {
+ this.mContext = context;
+ meshNetworkLiveData.observe((LifecycleOwner) context, networkData -> {
final List keys = networkData.getAppKeys();
if (keys != null) {
appKeys.clear();
@@ -64,10 +64,18 @@ public ManageAppKeyAdapter(final ManageAppKeysActivity activity, final MeshNetwo
});
}
- public ManageAppKeyAdapter(final ManageAppKeysActivity activity, final List appKeys) {
- this.mContext = activity;
- this.appKeys.addAll(appKeys);
- Collections.sort(appKeys, Utils.appKeyComparator);
+ public ManageAppKeyAdapter(@NonNull final Context context,
+ @NonNull final List appKeys,
+ @NonNull final List appKeyIndexes) {
+ this.mContext = context;
+ for (NodeKey nodeKey : appKeyIndexes) {
+ for (ApplicationKey applicationKey : appKeys) {
+ if (nodeKey.getIndex() == applicationKey.getKeyIndex()) {
+ this.appKeys.add(applicationKey);
+ }
+ }
+ }
+ Collections.sort(this.appKeys, Utils.appKeyComparator);
notifyDataSetChanged();
}
@@ -78,7 +86,7 @@ public void setOnItemClickListener(final ManageAppKeyAdapter.OnItemClickListener
@NonNull
@Override
public ManageAppKeyAdapter.ViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int viewType) {
- final View layoutView = LayoutInflater.from(mContext).inflate(R.layout.app_key_item, parent, false);
+ final View layoutView = LayoutInflater.from(mContext).inflate(R.layout.removable_row_item, parent, false);
return new ManageAppKeyAdapter.ViewHolder(layoutView);
}
@@ -86,11 +94,10 @@ public ManageAppKeyAdapter.ViewHolder onCreateViewHolder(@NonNull final ViewGrou
public void onBindViewHolder(@NonNull final ManageAppKeyAdapter.ViewHolder holder, final int position) {
if (appKeys.size() > 0) {
final ApplicationKey appKey = appKeys.get(position);
- holder.appKeyId.setText(mContext.getString(R.string.app_key_item, appKey.getKeyIndex()));
+ holder.appKeyName.setText(appKey.getName());
final String key = MeshParserUtils.bytesToHex(appKey.getKey(), false);
holder.appKey.setText(key.toUpperCase());
holder.getSwipeableView().setTag(appKey);
-
}
}
@@ -110,14 +117,14 @@ public boolean isEmpty() {
@FunctionalInterface
public interface OnItemClickListener {
- void onItemClick(final int position, final ApplicationKey appKey);
+ void onItemClick(final int position, @NonNull final ApplicationKey appKey);
}
final class ViewHolder extends RemovableViewHolder {
- @BindView(R.id.app_key_id)
- TextView appKeyId;
- @BindView(R.id.app_key)
+ @BindView(R.id.title)
+ TextView appKeyName;
+ @BindView(R.id.subtitle)
TextView appKey;
private ViewHolder(final View view) {
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/AppKeyAdapter.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/adapter/ManageBoundNetKeyAdapter.java
similarity index 51%
rename from Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/AppKeyAdapter.java
rename to Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/adapter/ManageBoundNetKeyAdapter.java
index 9de67bb33..f9860d80b 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/AppKeyAdapter.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/adapter/ManageBoundNetKeyAdapter.java
@@ -20,53 +20,74 @@
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package no.nordicsemi.android.nrfmeshprovisioner.adapter;
+package no.nordicsemi.android.nrfmeshprovisioner.keys.adapter;
import android.content.Context;
-import android.support.v7.widget.RecyclerView;
-import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.RadioButton;
import android.widget.TextView;
+import java.util.List;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
import butterknife.BindView;
import butterknife.ButterKnife;
-import no.nordicsemi.android.meshprovisioner.transport.ApplicationKey;
+import no.nordicsemi.android.meshprovisioner.ApplicationKey;
+import no.nordicsemi.android.meshprovisioner.NetworkKey;
import no.nordicsemi.android.meshprovisioner.utils.MeshParserUtils;
import no.nordicsemi.android.nrfmeshprovisioner.R;
import no.nordicsemi.android.nrfmeshprovisioner.widgets.RemovableViewHolder;
-public class AppKeyAdapter extends RecyclerView.Adapter {
+public class ManageBoundNetKeyAdapter extends RecyclerView.Adapter {
- private final SparseArray appKeys;
+ private final List mNetworkKeys;
private final Context mContext;
+ private ApplicationKey mAppKey;
private OnItemClickListener mOnItemClickListener;
- public AppKeyAdapter(final Context context, final SparseArray appKeys) {
- this.mContext = context;
- this.appKeys = appKeys;
+ public ManageBoundNetKeyAdapter(@NonNull final Context context,
+ @NonNull final List networkKeys,
+ @NonNull final ApplicationKey appKey) {
+ mContext = context;
+ mNetworkKeys = networkKeys;
+ mAppKey = appKey;
}
- public void setOnItemClickListener(final AppKeyAdapter.OnItemClickListener listener) {
+ public void setOnItemClickListener(final ManageBoundNetKeyAdapter.OnItemClickListener listener) {
mOnItemClickListener = listener;
}
+ @NonNull
@Override
- public AppKeyAdapter.ViewHolder onCreateViewHolder(final ViewGroup parent, final int viewType) {
- final View layoutView = LayoutInflater.from(mContext).inflate(R.layout.app_key_item, parent, false);
- return new AppKeyAdapter.ViewHolder(layoutView);
+ public ManageBoundNetKeyAdapter.ViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int viewType) {
+ final View layoutView = LayoutInflater.from(mContext).inflate(R.layout.removable_row_item2, parent, false);
+ return new ManageBoundNetKeyAdapter.ViewHolder(layoutView);
}
@Override
- public void onBindViewHolder(final AppKeyAdapter.ViewHolder holder, final int position) {
- if(appKeys.size() > 0) {
- holder.appKeyId.setText(mContext.getString(R.string.app_key_item , position + 1));
- final String appKey = MeshParserUtils.bytesToHex(appKeys.get(position).getKey(), false);
- holder.appKey.setText(appKey.toUpperCase());
+ public void onBindViewHolder(@NonNull final ManageBoundNetKeyAdapter.ViewHolder holder, final int position) {
+ if (mNetworkKeys.size() > 0) {
+ final NetworkKey networkKey = mNetworkKeys.get(position);
+ holder.netKeyName.setText(networkKey.getName());
+ final String key = MeshParserUtils.bytesToHex(networkKey.getKey(), false);
+ holder.netKey.setText(key.toUpperCase());
+ holder.getSwipeableView().setTag(networkKey);
+
+ if (checkRadio(networkKey)) {
+ holder.bound.setChecked(true);
+ } else {
+ holder.bound.setChecked(false);
+ }
}
}
+ private boolean checkRadio(@NonNull final NetworkKey key) {
+ return key.getKeyIndex() == mAppKey.getBoundNetKeyIndex();
+ }
+
@Override
public long getItemId(final int position) {
return position;
@@ -74,7 +95,7 @@ public long getItemId(final int position) {
@Override
public int getItemCount() {
- return appKeys.size();
+ return mNetworkKeys.size();
}
public boolean isEmpty() {
@@ -83,23 +104,29 @@ public boolean isEmpty() {
@FunctionalInterface
public interface OnItemClickListener {
- void onItemClick(final int position, final ApplicationKey appKey);
+ ApplicationKey updateBoundNetKeyIndex(final int position, @NonNull final NetworkKey networkKey);
}
final class ViewHolder extends RemovableViewHolder {
- @BindView(R.id.app_key_id)
- TextView appKeyId;
- @BindView(R.id.app_key)
- TextView appKey;
+ @BindView(R.id.title)
+ TextView netKeyName;
+ @BindView(R.id.subtitle)
+ TextView netKey;
+ @BindView(R.id.radio)
+ RadioButton bound;
private ViewHolder(final View view) {
super(view);
ButterKnife.bind(this, view);
view.findViewById(R.id.removable).setOnClickListener(v -> {
if (mOnItemClickListener != null) {
- final int key = appKeys.keyAt(getAdapterPosition());
- mOnItemClickListener.onItemClick(key, appKeys.get(key));
+ final NetworkKey netKey = mNetworkKeys.get(getAdapterPosition());
+ final ApplicationKey appKey = mOnItemClickListener.updateBoundNetKeyIndex(getAdapterPosition(), netKey);
+ if (appKey != null) {
+ mAppKey = appKey;
+ notifyDataSetChanged();
+ }
}
});
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/BindAppKeyAdapter.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/adapter/ManageNetKeyAdapter.java
similarity index 55%
rename from Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/BindAppKeyAdapter.java
rename to Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/adapter/ManageNetKeyAdapter.java
index 8f5179741..496854ac3 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/BindAppKeyAdapter.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/adapter/ManageNetKeyAdapter.java
@@ -20,54 +20,69 @@
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package no.nordicsemi.android.nrfmeshprovisioner.adapter;
+package no.nordicsemi.android.nrfmeshprovisioner.keys.adapter;
import android.content.Context;
-import android.support.annotation.NonNull;
-import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
+import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
+import androidx.annotation.NonNull;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.recyclerview.widget.RecyclerView;
import butterknife.BindView;
import butterknife.ButterKnife;
-import no.nordicsemi.android.meshprovisioner.transport.ApplicationKey;
+import no.nordicsemi.android.meshprovisioner.NetworkKey;
import no.nordicsemi.android.meshprovisioner.utils.MeshParserUtils;
import no.nordicsemi.android.nrfmeshprovisioner.R;
+import no.nordicsemi.android.nrfmeshprovisioner.utils.Utils;
+import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.MeshNetworkLiveData;
import no.nordicsemi.android.nrfmeshprovisioner.widgets.RemovableViewHolder;
-public class BindAppKeyAdapter extends RecyclerView.Adapter {
+public class ManageNetKeyAdapter extends RecyclerView.Adapter {
- private final List appKeys;
+ private final List networkKeys = new ArrayList<>();
private final Context mContext;
private OnItemClickListener mOnItemClickListener;
- public BindAppKeyAdapter(final Context context, final List appKeys) {
+ public ManageNetKeyAdapter(@NonNull final Context context, @NonNull final MeshNetworkLiveData meshNetworkLiveData) {
this.mContext = context;
- this.appKeys = appKeys;
+ meshNetworkLiveData.observe((LifecycleOwner) context, networkData -> {
+ final List keys = networkData.getNetworkKeys();
+ if (keys != null) {
+ networkKeys.clear();
+ networkKeys.addAll(keys);
+ networkKeys.remove(0);
+ Collections.sort(networkKeys, Utils.netKeyComparator);
+ }
+ notifyDataSetChanged();
+ });
}
- public void setOnItemClickListener(final BindAppKeyAdapter.OnItemClickListener listener) {
+ public void setOnItemClickListener(final ManageNetKeyAdapter.OnItemClickListener listener) {
mOnItemClickListener = listener;
}
@NonNull
@Override
- public BindAppKeyAdapter.ViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int viewType) {
- final View layoutView = LayoutInflater.from(mContext).inflate(R.layout.app_key_item, parent, false);
- return new BindAppKeyAdapter.ViewHolder(layoutView);
+ public ManageNetKeyAdapter.ViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int viewType) {
+ final View layoutView = LayoutInflater.from(mContext).inflate(R.layout.removable_row_item, parent, false);
+ return new ManageNetKeyAdapter.ViewHolder(layoutView);
}
@Override
- public void onBindViewHolder(@NonNull final BindAppKeyAdapter.ViewHolder holder, final int position) {
- if(appKeys.size() > 0) {
- final ApplicationKey applicationKey = appKeys.get(position);
- holder.appKeyId.setText(mContext.getString(R.string.app_key_item , applicationKey.getKeyIndex()));
- final String appKey = MeshParserUtils.bytesToHex(applicationKey.getKey(), false);
- holder.appKey.setText(appKey.toUpperCase());
+ public void onBindViewHolder(@NonNull final ManageNetKeyAdapter.ViewHolder holder, final int position) {
+ if (networkKeys.size() > 0) {
+ final NetworkKey networkKey = networkKeys.get(position);
+ holder.netKeyName.setText(networkKey.getName());
+ final String key = MeshParserUtils.bytesToHex(networkKey.getKey(), false);
+ holder.netKey.setText(key.toUpperCase());
+ holder.getSwipeableView().setTag(networkKey);
}
}
@@ -78,7 +93,7 @@ public long getItemId(final int position) {
@Override
public int getItemCount() {
- return appKeys.size();
+ return networkKeys.size();
}
public boolean isEmpty() {
@@ -87,23 +102,23 @@ public boolean isEmpty() {
@FunctionalInterface
public interface OnItemClickListener {
- void onItemClick(final int position, final ApplicationKey appKey);
+ void onItemClick(final int position, @NonNull final NetworkKey networkKey);
}
final class ViewHolder extends RemovableViewHolder {
- @BindView(R.id.app_key_id)
- TextView appKeyId;
- @BindView(R.id.app_key)
- TextView appKey;
+ @BindView(R.id.title)
+ TextView netKeyName;
+ @BindView(R.id.subtitle)
+ TextView netKey;
private ViewHolder(final View view) {
super(view);
ButterKnife.bind(this, view);
view.findViewById(R.id.removable).setOnClickListener(v -> {
if (mOnItemClickListener != null) {
- final int key = getAdapterPosition();
- mOnItemClickListener.onItemClick(key, appKeys.get(key));
+ final NetworkKey key = networkKeys.get(getAdapterPosition());
+ mOnItemClickListener.onItemClick(getAdapterPosition(), key);
}
});
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentAddAppKey.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/dialogs/DialogFragmentAddKey.java
similarity index 72%
rename from Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentAddAppKey.java
rename to Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/dialogs/DialogFragmentAddKey.java
index 98d404d0e..33a60abab 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentAddAppKey.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/dialogs/DialogFragmentAddKey.java
@@ -20,34 +20,33 @@
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package no.nordicsemi.android.nrfmeshprovisioner.dialog;
+package no.nordicsemi.android.nrfmeshprovisioner.keys.dialogs;
-import android.app.AlertDialog;
+import android.annotation.SuppressLint;
+import androidx.appcompat.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.design.widget.TextInputEditText;
-import android.support.design.widget.TextInputLayout;
-import android.support.v4.app.DialogFragment;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
+import android.widget.TextView;
+import com.google.android.material.textfield.TextInputEditText;
+import com.google.android.material.textfield.TextInputLayout;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.DialogFragment;
import butterknife.BindView;
import butterknife.ButterKnife;
-import no.nordicsemi.android.meshprovisioner.transport.ApplicationKey;
import no.nordicsemi.android.meshprovisioner.utils.MeshParserUtils;
import no.nordicsemi.android.meshprovisioner.utils.SecureUtils;
import no.nordicsemi.android.nrfmeshprovisioner.R;
-import no.nordicsemi.android.nrfmeshprovisioner.adapter.AppKeyAdapter;
-
-public class DialogFragmentAddAppKey extends DialogFragment implements AppKeyAdapter.OnItemClickListener {
- private static final String APP_KEY = "APP_KEY";
+public class DialogFragmentAddKey extends DialogFragment {
//UI Bindings
@BindView(R.id.text_input_layout)
@@ -57,28 +56,30 @@ public class DialogFragmentAddAppKey extends DialogFragment implements AppKeyAda
private String mAppKey;
- public static DialogFragmentAddAppKey newInstance(final String appKey) {
- DialogFragmentAddAppKey fragmentNetworkKey = new DialogFragmentAddAppKey();
+ public interface DialogFragmentAddAppKeysListener {
+ void onAppKeyAdded(@NonNull final String appKey);
+ }
+
+ public static DialogFragmentAddKey newInstance() {
+ DialogFragmentAddKey fragmentAddAppKey = new DialogFragmentAddKey();
final Bundle args = new Bundle();
- args.putString(APP_KEY, appKey);
- fragmentNetworkKey.setArguments(args);
- return fragmentNetworkKey;
+ fragmentAddAppKey.setArguments(args);
+ return fragmentAddAppKey;
}
@Override
public void onCreate(@Nullable final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- if (getArguments() != null) {
- mAppKey = getArguments().getString(APP_KEY);
- }
+ mAppKey = SecureUtils.generateRandomApplicationKey();
}
@NonNull
@Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
+ @SuppressLint("InflateParams")
final View rootView = LayoutInflater.from(getContext()).inflate(R.layout.dialog_fragment_key_input, null);
ButterKnife.bind(this, rootView);
-
+ final TextView summary = rootView.findViewById(R.id.summary);
//Bind ui
appKeysInputLayout.setHint(getString(R.string.hint_app_key));
appKeyInput.setText(mAppKey);
@@ -103,33 +104,34 @@ public void afterTextChanged(final Editable s) {
}
});
- final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getContext()).setView(rootView)
+ final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(requireContext()).setView(rootView)
.setPositiveButton(R.string.ok, null).setNegativeButton(R.string.cancel, null)
- .setNeutralButton(R.string.generate_app_key, null);
+ .setNeutralButton(R.string.generate_new_key, null);
alertDialogBuilder.setIcon(R.drawable.ic_vpn_key_black_alpha_24dp);
alertDialogBuilder.setTitle(R.string.title_manage_app_keys);
- alertDialogBuilder.setMessage(R.string.summary_app_keys);
+ summary.setText(R.string.title_app_keys);
final AlertDialog alertDialog = alertDialogBuilder.show();
alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(v -> {
- final String appKey = appKeyInput.getText().toString();
+ final String appKey = appKeyInput.getEditableText().toString().trim();
if (validateInput(appKey)) {
try {
- ((DialogFragmentAddAppKeysListener) getContext()).onAppKeyAdded(appKey);
+ ((DialogFragmentAddAppKeysListener) requireContext()).onAppKeyAdded(appKey);
dismiss();
} catch (IllegalArgumentException ex) {
appKeysInputLayout.setError(ex.getMessage());
}
}
});
- alertDialog.getButton(DialogInterface.BUTTON_NEUTRAL).setOnClickListener(v -> appKeyInput.setText(SecureUtils.generateRandomNetworkKey()));
+ alertDialog.getButton(DialogInterface.BUTTON_NEUTRAL).
+ setOnClickListener(v -> appKeyInput.setText(SecureUtils.generateRandomNetworkKey()));
return alertDialog;
}
private boolean validateInput(final String appKey) {
try {
- if(MeshParserUtils.validateAppKeyInput(getContext(), appKey)) {
+ if(MeshParserUtils.validateAppKeyInput(appKey)) {
return true;
}
} catch (IllegalArgumentException ex) {
@@ -137,13 +139,4 @@ private boolean validateInput(final String appKey) {
}
return false;
}
-
- @Override
- public void onItemClick(final int position, final ApplicationKey appKey) {
-
- }
-
- public interface DialogFragmentAddAppKeysListener {
- void onAppKeyAdded(final String appKey);
- }
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentEditAppKey.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/dialogs/DialogFragmentEditAppKey.java
similarity index 69%
rename from Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentEditAppKey.java
rename to Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/dialogs/DialogFragmentEditAppKey.java
index dddab732b..fe663359d 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentEditAppKey.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/dialogs/DialogFragmentEditAppKey.java
@@ -20,31 +20,37 @@
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package no.nordicsemi.android.nrfmeshprovisioner.dialog;
+package no.nordicsemi.android.nrfmeshprovisioner.keys.dialogs;
-import android.app.AlertDialog;
+import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.design.widget.TextInputEditText;
-import android.support.design.widget.TextInputLayout;
-import android.support.v4.app.DialogFragment;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
+import android.text.method.KeyListener;
import android.view.LayoutInflater;
import android.view.View;
+import android.widget.TextView;
+import com.google.android.material.textfield.TextInputEditText;
+import com.google.android.material.textfield.TextInputLayout;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.DialogFragment;
import butterknife.BindView;
import butterknife.ButterKnife;
-import no.nordicsemi.android.meshprovisioner.transport.ApplicationKey;
+import no.nordicsemi.android.meshprovisioner.ApplicationKey;
import no.nordicsemi.android.meshprovisioner.utils.MeshParserUtils;
+import no.nordicsemi.android.meshprovisioner.utils.SecureUtils;
import no.nordicsemi.android.nrfmeshprovisioner.R;
-import no.nordicsemi.android.nrfmeshprovisioner.adapter.AppKeyAdapter;
+import no.nordicsemi.android.nrfmeshprovisioner.keys.MeshKeyListener;
+import no.nordicsemi.android.nrfmeshprovisioner.utils.HexKeyListener;
-public class DialogFragmentEditAppKey extends DialogFragment implements AppKeyAdapter.OnItemClickListener {
+public class DialogFragmentEditAppKey extends DialogFragment {
private static final String POSITION = "POSITION";
private static final String APP_KEY = "APP_KEY";
@@ -58,7 +64,7 @@ public class DialogFragmentEditAppKey extends DialogFragment implements AppKeyAd
private int mPosition;
private ApplicationKey mAppKey;
- public static DialogFragmentEditAppKey newInstance(final int position, final ApplicationKey appKey) {
+ public static DialogFragmentEditAppKey newInstance(final int position, @NonNull final ApplicationKey appKey) {
DialogFragmentEditAppKey fragmentNetworkKey = new DialogFragmentEditAppKey();
final Bundle args = new Bundle();
args.putInt(POSITION, position);
@@ -79,12 +85,16 @@ public void onCreate(@Nullable final Bundle savedInstanceState) {
@NonNull
@Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
+ @SuppressLint("InflateParams")
final View rootView = LayoutInflater.from(getContext()).inflate(R.layout.dialog_fragment_key_input, null);
- ButterKnife.bind(this, rootView);
+ ButterKnife.bind(this, rootView);
+ final TextView summary = rootView.findViewById(R.id.summary);
//Bind ui
+ final KeyListener hexKeyListener = new HexKeyListener();
appKeysInputLayout.setHint(getString(R.string.hint_app_key));
appKeyInput.setText(MeshParserUtils.bytesToHex(mAppKey.getKey(), false));
+ appKeyInput.setKeyListener(hexKeyListener);
appKeyInput.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(final CharSequence s, final int start, final int count, final int after) {
@@ -106,47 +116,30 @@ public void afterTextChanged(final Editable s) {
}
});
- final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getContext()).setView(rootView)
- .setPositiveButton(R.string.ok, null).setNegativeButton(R.string.cancel, null);
+ final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(requireContext())
+ .setView(rootView)
+ .setIcon(R.drawable.ic_vpn_key_black_alpha_24dp)
+ .setTitle(R.string.title_edit_key)
+ .setPositiveButton(R.string.ok, null)
+ .setNegativeButton(R.string.cancel, null)
+ .setNeutralButton(R.string.generate_new_key, null);
+ final AlertDialog alertDialog = alertDialogBuilder.show();
- alertDialogBuilder.setIcon(R.drawable.ic_vpn_key_black_alpha_24dp);
- alertDialogBuilder.setTitle(R.string.title_manage_app_keys);
- alertDialogBuilder.setMessage(R.string.summary_app_keys);
+ summary.setText(R.string.summary_edit_key);
- final AlertDialog alertDialog = alertDialogBuilder.show();
alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(v -> {
- final String appKey = appKeyInput.getText().toString();
- if (validateInput(appKey)) {
- try {
- ((DialogFragmentEditAppKeysListener) getContext()).onAppKeysUpdated(mPosition, appKey);
+ final String appKey = appKeyInput.getEditableText().toString().trim();
+ try {
+ if (((MeshKeyListener) requireContext()).onKeyUpdated(mPosition, appKey))
dismiss();
- } catch (IllegalArgumentException ex) {
- appKeysInputLayout.setError(ex.getMessage());
- }
+ } catch (IllegalArgumentException ex) {
+ appKeysInputLayout.setError(ex.getMessage());
}
+
});
+ alertDialog.getButton(DialogInterface.BUTTON_NEUTRAL).
+ setOnClickListener(v -> appKeyInput.setText(SecureUtils.generateRandomNetworkKey()));
return alertDialog;
}
-
- private boolean validateInput(final String appKey) {
- try {
-
- if(MeshParserUtils.validateAppKeyInput(getContext(), appKey)) {
- return true;
- }
- } catch (IllegalArgumentException ex) {
- appKeysInputLayout.setError(ex.getMessage());
- }
- return false;
- }
-
- @Override
- public void onItemClick(final int position, final ApplicationKey appKey) {
-
- }
-
- public interface DialogFragmentEditAppKeysListener {
- void onAppKeysUpdated(final int position, final String appKey);
- }
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentNetworkKey.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/dialogs/DialogFragmentEditNetKey.java
similarity index 63%
rename from Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentNetworkKey.java
rename to Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/dialogs/DialogFragmentEditNetKey.java
index ca1500bbc..41743d79c 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentNetworkKey.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/dialogs/DialogFragmentEditNetKey.java
@@ -20,38 +20,40 @@
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package no.nordicsemi.android.nrfmeshprovisioner.dialog;
+package no.nordicsemi.android.nrfmeshprovisioner.keys.dialogs;
-import android.app.AlertDialog;
+import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.design.widget.TextInputEditText;
-import android.support.design.widget.TextInputLayout;
-import android.support.v4.app.DialogFragment;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.text.method.KeyListener;
-import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
+import android.widget.TextView;
+import com.google.android.material.textfield.TextInputEditText;
+import com.google.android.material.textfield.TextInputLayout;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.DialogFragment;
import butterknife.BindView;
import butterknife.ButterKnife;
-import no.nordicsemi.android.meshprovisioner.transport.NetworkKey;
+import no.nordicsemi.android.meshprovisioner.NetworkKey;
import no.nordicsemi.android.meshprovisioner.utils.MeshParserUtils;
import no.nordicsemi.android.meshprovisioner.utils.SecureUtils;
import no.nordicsemi.android.nrfmeshprovisioner.R;
+import no.nordicsemi.android.nrfmeshprovisioner.keys.MeshKeyListener;
import no.nordicsemi.android.nrfmeshprovisioner.utils.HexKeyListener;
-import no.nordicsemi.android.nrfmeshprovisioner.utils.Utils;
-public class DialogFragmentNetworkKey extends DialogFragment {
+public class DialogFragmentEditNetKey extends DialogFragment {
- private static final String TAG = DialogFragmentNetworkKey.class.getSimpleName();
- private static final String PATTERN_NETWORK_KEY = "[0-9a-fA-F]{32}";
+ private static final String TAG = DialogFragmentEditNetKey.class.getSimpleName();
+ private static final String POSITION = "POSITION";
private static final String NETWORK_KEY = "NETWORK_KEY";
//UI Bindings
@@ -60,11 +62,13 @@ public class DialogFragmentNetworkKey extends DialogFragment {
@BindView(R.id.text_input)
TextInputEditText networkKeyInput;
+ private int mPosition;
private NetworkKey mNetworkKey;
- public static DialogFragmentNetworkKey newInstance(final NetworkKey networkKey) {
- DialogFragmentNetworkKey fragmentNetworkKey = new DialogFragmentNetworkKey();
+ public static DialogFragmentEditNetKey newInstance(final int position, @NonNull final NetworkKey networkKey) {
+ DialogFragmentEditNetKey fragmentNetworkKey = new DialogFragmentEditNetKey();
final Bundle args = new Bundle();
+ args.putInt(POSITION, position);
args.putParcelable(NETWORK_KEY, networkKey);
fragmentNetworkKey.setArguments(args);
return fragmentNetworkKey;
@@ -74,6 +78,7 @@ public static DialogFragmentNetworkKey newInstance(final NetworkKey networkKey)
public void onCreate(@Nullable final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
+ mPosition = getArguments().getInt(POSITION);
mNetworkKey = getArguments().getParcelable(NETWORK_KEY);
}
}
@@ -81,11 +86,12 @@ public void onCreate(@Nullable final Bundle savedInstanceState) {
@NonNull
@Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
- final View rootView = LayoutInflater.from(getContext()).inflate(R.layout.dialog_fragment_key_input, null);
+ @SuppressLint("InflateParams") final View rootView = LayoutInflater.from(getContext()).inflate(R.layout.dialog_fragment_key_input, null);
final KeyListener hexKeyListener = new HexKeyListener();
//Bind ui
ButterKnife.bind(this, rootView);
+ final TextView summary = rootView.findViewById(R.id.summary);
final String key = MeshParserUtils.bytesToHex(mNetworkKey.getKey(), false);
networkKeyInputLayout.setHint(getString(R.string.hint_network_key));
networkKeyInput.setKeyListener(hexKeyListener);
@@ -112,55 +118,27 @@ public void afterTextChanged(final Editable s) {
}
});
- final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getContext()).setView(rootView)
+ final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(requireContext()).setView(rootView)
.setPositiveButton(R.string.ok, null).setNegativeButton(R.string.cancel, null)
- .setNeutralButton(R.string.generate_network_key, null);
+ .setNeutralButton(R.string.generate_network_key, null)
+ .setIcon(R.drawable.ic_vpn_key_black_alpha_24dp)
+ .setTitle(R.string.title_edit_key);
+ final AlertDialog alertDialog = alertDialogBuilder.show();
- alertDialogBuilder.setIcon(R.drawable.ic_vpn_key_black_alpha_24dp);
- alertDialogBuilder.setTitle(R.string.title_generate_network_key);
- alertDialogBuilder.setMessage(R.string.summary_generate_network_key);
+ summary.setText(R.string.summary_edit_key);
- final AlertDialog alertDialog = alertDialogBuilder.show();
alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(v -> {
- final String networkKey = networkKeyInput.getText().toString();
- if (validateInput(networkKey)) {
- try {
- if (getParentFragment() == null) {
- ((DialogFragmentNetworkKeyListener) getActivity()).onNetworkKeyGenerated(networkKey);
- } else {
- ((DialogFragmentNetworkKeyListener) getParentFragment()).onNetworkKeyGenerated(networkKey);
- }
- } catch (Exception ex) {
- Log.v(TAG, ex.getMessage());
- }
- dismiss();
+ final String networkKey = networkKeyInput.getEditableText().toString().trim();
+ try {
+ if (((MeshKeyListener) requireActivity()).onKeyUpdated(mPosition, networkKey))
+ dismiss();
+ } catch (Exception ex) {
+ networkKeyInputLayout.setError(ex.getMessage());
}
});
- alertDialog.getButton(DialogInterface.BUTTON_NEUTRAL).setOnClickListener(v -> networkKeyInput.setText(SecureUtils.generateRandomNetworkKey()));
+ alertDialog.getButton(DialogInterface.BUTTON_NEUTRAL)
+ .setOnClickListener(v -> networkKeyInput.setText(SecureUtils.generateRandomNetworkKey()));
return alertDialog;
}
-
- private boolean validateInput(final String input) {
- try {
-
- if (!input.matches(Utils.HEX_PATTERN)) {
- networkKeyInputLayout.setError(getString(R.string.invalid_hex_value));
- return false;
- }
-
- if (MeshParserUtils.validateNetworkKeyInput(getContext(), input)) {
- return true;
- }
- } catch (IllegalArgumentException ex) {
- networkKeyInputLayout.setError(ex.getMessage());
- }
- return false;
- }
-
- public interface DialogFragmentNetworkKeyListener {
-
- void onNetworkKeyGenerated(final String networkKey);
-
- }
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentModelConfiguration.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/dialogs/DialogFragmentKeyName.java
similarity index 56%
rename from Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentModelConfiguration.java
rename to Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/dialogs/DialogFragmentKeyName.java
index 5f88aa2fc..2b4bec4ea 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentModelConfiguration.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/keys/dialogs/DialogFragmentKeyName.java
@@ -20,45 +20,47 @@
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package no.nordicsemi.android.nrfmeshprovisioner.dialog;
+package no.nordicsemi.android.nrfmeshprovisioner.keys.dialogs;
-import android.app.AlertDialog;
+import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.design.widget.TextInputEditText;
-import android.support.design.widget.TextInputLayout;
-import android.support.v4.app.DialogFragment;
import android.text.Editable;
-import android.text.InputType;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
+import android.widget.TextView;
+import com.google.android.material.textfield.TextInputEditText;
+import com.google.android.material.textfield.TextInputLayout;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.DialogFragment;
import butterknife.BindView;
import butterknife.ButterKnife;
-import no.nordicsemi.android.meshprovisioner.utils.MeshParserUtils;
-import no.nordicsemi.android.meshprovisioner.utils.SecureUtils;
import no.nordicsemi.android.nrfmeshprovisioner.R;
+import no.nordicsemi.android.nrfmeshprovisioner.keys.MeshKeyListener;
+
+public class DialogFragmentKeyName extends DialogFragment {
-public class DialogFragmentModelConfiguration extends DialogFragment{
- private static final String APP_KEY = "APP_KEY";
+ private static final String KEY_NAME = "NODE_NAME";
//UI Bindings
@BindView(R.id.text_input_layout)
- TextInputLayout appKeysInputLayout;
+ TextInputLayout keyNameInputLayout;
@BindView(R.id.text_input)
- TextInputEditText appKeyInput;
+ TextInputEditText keyNameInput;
- private String mAppKey;
+ private String name;
- public static DialogFragmentAddAppKey newInstance(final String appKey) {
- DialogFragmentAddAppKey fragmentNetworkKey = new DialogFragmentAddAppKey();
+ public static DialogFragmentKeyName newInstance(@NonNull final String name) {
+ DialogFragmentKeyName fragmentNetworkKey = new DialogFragmentKeyName();
final Bundle args = new Bundle();
- args.putString(APP_KEY, appKey);
+ args.putString(KEY_NAME, name);
fragmentNetworkKey.setArguments(args);
return fragmentNetworkKey;
}
@@ -67,21 +69,21 @@ public static DialogFragmentAddAppKey newInstance(final String appKey) {
public void onCreate(@Nullable final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
- mAppKey = getArguments().getString(APP_KEY);
+ name = getArguments().getString(KEY_NAME);
}
}
@NonNull
@Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
- final View rootView = LayoutInflater.from(getContext()).inflate(R.layout.dialog_fragment_provision_data_input, null);
- ButterKnife.bind(this, rootView);
+ @SuppressLint("InflateParams") final View rootView = LayoutInflater.from(getContext()).inflate(R.layout.dialog_fragment_name, null);
//Bind ui
- appKeyInput.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS);
- appKeysInputLayout.setHint(getString(R.string.hint_app_key));
- appKeyInput.setText(mAppKey);
- appKeyInput.addTextChangedListener(new TextWatcher() {
+ ButterKnife.bind(this, rootView);
+ final TextView summary = rootView.findViewById(R.id.summary);
+ keyNameInputLayout.setHint(getString(R.string.name));
+ keyNameInput.setText(name);
+ keyNameInput.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(final CharSequence s, final int start, final int count, final int after) {
@@ -90,9 +92,9 @@ public void beforeTextChanged(final CharSequence s, final int start, final int c
@Override
public void onTextChanged(final CharSequence s, final int start, final int before, final int count) {
if (TextUtils.isEmpty(s.toString())) {
- appKeysInputLayout.setError(getString(R.string.error_empty_app_key));
+ keyNameInputLayout.setError(getString(R.string.error_empty_name));
} else {
- appKeysInputLayout.setError(null);
+ keyNameInputLayout.setError(null);
}
}
@@ -102,41 +104,25 @@ public void afterTextChanged(final Editable s) {
}
});
- final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getContext()).setView(rootView)
- .setPositiveButton(R.string.ok, null).setNegativeButton(R.string.cancel, null)
- .setNeutralButton(R.string.generate_app_key, null);
+ final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(requireContext()).setView(rootView)
+ .setPositiveButton(R.string.ok, null).setNegativeButton(R.string.cancel, null);
alertDialogBuilder.setIcon(R.drawable.ic_vpn_key_black_alpha_24dp);
- alertDialogBuilder.setTitle(R.string.title_manage_app_keys);
- alertDialogBuilder.setMessage(R.string.summary_app_keys);
+ alertDialogBuilder.setTitle(R.string.title_edit_key_name);
+ summary.setText(R.string.key_name_rationale);
final AlertDialog alertDialog = alertDialogBuilder.show();
alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(v -> {
- final String appKey = appKeyInput.getText().toString();
- if (validateInput(appKey)) {
- ((DialogFragmentAddAppKey.DialogFragmentAddAppKeysListener) getContext()).onAppKeyAdded(appKey);
- dismiss();
+ final String nodeName = keyNameInput.getEditableText().toString().trim();
+ try {
+ if (((MeshKeyListener) requireContext()).onKeyNameUpdated(nodeName)) {
+ dismiss();
+ }
+ } catch (IllegalArgumentException ex) {
+ keyNameInputLayout.setError(ex.getMessage());
}
});
- alertDialog.getButton(DialogInterface.BUTTON_NEUTRAL).setOnClickListener(v -> {
- appKeyInput.setText(SecureUtils.generateRandomNetworkKey());
- });
return alertDialog;
}
-
- private boolean validateInput(final String appKey) {
- try {
- if(MeshParserUtils.validateAppKeyInput(getContext(), appKey)) {
- return true;
- }
- } catch (IllegalArgumentException ex) {
- appKeysInputLayout.setError(ex.getMessage());
- }
- return false;
- }
-
- public interface DialogFragmentAddAppKeysListener {
- void onAppKeyAdded(final String appKey);
- }
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/BaseModelConfigurationActivity.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/BaseModelConfigurationActivity.java
new file mode 100644
index 000000000..1d81907be
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/BaseModelConfigurationActivity.java
@@ -0,0 +1,801 @@
+/*
+ * Copyright (c) 2018, Nordic Semiconductor
+ * 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 no.nordicsemi.android.nrfmeshprovisioner.node;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
+import com.google.android.material.snackbar.Snackbar;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+import java.util.UUID;
+
+import javax.inject.Inject;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.Toolbar;
+import androidx.coordinatorlayout.widget.CoordinatorLayout;
+import androidx.lifecycle.ViewModelProvider;
+import androidx.lifecycle.ViewModelProviders;
+import androidx.recyclerview.widget.ItemTouchHelper;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
+import butterknife.BindView;
+import butterknife.ButterKnife;
+import no.nordicsemi.android.meshprovisioner.ApplicationKey;
+import no.nordicsemi.android.meshprovisioner.Group;
+import no.nordicsemi.android.meshprovisioner.MeshNetwork;
+import no.nordicsemi.android.meshprovisioner.models.ConfigurationClientModel;
+import no.nordicsemi.android.meshprovisioner.models.ConfigurationServerModel;
+import no.nordicsemi.android.meshprovisioner.models.SigModel;
+import no.nordicsemi.android.meshprovisioner.models.SigModelParser;
+import no.nordicsemi.android.meshprovisioner.transport.ConfigModelAppBind;
+import no.nordicsemi.android.meshprovisioner.transport.ConfigModelAppStatus;
+import no.nordicsemi.android.meshprovisioner.transport.ConfigModelAppUnbind;
+import no.nordicsemi.android.meshprovisioner.transport.ConfigModelPublicationGet;
+import no.nordicsemi.android.meshprovisioner.transport.ConfigModelPublicationSet;
+import no.nordicsemi.android.meshprovisioner.transport.ConfigModelPublicationStatus;
+import no.nordicsemi.android.meshprovisioner.transport.ConfigModelSubscriptionAdd;
+import no.nordicsemi.android.meshprovisioner.transport.ConfigModelSubscriptionDelete;
+import no.nordicsemi.android.meshprovisioner.transport.ConfigModelSubscriptionStatus;
+import no.nordicsemi.android.meshprovisioner.transport.ConfigModelSubscriptionVirtualAddressAdd;
+import no.nordicsemi.android.meshprovisioner.transport.ConfigModelSubscriptionVirtualAddressDelete;
+import no.nordicsemi.android.meshprovisioner.transport.ConfigSigModelAppGet;
+import no.nordicsemi.android.meshprovisioner.transport.ConfigSigModelAppList;
+import no.nordicsemi.android.meshprovisioner.transport.ConfigSigModelSubscriptionGet;
+import no.nordicsemi.android.meshprovisioner.transport.ConfigSigModelSubscriptionList;
+import no.nordicsemi.android.meshprovisioner.transport.ConfigVendorModelAppGet;
+import no.nordicsemi.android.meshprovisioner.transport.ConfigVendorModelAppList;
+import no.nordicsemi.android.meshprovisioner.transport.ConfigVendorModelSubscriptionGet;
+import no.nordicsemi.android.meshprovisioner.transport.ConfigVendorModelSubscriptionList;
+import no.nordicsemi.android.meshprovisioner.transport.Element;
+import no.nordicsemi.android.meshprovisioner.transport.MeshMessage;
+import no.nordicsemi.android.meshprovisioner.transport.MeshModel;
+import no.nordicsemi.android.meshprovisioner.transport.ProvisionedMeshNode;
+import no.nordicsemi.android.meshprovisioner.transport.PublicationSettings;
+import no.nordicsemi.android.meshprovisioner.utils.CompositionDataParser;
+import no.nordicsemi.android.meshprovisioner.utils.MeshAddress;
+import no.nordicsemi.android.nrfmeshprovisioner.GroupCallbacks;
+import no.nordicsemi.android.nrfmeshprovisioner.R;
+import no.nordicsemi.android.nrfmeshprovisioner.adapter.GroupAddressAdapter;
+import no.nordicsemi.android.nrfmeshprovisioner.di.Injectable;
+import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentConfigStatus;
+import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentDisconnected;
+import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentError;
+import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentGroupSubscription;
+import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentTransactionStatus;
+import no.nordicsemi.android.nrfmeshprovisioner.keys.AppKeysActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.keys.adapter.BoundAppKeysAdapter;
+import no.nordicsemi.android.nrfmeshprovisioner.utils.Utils;
+import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.ModelConfigurationViewModel;
+import no.nordicsemi.android.nrfmeshprovisioner.widgets.ItemTouchHelperAdapter;
+import no.nordicsemi.android.nrfmeshprovisioner.widgets.RemovableItemTouchHelperCallback;
+import no.nordicsemi.android.nrfmeshprovisioner.widgets.RemovableViewHolder;
+
+public abstract class BaseModelConfigurationActivity extends AppCompatActivity implements Injectable,
+ GroupCallbacks,
+ ItemTouchHelperAdapter,
+ DialogFragmentDisconnected.DialogFragmentDisconnectedListener, SwipeRefreshLayout.OnRefreshListener {
+
+ private static final String DIALOG_FRAGMENT_CONFIGURATION_STATUS = "DIALOG_FRAGMENT_CONFIGURATION_STATUS";
+ private static final String PROGRESS_BAR_STATE = "PROGRESS_BAR_STATE";
+
+ @Inject
+ ViewModelProvider.Factory mViewModelFactory;
+
+ @BindView(R.id.container)
+ CoordinatorLayout mContainer;
+ @BindView(R.id.app_key_card)
+ View mContainerAppKeyBinding;
+ @BindView(R.id.action_bind_app_key)
+ Button mActionBindAppKey;
+ @BindView(R.id.bound_keys)
+ TextView mAppKeyView;
+ @BindView(R.id.unbind_hint)
+ TextView mUnbindHint;
+
+ @BindView(R.id.publish_address_card)
+ View mContainerPublication;
+ @BindView(R.id.action_set_publication)
+ Button mActionSetPublication;
+ @BindView(R.id.action_clear_publication)
+ Button mActionClearPublication;
+ @BindView(R.id.publish_address)
+ TextView mPublishAddressView;
+
+ @BindView(R.id.subscription_address_card)
+ View mContainerSubscribe;
+ @BindView(R.id.action_subscribe_address)
+ Button mActionSubscribe;
+ @BindView(R.id.subscribe_addresses)
+ TextView mSubscribeAddressView;
+ @BindView(R.id.subscribe_hint)
+ TextView mSubscribeHint;
+ @BindView(R.id.configuration_progress_bar)
+ ProgressBar mProgressbar;
+ @BindView(R.id.swipe_refresh)
+ SwipeRefreshLayout mSwipe;
+
+ protected Handler mHandler;
+ protected ModelConfigurationViewModel mViewModel;
+ protected List mGroupAddress = new ArrayList<>();
+ protected List mKeyIndexes = new ArrayList<>();
+ protected GroupAddressAdapter mSubscriptionAdapter;
+ protected BoundAppKeysAdapter mBoundAppKeyAdapter;
+ protected Button mActionRead;
+ protected Button mActionSetRelayState;
+ protected Button mReadNetworkTransmitStateButton;
+ protected Button mSetNetworkTransmitStateButton;
+
+ private RecyclerView recyclerViewBoundKeys, recyclerViewAddresses;
+ protected boolean mIsConnected;
+
+ @Override
+ protected void onCreate(final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_model_configuration);
+ ButterKnife.bind(this);
+ mViewModel = ViewModelProviders.of(this, mViewModelFactory).get(ModelConfigurationViewModel.class);
+ mHandler = new Handler();
+
+ final MeshModel meshModel = mViewModel.getSelectedModel().getValue();
+ //noinspection ConstantConditions
+ final String modelName = meshModel.getModelName();
+
+ // Set up views
+ final Toolbar toolbar = findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+ //noinspection ConstantConditions
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+ getSupportActionBar().setTitle(modelName);
+ final int modelId = meshModel.getModelId();
+ getSupportActionBar().setSubtitle(getString(R.string.model_id, CompositionDataParser.formatModelIdentifier(modelId, true)));
+ mSwipe.setOnRefreshListener(this);
+
+ recyclerViewAddresses = findViewById(R.id.recycler_view_addresses);
+ recyclerViewAddresses.setLayoutManager(new LinearLayoutManager(this));
+ final ItemTouchHelper.Callback itemTouchHelperCallback = new RemovableItemTouchHelperCallback(this);
+ final ItemTouchHelper itemTouchHelper = new ItemTouchHelper(itemTouchHelperCallback);
+ itemTouchHelper.attachToRecyclerView(recyclerViewAddresses);
+ mSubscriptionAdapter = new GroupAddressAdapter(this, mViewModel.getNetworkLiveData().getMeshNetwork(), mViewModel.getSelectedModel());
+ recyclerViewAddresses.setAdapter(mSubscriptionAdapter);
+
+ recyclerViewBoundKeys = findViewById(R.id.recycler_view_bound_keys);
+ recyclerViewBoundKeys.setLayoutManager(new LinearLayoutManager(this));
+ final ItemTouchHelper.Callback itemTouchHelperCallbackKeys = new RemovableItemTouchHelperCallback(this);
+ final ItemTouchHelper itemTouchHelperKeys = new ItemTouchHelper(itemTouchHelperCallbackKeys);
+ itemTouchHelperKeys.attachToRecyclerView(recyclerViewBoundKeys);
+ mBoundAppKeyAdapter = new BoundAppKeysAdapter(this, mViewModel.getNetworkLiveData().getAppKeys(), mViewModel.getSelectedModel());
+ recyclerViewBoundKeys.setAdapter(mBoundAppKeyAdapter);
+
+ mActionBindAppKey.setOnClickListener(v -> {
+ final ProvisionedMeshNode node = mViewModel.getSelectedMeshNode().getValue();
+ if (node != null && !node.isExist(SigModelParser.CONFIGURATION_SERVER)) {
+ return;
+ }
+ if (!checkConnectivity()) return;
+ final Intent bindAppKeysIntent = new Intent(BaseModelConfigurationActivity.this, AppKeysActivity.class);
+ bindAppKeysIntent.putExtra(Utils.EXTRA_DATA, Utils.BIND_APP_KEY);
+ startActivityForResult(bindAppKeysIntent, Utils.SELECT_KEY);
+ });
+
+ mPublishAddressView.setText(R.string.none);
+ mActionSetPublication.setOnClickListener(v -> navigateToPublication());
+
+ mActionClearPublication.setOnClickListener(v -> clearPublication());
+
+ mActionSubscribe.setOnClickListener(v -> {
+ if (!checkConnectivity()) return;
+ //noinspection ConstantConditions
+ final ArrayList groups = new ArrayList<>(mViewModel.getGroups().getValue());
+ final DialogFragmentGroupSubscription fragmentSubscriptionAddress = DialogFragmentGroupSubscription.newInstance(groups);
+ fragmentSubscriptionAddress.show(getSupportFragmentManager(), null);
+ });
+
+ mViewModel.getSelectedModel().observe(this, model -> {
+ if (model != null) {
+ updateAppStatusUi(model);
+ updatePublicationUi(model);
+ updateSubscriptionUi(model);
+ }
+ });
+
+ mViewModel.getTransactionStatus().observe(this, transactionStatus -> {
+ if (transactionStatus != null) {
+ hideProgressBar();
+ final String message = getString(R.string.operation_timed_out);
+ DialogFragmentTransactionStatus fragmentMessage = DialogFragmentTransactionStatus.newInstance("Transaction Failed", message);
+ fragmentMessage.show(getSupportFragmentManager(), null);
+ }
+ });
+
+ mViewModel.isConnectedToProxy().observe(this, isConnected -> {
+ if (isConnected != null) {
+ mIsConnected = isConnected;
+ hideProgressBar();
+ updateClickableViews();
+ }
+ invalidateOptionsMenu();
+ });
+
+ mViewModel.getMeshMessage().observe(this, this::updateMeshMessage);
+
+ final Boolean isConnectedToNetwork = mViewModel.isConnectedToProxy().getValue();
+ if (isConnectedToNetwork != null) {
+ mIsConnected = isConnectedToNetwork;
+ }
+ invalidateOptionsMenu();
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mViewModel.setActivityVisible(true);
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(final Menu menu) {
+ if (mIsConnected) {
+ getMenuInflater().inflate(R.menu.disconnect, menu);
+ } else {
+ getMenuInflater().inflate(R.menu.connect, menu);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(@NonNull final MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ case R.id.action_connect:
+ mViewModel.navigateToScannerActivity(this, false, Utils.CONNECT_TO_NETWORK, false);
+ return true;
+ case R.id.action_disconnect:
+ mViewModel.disconnect();
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ @Override
+ protected void onSaveInstanceState(@NonNull final Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putBoolean(PROGRESS_BAR_STATE, mProgressbar.getVisibility() == View.VISIBLE);
+ }
+
+ @Override
+ protected void onRestoreInstanceState(@NonNull final Bundle savedInstanceState) {
+ super.onRestoreInstanceState(savedInstanceState);
+ if (savedInstanceState.getBoolean(PROGRESS_BAR_STATE)) {
+ mProgressbar.setVisibility(View.VISIBLE);
+ disableClickableViews();
+ } else {
+ mProgressbar.setVisibility(View.INVISIBLE);
+ enableClickableViews();
+ }
+ }
+
+ @Override
+ protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ switch (requestCode) {
+ case Utils.SELECT_KEY:
+ if (resultCode == RESULT_OK) {
+ final ApplicationKey appKey = data.getParcelableExtra(AppKeysActivity.RESULT_APP_KEY);
+ if (appKey != null) {
+ bindAppKey(appKey.getKeyIndex());
+ }
+ }
+ break;
+ case PublicationSettingsActivity.SET_PUBLICATION_SETTINGS:
+ if (resultCode == RESULT_OK) {
+ showProgressbar();
+ }
+ break;
+ }
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mViewModel.setActivityVisible(false);
+ if (isFinishing()) {
+ mHandler.removeCallbacksAndMessages(null);
+ }
+ }
+
+ @Override
+ public Group createGroup(@NonNull final String name) {
+ final MeshNetwork network = mViewModel.getNetworkLiveData().getMeshNetwork();
+ return network.createGroup(network.getSelectedProvisioner(), name);
+ }
+
+ @Override
+ public Group createGroup(@NonNull final UUID uuid, final String name) {
+ final MeshNetwork network = mViewModel.getNetworkLiveData().getMeshNetwork();
+ return network.createGroup(uuid, null, name);
+ }
+
+ @Override
+ public boolean onGroupAdded(@NonNull final String name, final int address) {
+ final MeshNetwork network = mViewModel.getNetworkLiveData().getMeshNetwork();
+ final Group group = network.createGroup(network.getSelectedProvisioner(), address, name);
+ if (group != null) {
+ if (network.addGroup(group)) {
+ subscribe(group);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean onGroupAdded(@NonNull final Group group) {
+ final MeshNetwork network = mViewModel.getNetworkLiveData().getMeshNetwork();
+ if (network.addGroup(group)) {
+ subscribe(group);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void subscribe(final Group group) {
+ final ProvisionedMeshNode meshNode = mViewModel.getSelectedMeshNode().getValue();
+ if (meshNode != null) {
+ final Element element = mViewModel.getSelectedElement().getValue();
+ if (element != null) {
+ final int elementAddress = element.getElementAddress();
+ final MeshModel model = mViewModel.getSelectedModel().getValue();
+ if (model != null) {
+ final int modelIdentifier = model.getModelId();
+ final MeshMessage configModelSubscriptionAdd;
+ if (group.getAddressLabel() == null) {
+ configModelSubscriptionAdd = new ConfigModelSubscriptionAdd(elementAddress, group.getAddress(), modelIdentifier);
+ } else {
+ configModelSubscriptionAdd = new ConfigModelSubscriptionVirtualAddressAdd(elementAddress, group.getAddressLabel(), modelIdentifier);
+ }
+ sendMessage(meshNode.getUnicastAddress(), configModelSubscriptionAdd);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void onItemDismiss(final RemovableViewHolder viewHolder) {
+ final int position = viewHolder.getAdapterPosition();
+ if (viewHolder instanceof GroupAddressAdapter.ViewHolder) {
+ deleteSubscription(position);
+ } else if (viewHolder instanceof BoundAppKeysAdapter.ViewHolder) {
+ unbindAppKey(position);
+ }
+ }
+
+ @Override
+ public void onItemDismissFailed(final RemovableViewHolder viewHolder) {
+ }
+
+ @Override
+ public void onDisconnected() {
+ finish();
+ }
+
+ @Override
+ public void onRefresh() {
+ final MeshModel model = mViewModel.getSelectedModel().getValue();
+ if (!checkConnectivity() || model == null) {
+ mSwipe.setRefreshing(false);
+ }
+ final ProvisionedMeshNode node = mViewModel.getSelectedMeshNode().getValue();
+ final Element element = mViewModel.getSelectedElement().getValue();
+ if (node != null && element != null && model != null) {
+ if (model instanceof SigModel) {
+ if (!(model instanceof ConfigurationServerModel) && !(model instanceof ConfigurationClientModel)) {
+ mViewModel.displaySnackBar(this, mContainer, getString(R.string.listing_model_configuration), Snackbar.LENGTH_LONG);
+ final ConfigSigModelAppGet appGet = new ConfigSigModelAppGet(element.getElementAddress(), model.getModelId());
+ final ConfigSigModelSubscriptionGet subscriptionGet = new ConfigSigModelSubscriptionGet(element.getElementAddress(), model.getModelId());
+ mViewModel.getMessageQueue().add(appGet);
+ mViewModel.getMessageQueue().add(subscriptionGet);
+ queuePublicationGetMessage(element.getElementAddress(), model.getModelId());
+ //noinspection ConstantConditions
+ sendMessage(node.getUnicastAddress(), mViewModel.getMessageQueue().peek());
+ } else {
+ mSwipe.setRefreshing(false);
+ }
+
+ } else {
+ mViewModel.displaySnackBar(this, mContainer, getString(R.string.listing_model_configuration), Snackbar.LENGTH_LONG);
+ final ConfigVendorModelAppGet appGet = new ConfigVendorModelAppGet(element.getElementAddress(), model.getModelId());
+ final ConfigVendorModelSubscriptionGet subscriptionGet = new ConfigVendorModelSubscriptionGet(element.getElementAddress(), model.getModelId());
+ mViewModel.getMessageQueue().add(appGet);
+ mViewModel.getMessageQueue().add(subscriptionGet);
+ queuePublicationGetMessage(element.getElementAddress(), model.getModelId());
+ //noinspection ConstantConditions
+ sendMessage(node.getUnicastAddress(), mViewModel.getMessageQueue().peek());
+ }
+ }
+ }
+
+ protected void navigateToPublication() {
+ final MeshModel model = mViewModel.getSelectedModel().getValue();
+ if (model != null && !model.getBoundAppKeyIndexes().isEmpty()) {
+ final Intent publicationSettings = new Intent(this, PublicationSettingsActivity.class);
+ startActivityForResult(publicationSettings, PublicationSettingsActivity.SET_PUBLICATION_SETTINGS);
+ } else {
+ mViewModel.displaySnackBar(this, mContainer, getString(R.string.error_no_app_keys_bound), Snackbar.LENGTH_LONG);
+ }
+ }
+
+ private void bindAppKey(final int appKeyIndex) {
+ final ProvisionedMeshNode meshNode = mViewModel.getSelectedMeshNode().getValue();
+ if (meshNode != null) {
+ final Element element = mViewModel.getSelectedElement().getValue();
+ if (element != null) {
+ final MeshModel model = mViewModel.getSelectedModel().getValue();
+ if (model != null) {
+ final ConfigModelAppBind configModelAppUnbind = new ConfigModelAppBind(element.getElementAddress(), model.getModelId(), appKeyIndex);
+ sendMessage(meshNode.getUnicastAddress(), configModelAppUnbind);
+ }
+ }
+ }
+ }
+
+ private void unbindAppKey(final int position) {
+ if (mBoundAppKeyAdapter.getItemCount() != 0) {
+ if (!checkConnectivity()) {
+ mBoundAppKeyAdapter.notifyItemChanged(position);
+ return;
+ }
+ final ApplicationKey appKey = mBoundAppKeyAdapter.getAppKey(position);
+ final int keyIndex = appKey.getKeyIndex();
+ final ProvisionedMeshNode meshNode = mViewModel.getSelectedMeshNode().getValue();
+ if (meshNode != null) {
+ final Element element = mViewModel.getSelectedElement().getValue();
+ if (element != null) {
+ final MeshModel model = mViewModel.getSelectedModel().getValue();
+ if (model != null) {
+ final ConfigModelAppUnbind configModelAppUnbind = new ConfigModelAppUnbind(element.getElementAddress(), model.getModelId(), keyIndex);
+ sendMessage(meshNode.getUnicastAddress(), configModelAppUnbind);
+ }
+ }
+ }
+ }
+ }
+
+ private void clearPublication() {
+ final ProvisionedMeshNode meshNode = mViewModel.getSelectedMeshNode().getValue();
+ if (meshNode != null) {
+ final Element element = mViewModel.getSelectedElement().getValue();
+ if (element != null) {
+ final MeshModel model = mViewModel.getSelectedModel().getValue();
+ if (model != null) {
+ if (!model.getBoundAppKeyIndexes().isEmpty()) {
+ final int address = MeshAddress.UNASSIGNED_ADDRESS;
+ final int appKeyIndex = model.getPublicationSettings().getAppKeyIndex();
+ final boolean credentialFlag = model.getPublicationSettings().getCredentialFlag();
+ final int ttl = model.getPublicationSettings().getPublishTtl();
+ final int publicationSteps = model.getPublicationSettings().getPublicationSteps();
+ final int publicationResolution = model.getPublicationSettings().getPublicationResolution();
+ final int retransmitCount = model.getPublicationSettings().getPublishRetransmitCount();
+ final int retransmitIntervalSteps = model.getPublicationSettings().getPublishRetransmitIntervalSteps();
+ final ConfigModelPublicationSet configModelPublicationSet = new ConfigModelPublicationSet(element.getElementAddress(), address, appKeyIndex,
+ credentialFlag, ttl, publicationSteps, publicationResolution, retransmitCount, retransmitIntervalSteps, model.getModelId());
+ sendMessage(meshNode.getUnicastAddress(), configModelPublicationSet);
+ } else {
+ mViewModel.displaySnackBar(this, mContainer, getString(R.string.error_no_app_keys_bound), Snackbar.LENGTH_LONG);
+ }
+ }
+ }
+ }
+ }
+
+ private void deleteSubscription(final int position) {
+ if (mSubscriptionAdapter.getItemCount() != 0) {
+ if (!checkConnectivity()) {
+ mSubscriptionAdapter.notifyItemChanged(position);
+ return;
+ }
+ final int address = mGroupAddress.get(position);
+ final ProvisionedMeshNode meshNode = mViewModel.getSelectedMeshNode().getValue();
+ if (meshNode != null) {
+ final Element element = mViewModel.getSelectedElement().getValue();
+ if (element != null) {
+ final MeshModel model = mViewModel.getSelectedModel().getValue();
+ if (model != null) {
+ MeshMessage subscriptionDelete = null;
+ if (MeshAddress.isValidGroupAddress(address)) {
+ subscriptionDelete = new ConfigModelSubscriptionDelete(element.getElementAddress(), address, model.getModelId());
+ } else {
+ final UUID uuid = model.getLabelUUID(address);
+ if (uuid != null)
+ subscriptionDelete = new ConfigModelSubscriptionVirtualAddressDelete(element.getElementAddress(), uuid, model.getModelId());
+ }
+
+ if (subscriptionDelete != null) {
+ sendMessage(meshNode.getUnicastAddress(), subscriptionDelete);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ protected final void showProgressbar() {
+ mHandler.postDelayed(mOperationTimeout, Utils.MESSAGE_TIME_OUT);
+ disableClickableViews();
+ mProgressbar.setVisibility(View.VISIBLE);
+ }
+
+ protected final void hideProgressBar() {
+ mSwipe.setRefreshing(false);
+ enableClickableViews();
+ mProgressbar.setVisibility(View.INVISIBLE);
+ mHandler.removeCallbacks(mOperationTimeout);
+ }
+
+ private final Runnable mOperationTimeout = () -> {
+ hideProgressBar();
+ mViewModel.getMessageQueue().clear();
+ if (mViewModel.isActivityVisibile()) {
+ DialogFragmentTransactionStatus fragmentMessage = DialogFragmentTransactionStatus.
+ newInstance(getString(R.string.title_transaction_failed), getString(R.string.operation_timed_out));
+ fragmentMessage.show(getSupportFragmentManager(), null);
+ }
+ };
+
+ protected void enableClickableViews() {
+ mActionBindAppKey.setEnabled(true);
+ mActionSetPublication.setEnabled(true);
+ mActionClearPublication.setEnabled(true);
+ mActionSubscribe.setEnabled(true);
+
+ if (mActionSetRelayState != null)
+ mActionSetRelayState.setEnabled(true);
+ if (mReadNetworkTransmitStateButton != null)
+ mReadNetworkTransmitStateButton.setEnabled(true);
+ if (mSetNetworkTransmitStateButton != null)
+ mSetNetworkTransmitStateButton.setEnabled(true);
+
+ if (mActionRead != null && !mActionRead.isEnabled())
+ mActionRead.setEnabled(true);
+ }
+
+ protected void disableClickableViews() {
+ mActionBindAppKey.setEnabled(false);
+ mActionSetPublication.setEnabled(false);
+ mActionClearPublication.setEnabled(false);
+ mActionSubscribe.setEnabled(false);
+
+ if (mActionSetRelayState != null)
+ mActionSetRelayState.setEnabled(false);
+ if (mReadNetworkTransmitStateButton != null)
+ mReadNetworkTransmitStateButton.setEnabled(false);
+ if (mSetNetworkTransmitStateButton != null)
+ mSetNetworkTransmitStateButton.setEnabled(false);
+
+ if (mActionRead != null)
+ mActionRead.setEnabled(false);
+ }
+
+ /**
+ * Update the mesh message
+ *
+ * @param meshMessage {@link MeshMessage} mesh message status
+ */
+ protected void updateMeshMessage(final MeshMessage meshMessage) {
+ if (meshMessage instanceof ConfigModelAppStatus) {
+ final ConfigModelAppStatus status = (ConfigModelAppStatus) meshMessage;
+ if (status.isSuccessful()) {
+ mViewModel.displaySnackBar(this, mContainer, getString(R.string.operation_success), Snackbar.LENGTH_SHORT);
+ } else {
+ displayStatusDialogFragment(getString(R.string.title_appkey_status), status.getStatusCodeName());
+ }
+ } else if (meshMessage instanceof ConfigSigModelAppList) {
+ final ConfigSigModelAppList status = (ConfigSigModelAppList) meshMessage;
+ mViewModel.removeMessage();
+ if (status.isSuccessful()) {
+ if (handleStatuses()) return;
+ } else {
+ displayStatusDialogFragment(getString(R.string.title_sig_model_subscription_list), status.getStatusCodeName());
+ }
+ } else if (meshMessage instanceof ConfigVendorModelAppList) {
+ final ConfigVendorModelAppList status = (ConfigVendorModelAppList) meshMessage;
+ mViewModel.removeMessage();
+ if (status.isSuccessful()) {
+ if (handleStatuses()) return;
+ } else {
+ displayStatusDialogFragment(getString(R.string.title_vendor_model_app_list), status.getStatusCodeName());
+ }
+ } else if (meshMessage instanceof ConfigModelPublicationStatus) {
+ final ConfigModelPublicationStatus status = (ConfigModelPublicationStatus) meshMessage;
+ mViewModel.removeMessage();
+ if (status.isSuccessful()) {
+ if (handleStatuses()) return;
+ } else {
+ displayStatusDialogFragment(getString(R.string.title_publication_status), status.getStatusCodeName());
+ }
+ } else if (meshMessage instanceof ConfigModelSubscriptionStatus) {
+ final ConfigModelSubscriptionStatus status = (ConfigModelSubscriptionStatus) meshMessage;
+ mViewModel.removeMessage();
+ if (status.isSuccessful()) {
+ if (handleStatuses()) return;
+ } else {
+ displayStatusDialogFragment(getString(R.string.title_subscription_status), status.getStatusCodeName());
+ }
+ } else if (meshMessage instanceof ConfigSigModelSubscriptionList) {
+ final ConfigSigModelSubscriptionList status = (ConfigSigModelSubscriptionList) meshMessage;
+ mViewModel.removeMessage();
+ if (status.isSuccessful()) {
+ if (handleStatuses()) return;
+ } else {
+ displayStatusDialogFragment(getString(R.string.title_sig_model_subscription_list), status.getStatusCodeName());
+ }
+ } else if (meshMessage instanceof ConfigVendorModelSubscriptionList) {
+ final ConfigVendorModelSubscriptionList status = (ConfigVendorModelSubscriptionList) meshMessage;
+ mViewModel.removeMessage();
+ if (status.isSuccessful()) {
+ if (handleStatuses()) return;
+ } else {
+ displayStatusDialogFragment(getString(R.string.title_vendor_model_subscription_list), status.getStatusCodeName());
+ }
+ }
+ hideProgressBar();
+ }
+
+ private void updateAppStatusUi(final MeshModel meshModel) {
+ final List keys = meshModel.getBoundAppKeyIndexes();
+ mKeyIndexes.clear();
+ mKeyIndexes.addAll(keys);
+ if (!keys.isEmpty()) {
+ mUnbindHint.setVisibility(View.VISIBLE);
+ mAppKeyView.setVisibility(View.GONE);
+ recyclerViewBoundKeys.setVisibility(View.VISIBLE);
+ } else {
+ mUnbindHint.setVisibility(View.GONE);
+ mAppKeyView.setVisibility(View.VISIBLE);
+ recyclerViewBoundKeys.setVisibility(View.GONE);
+ }
+ }
+
+ private void updatePublicationUi(final MeshModel meshModel) {
+ final PublicationSettings publicationSettings = meshModel.getPublicationSettings();
+ if (publicationSettings != null) {
+ final int publishAddress = publicationSettings.getPublishAddress();
+ if (publishAddress != MeshAddress.UNASSIGNED_ADDRESS) {
+ if (MeshAddress.isValidVirtualAddress(publishAddress)) {
+ final UUID uuid = publicationSettings.getLabelUUID();
+ if (uuid != null) {
+ mPublishAddressView.setText(uuid.toString().toUpperCase(Locale.US));
+ } else {
+ mPublishAddressView.setText(MeshAddress.formatAddress(publishAddress, true));
+ }
+ } else {
+ mPublishAddressView.setText(MeshAddress.formatAddress(publishAddress, true));
+ }
+ mActionClearPublication.setVisibility(View.VISIBLE);
+ } else {
+ mPublishAddressView.setText(R.string.none);
+ mActionClearPublication.setVisibility(View.GONE);
+ }
+ }
+ }
+
+ private void updateSubscriptionUi(final MeshModel meshModel) {
+ final List subscriptionAddresses = meshModel.getSubscribedAddresses();
+ mGroupAddress.clear();
+ mGroupAddress.addAll(subscriptionAddresses);
+ if (!subscriptionAddresses.isEmpty()) {
+ mSubscribeHint.setVisibility(View.VISIBLE);
+ mSubscribeAddressView.setVisibility(View.GONE);
+ recyclerViewAddresses.setVisibility(View.VISIBLE);
+ } else {
+ mSubscribeHint.setVisibility(View.GONE);
+ mSubscribeAddressView.setVisibility(View.VISIBLE);
+ recyclerViewAddresses.setVisibility(View.GONE);
+ }
+ }
+
+ @SuppressWarnings("BooleanMethodIsAlwaysInverted")
+ protected final boolean checkConnectivity() {
+ if (!mIsConnected) {
+ mViewModel.displayDisconnectedSnackBar(this, mContainer);
+ return false;
+ }
+ return true;
+ }
+
+ protected void sendMessage(@NonNull final MeshMessage meshMessage) {
+ try {
+ if (!checkConnectivity())
+ return;
+ final ProvisionedMeshNode node = mViewModel.getSelectedMeshNode().getValue();
+ if (node != null) {
+ mViewModel.getMeshManagerApi().createMeshPdu(node.getUnicastAddress(), meshMessage);
+ showProgressbar();
+ }
+ } catch (IllegalArgumentException ex) {
+ hideProgressBar();
+ final DialogFragmentError message = DialogFragmentError.
+ newInstance(getString(R.string.title_error), ex.getMessage());
+ message.show(getSupportFragmentManager(), null);
+ }
+ }
+
+ private boolean handleStatuses() {
+ final MeshMessage message = mViewModel.getMessageQueue().peek();
+ if (message != null) {
+ sendMessage(message);
+ return true;
+ } else {
+ mViewModel.displaySnackBar(this, mContainer, getString(R.string.operation_success), Snackbar.LENGTH_SHORT);
+ }
+ return false;
+ }
+
+ protected void sendMessage(final int address, @NonNull final MeshMessage meshMessage) {
+ try {
+ if (!checkConnectivity())
+ return;
+ mViewModel.getMeshManagerApi().createMeshPdu(address, meshMessage);
+ showProgressbar();
+ } catch (IllegalArgumentException ex) {
+ hideProgressBar();
+ final DialogFragmentError message = DialogFragmentError.
+ newInstance(getString(R.string.title_error), ex.getMessage());
+ message.show(getSupportFragmentManager(), null);
+ }
+ }
+
+ private void updateClickableViews() {
+ final MeshModel model = mViewModel.getSelectedModel().getValue();
+ if (model != null && model.getModelId() == SigModelParser.CONFIGURATION_CLIENT)
+ disableClickableViews();
+ }
+
+ private void queuePublicationGetMessage(final int address, final int modelId) {
+ final ConfigModelPublicationGet publicationGet = new ConfigModelPublicationGet(address, modelId);
+ mViewModel.getMessageQueue().add(publicationGet);
+ }
+
+ private void displayStatusDialogFragment(@NonNull final String title, @NonNull final String message) {
+ if (mViewModel.isActivityVisibile()) {
+ DialogFragmentConfigStatus fragmentAppKeyBindStatus = DialogFragmentConfigStatus.
+ newInstance(title, message);
+ fragmentAppKeyBindStatus.show(getSupportFragmentManager(), DIALOG_FRAGMENT_CONFIGURATION_STATUS);
+ }
+ }
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/ConfigurationClientActivity.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/ConfigurationClientActivity.java
new file mode 100644
index 000000000..478374672
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/ConfigurationClientActivity.java
@@ -0,0 +1,19 @@
+package no.nordicsemi.android.nrfmeshprovisioner.node;
+
+import android.os.Bundle;
+
+import no.nordicsemi.android.meshprovisioner.models.ConfigurationClientModel;
+import no.nordicsemi.android.meshprovisioner.transport.MeshModel;
+
+
+public class ConfigurationClientActivity extends BaseModelConfigurationActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ final MeshModel model = mViewModel.getSelectedModel().getValue();
+ if (model instanceof ConfigurationClientModel) {
+ disableClickableViews();
+ }
+ }
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/ConfigurationServerActivity.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/ConfigurationServerActivity.java
similarity index 64%
rename from Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/ConfigurationServerActivity.java
rename to Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/ConfigurationServerActivity.java
index a1ffff172..1143b6897 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/ConfigurationServerActivity.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/ConfigurationServerActivity.java
@@ -1,15 +1,15 @@
-package no.nordicsemi.android.nrfmeshprovisioner;
+package no.nordicsemi.android.nrfmeshprovisioner.node;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.constraint.ConstraintLayout;
-import android.support.v7.widget.CardView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
+import androidx.annotation.NonNull;
+import androidx.cardview.widget.CardView;
+import androidx.constraintlayout.widget.ConstraintLayout;
import no.nordicsemi.android.meshprovisioner.models.ConfigurationServerModel;
import no.nordicsemi.android.meshprovisioner.transport.ConfigNetworkTransmitGet;
import no.nordicsemi.android.meshprovisioner.transport.ConfigNetworkTransmitSet;
@@ -22,8 +22,9 @@
import no.nordicsemi.android.meshprovisioner.transport.ProvisionedMeshNode;
import no.nordicsemi.android.meshprovisioner.utils.NetworkTransmitSettings;
import no.nordicsemi.android.meshprovisioner.utils.RelaySettings;
-import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentNetworkTransmitSettings;
-import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogRelayRetransmitSettings;
+import no.nordicsemi.android.nrfmeshprovisioner.R;
+import no.nordicsemi.android.nrfmeshprovisioner.node.dialog.DialogFragmentNetworkTransmitSettings;
+import no.nordicsemi.android.nrfmeshprovisioner.node.dialog.DialogRelayRetransmitSettings;
public class ConfigurationServerActivity extends BaseModelConfigurationActivity implements
DialogFragmentNetworkTransmitSettings.DialogFragmentNetworkTransmitSettingsListener,
@@ -34,17 +35,11 @@ public class ConfigurationServerActivity extends BaseModelConfigurationActivity
private static final int NETWORK_TRANSMIT_SETTING_UNKNOWN = -1;
private static final int RELAY_RETRANSMIT_SETTINGS_UNKNOWN = -1;
- private Button mActionReadRelayState;
- private Button mActionSetRelayState;
private TextView mRelayRetransmitCountText;
private TextView mRelayRetransmitIntervalStepsText;
-
- private Button mReadNetworkTransmitStateButton;
- private Button mSetNetworkTransmitStateButton;
private TextView mNetworkTransmitCountText;
private TextView mNetworkTransmitIntervalStepsText;
- private int mRelay;
private int mRelayRetransmitCount = RELAY_RETRANSMIT_SETTINGS_UNKNOWN;
private int mRelayRetransmitIntervalSteps = RELAY_RETRANSMIT_SETTINGS_UNKNOWN;
private int mNetworkTransmitCount = NETWORK_TRANSMIT_SETTING_UNKNOWN;
@@ -56,25 +51,31 @@ protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final MeshModel model = mViewModel.getSelectedModel().getValue();
if (model instanceof ConfigurationServerModel) {
- //Hide the subscription view since the ConfigurationServerModel is not a subscribe model
+ //Hide the app key binding, publication adn subscription views since the ConfigurationServerModel does not support app key binding
+ mContainerAppKeyBinding.setVisibility(View.GONE);
+ mContainerPublication.setVisibility(View.GONE);
mContainerSubscribe.setVisibility(View.GONE);
final ConstraintLayout view = findViewById(R.id.node_controls_container);
final View nodeControlsContainer = LayoutInflater.from(this)
.inflate(R.layout.layout_config_server_model, view);
final ProvisionedMeshNode meshNode = mViewModel.getSelectedMeshNode().getValue();
- if(meshNode != null) {
- if(meshNode.getNodeFeatures().isRelayFeatureSupported()) {
+ if (meshNode != null) {
+ final Button actionReadRelayState = nodeControlsContainer.findViewById(R.id.action_relay_retransmit_get);
+ mRelayRetransmitIntervalStepsText = nodeControlsContainer.findViewById(R.id.relay_retransmit_interval_steps);
+ mActionSetRelayState = nodeControlsContainer.findViewById(R.id.action_relay_retransmit_configure);
+ mRelayRetransmitCountText = nodeControlsContainer.findViewById(R.id.relay_retransmit_count);
+ if (meshNode.getNodeFeatures().isRelayFeatureSupported()) {
final CardView relayCardView = findViewById(R.id.config_relay_set_card);
relayCardView.setVisibility(View.VISIBLE);
- mRelayRetransmitCountText = nodeControlsContainer.findViewById(R.id.relay_retransmit_count);
- mRelayRetransmitIntervalStepsText = nodeControlsContainer.findViewById(R.id.relay_retransmit_interval_steps);
- mActionReadRelayState = nodeControlsContainer.findViewById(R.id.action_relay_retransmit_get);
- mActionReadRelayState.setOnClickListener(v -> getRelayRetransmit());
+ actionReadRelayState.setOnClickListener(v -> {
+ if (!checkConnectivity()) return;
+ getRelayRetransmit();
+ });
- mActionSetRelayState = nodeControlsContainer.findViewById(R.id.action_relay_retransmit_configure);
mActionSetRelayState.setOnClickListener(v -> {
+ if (!checkConnectivity()) return;
final RelaySettings relaySettings = meshNode.getRelaySettings();
if (relaySettings != null) {
mRelayRetransmitCount = meshNode.getRelaySettings().getRelayTransmitCount();
@@ -92,11 +93,15 @@ protected void onCreate(Bundle savedInstanceState) {
mNetworkTransmitIntervalStepsText = nodeControlsContainer.findViewById(R.id.network_transmit_interval_steps);
mReadNetworkTransmitStateButton = nodeControlsContainer.findViewById(R.id.action_network_transmit_get);
- mReadNetworkTransmitStateButton.setOnClickListener(v -> getNetworkTransmit());
+ mReadNetworkTransmitStateButton.setOnClickListener(v -> {
+ if (!checkConnectivity()) return;
+ getNetworkTransmit();
+ });
mSetNetworkTransmitStateButton = nodeControlsContainer.findViewById(R.id.action_network_transmit_configure);
mSetNetworkTransmitStateButton.setOnClickListener(v -> {
- if (meshNode.getNetworkTransmitSettings() != null) {
+ if (!checkConnectivity()) return;
+ if (meshNode != null && meshNode.getNetworkTransmitSettings() != null) {
mNetworkTransmitCount = meshNode.getNetworkTransmitSettings().getNetworkTransmitCount();
mNetworkTransmitIntervalSteps = meshNode.getNetworkTransmitSettings().getNetworkIntervalSteps();
}
@@ -106,8 +111,10 @@ protected void onCreate(Bundle savedInstanceState) {
});
mViewModel.getSelectedMeshNode().observe(this, node -> {
- updateNetworkTransmitUi(node);
- updateRelayUi(node);
+ if (node != null) {
+ updateNetworkTransmitUi(node);
+ updateRelayUi(node);
+ }
});
if (savedInstanceState == null) {
@@ -120,25 +127,62 @@ protected void onCreate(Bundle savedInstanceState) {
private void getRelayRetransmit() {
final ProvisionedMeshNode node = mViewModel.getSelectedMeshNode().getValue();
try {
- if(node != null) {
+ if (node != null) {
ConfigRelayGet message = new ConfigRelayGet();
- mViewModel.getMeshManagerApi().sendMeshMessage(node.getUnicastAddress(), message);
- showProgressbar();
+ sendMessage(node.getUnicastAddress(), message);
}
} catch (Exception e) {
Log.e(TAG, "Exception while constructing ConfigNetworkTransmitGet", e);
}
}
+ @Override
+ protected void updateMeshMessage(final MeshMessage meshMessage) {
+ super.updateMeshMessage(meshMessage);
+ if (meshMessage instanceof ConfigNetworkTransmitStatus) {
+ final ConfigNetworkTransmitStatus status = (ConfigNetworkTransmitStatus) meshMessage;
+ final ProvisionedMeshNode meshNode = mViewModel.getNetworkLiveData().getMeshNetwork().getNode(status.getSrc());
+ updateNetworkTransmitUi(meshNode);
+ } else if (meshMessage instanceof ConfigRelayStatus) {
+ final ConfigRelayStatus status = (ConfigRelayStatus) meshMessage;
+ final ProvisionedMeshNode meshNode = mViewModel.getNetworkLiveData().getMeshNetwork().getNode(status.getSrc());
+ updateRelayUi(meshNode);
+ }
+ }
+
+ @Override
+ protected void enableClickableViews() {
+ super.enableClickableViews();
+ mReadNetworkTransmitStateButton.setEnabled(true);
+ mSetNetworkTransmitStateButton.setEnabled(true);
+ }
+
+ @Override
+ protected void disableClickableViews() {
+ super.disableClickableViews();
+ mReadNetworkTransmitStateButton.setEnabled(false);
+ mSetNetworkTransmitStateButton.setEnabled(false);
+ }
+
+ @Override
+ public void onNetworkTransmitSettingsEntered(int transmitCount, int transmitIntervalSteps) {
+ setNetworkTransmit(transmitCount, transmitIntervalSteps);
+ }
+
+ @Override
+ public void onRelayRetransmitSet(final int relay, final int retransmitCount, final int retransmitIntervalSteps) {
+ setRelayRetransmit(relay, retransmitCount, retransmitIntervalSteps);
+ }
+
private void getNetworkTransmit() {
final ProvisionedMeshNode node = mViewModel.getSelectedMeshNode().getValue();
try {
- if(node != null) {
+ if (node != null) {
ConfigNetworkTransmitGet message = new ConfigNetworkTransmitGet();
- mViewModel.getMeshManagerApi().sendMeshMessage(node.getUnicastAddress(), message);
- showProgressbar();
+ sendMessage(node.getUnicastAddress(), message);
}
} catch (Exception e) {
+ hideProgressBar();
Log.e(TAG, "Exception while constructing ConfigNetworkTransmitGet", e);
}
}
@@ -146,12 +190,12 @@ private void getNetworkTransmit() {
private void setRelayRetransmit(final int relay, final int relayRetransmit, final int relayRetransmitIntervalSteps) {
final ProvisionedMeshNode node = mViewModel.getSelectedMeshNode().getValue();
try {
- if(node != null) {
+ if (node != null) {
final ConfigRelaySet message = new ConfigRelaySet(relay, relayRetransmit, relayRetransmitIntervalSteps);
- mViewModel.getMeshManagerApi().sendMeshMessage(node.getUnicastAddress(), message);
- showProgressbar();
+ sendMessage(node.getUnicastAddress(), message);
}
} catch (Exception e) {
+ hideProgressBar();
Log.e(TAG, "Exception while ConfigNetworkTransmitSet: " + e.getMessage());
}
}
@@ -159,87 +203,46 @@ private void setRelayRetransmit(final int relay, final int relayRetransmit, fina
private void setNetworkTransmit(final int networkTransmitCount, final int networkTransmitIntervalSteps) {
final ProvisionedMeshNode node = mViewModel.getSelectedMeshNode().getValue();
try {
- if(node != null) {
+ if (node != null) {
final ConfigNetworkTransmitSet message = new ConfigNetworkTransmitSet(networkTransmitCount, networkTransmitIntervalSteps);
- mViewModel.getMeshManagerApi().sendMeshMessage(node.getUnicastAddress(), message);
- showProgressbar();
+ sendMessage(node.getUnicastAddress(), message);
}
} catch (Exception e) {
+ hideProgressBar();
Log.e(TAG, "Error ConfigNetworkTransmitSet: " + e.getMessage());
}
}
- @Override
- protected void updateMeshMessage(final MeshMessage meshMessage) {
- super.updateMeshMessage(meshMessage);
- if (meshMessage instanceof ConfigNetworkTransmitStatus) {
- final ConfigNetworkTransmitStatus status = (ConfigNetworkTransmitStatus) meshMessage;
- final ProvisionedMeshNode meshNode = mViewModel.getMeshManagerApi().getMeshNetwork().getProvisionedNode(status.getSrc());
- updateNetworkTransmitUi(meshNode);
- } else if (meshMessage instanceof ConfigRelayStatus) {
- final ConfigRelayStatus status = (ConfigRelayStatus) meshMessage;
- final ProvisionedMeshNode meshNode = mViewModel.getMeshManagerApi().getMeshNetwork().getProvisionedNode(status.getSrc());
- updateRelayUi(meshNode);
- }
- }
-
- private void updateNetworkTransmitUi(final ProvisionedMeshNode meshNode) {
- if(meshNode != null) {
- final NetworkTransmitSettings networkTransmitSettings = meshNode.getNetworkTransmitSettings();
- if (networkTransmitSettings != null) {
- mSetNetworkTransmitStateButton.setEnabled(true);
- mNetworkTransmitCountText.setText(getString(R.string.text_network_transmit_count,
- networkTransmitSettings.getTransmissionCount()));
- mNetworkTransmitIntervalStepsText.setText(getString(R.string.text_network_transmit_interval_steps,
- networkTransmitSettings.getNetworkTransmissionInterval()));
- } else {
- mSetNetworkTransmitStateButton.setEnabled(false);
- mNetworkTransmitCountText.setText(getResources().getString(R.string.unknown));
- mNetworkTransmitIntervalStepsText.setText(getResources().getString(R.string.unknown));
- }
+ private void updateNetworkTransmitUi(@NonNull final ProvisionedMeshNode meshNode) {
+ final NetworkTransmitSettings networkTransmitSettings = meshNode.getNetworkTransmitSettings();
+ if (networkTransmitSettings != null) {
+ mSetNetworkTransmitStateButton.setEnabled(true);
+ mNetworkTransmitCountText.setText(getResources().getQuantityString(R.plurals.transmit_count,
+ networkTransmitSettings.getTransmissionCount(),
+ networkTransmitSettings.getTransmissionCount()));
+ mNetworkTransmitIntervalStepsText.setText(getString(R.string.time_ms,
+ networkTransmitSettings.getNetworkTransmissionInterval()));
+ } else {
+ mSetNetworkTransmitStateButton.setEnabled(false);
+ mNetworkTransmitCountText.setText(getResources().getString(R.string.unknown));
+ mNetworkTransmitIntervalStepsText.setText(getResources().getString(R.string.unknown));
}
}
private void updateRelayUi(@NonNull final ProvisionedMeshNode meshNode) {
- //noinspection ConstantConditions
- if(meshNode != null) {
- final RelaySettings relaySettings = meshNode.getRelaySettings();
- if (relaySettings != null) {
- mActionSetRelayState.setEnabled(true);
- mRelayRetransmitCountText.setText(getString(R.string.summary_network_transmit_count,
- relaySettings.getRelayTransmitCount(),
- relaySettings.getTotalTransmissionsCount()));
- mRelayRetransmitIntervalStepsText.setText(getString(R.string.text_network_transmit_interval_steps,
- relaySettings.getRetransmissionIntervals()));
- } else {
- mActionSetRelayState.setEnabled(false);
- mRelayRetransmitCountText.setText(getResources().getString(R.string.unknown));
- mRelayRetransmitIntervalStepsText.setText(getResources().getString(R.string.unknown));
- }
+ final RelaySettings relaySettings = meshNode.getRelaySettings();
+ if (relaySettings != null) {
+ mActionSetRelayState.setEnabled(true);
+ mRelayRetransmitCountText.setText(getResources().getQuantityString(R.plurals.summary_network_transmit_count,
+ relaySettings.getRelayTransmitCount(),
+ relaySettings.getRelayTransmitCount(),
+ relaySettings.getTotalTransmissionsCount()));
+ mRelayRetransmitIntervalStepsText.setText(getString(R.string.time_ms,
+ relaySettings.getRetransmissionIntervals()));
+ } else {
+ mActionSetRelayState.setEnabled(false);
+ mRelayRetransmitCountText.setText(getResources().getString(R.string.unknown));
+ mRelayRetransmitIntervalStepsText.setText(getResources().getString(R.string.unknown));
}
}
-
- @Override
- protected void enableClickableViews() {
- super.enableClickableViews();
- mReadNetworkTransmitStateButton.setEnabled(true);
- mSetNetworkTransmitStateButton.setEnabled(true);
- }
-
- @Override
- protected void disableClickableViews() {
- super.disableClickableViews();
- mReadNetworkTransmitStateButton.setEnabled(false);
- mSetNetworkTransmitStateButton.setEnabled(false);
- }
-
- @Override
- public void onNetworkTransmitSettingsEntered(int transmitCount, int transmitIntervalSteps) {
- setNetworkTransmit(transmitCount, transmitIntervalSteps);
- }
-
- @Override
- public void onRelayRetransmitSet(final int relay, final int retransmitCount, final int retransmitIntervalSteps) {
- setRelayRetransmit(relay, retransmitCount, retransmitIntervalSteps);
- }
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/GenericLevelServerActivity.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/GenericLevelServerActivity.java
similarity index 88%
rename from Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/GenericLevelServerActivity.java
rename to Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/GenericLevelServerActivity.java
index 92f936f1c..193083546 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/GenericLevelServerActivity.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/GenericLevelServerActivity.java
@@ -1,17 +1,19 @@
-package no.nordicsemi.android.nrfmeshprovisioner;
+package no.nordicsemi.android.nrfmeshprovisioner.node;
-import android.arch.lifecycle.ViewModelProvider;
import android.os.Bundle;
-import android.support.constraint.ConstraintLayout;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.SeekBar;
import android.widget.TextView;
-import android.widget.Toast;
+
+import com.google.android.material.snackbar.Snackbar;
import javax.inject.Inject;
+import androidx.constraintlayout.widget.ConstraintLayout;
+import androidx.lifecycle.ViewModelProvider;
+import no.nordicsemi.android.meshprovisioner.ApplicationKey;
import no.nordicsemi.android.meshprovisioner.models.GenericLevelServerModel;
import no.nordicsemi.android.meshprovisioner.transport.Element;
import no.nordicsemi.android.meshprovisioner.transport.GenericLevelGet;
@@ -20,9 +22,9 @@
import no.nordicsemi.android.meshprovisioner.transport.MeshMessage;
import no.nordicsemi.android.meshprovisioner.transport.MeshModel;
import no.nordicsemi.android.meshprovisioner.transport.ProvisionedMeshNode;
-import no.nordicsemi.android.meshprovisioner.utils.CompositionDataParser;
import no.nordicsemi.android.meshprovisioner.utils.MeshAddress;
import no.nordicsemi.android.meshprovisioner.utils.MeshParserUtils;
+import no.nordicsemi.android.nrfmeshprovisioner.R;
public class GenericLevelServerActivity extends BaseModelConfigurationActivity {
@@ -61,15 +63,12 @@ protected void onCreate(Bundle savedInstanceState) {
final TextView delayTime = nodeControlsContainer.findViewById(R.id.delay_time);
level = nodeControlsContainer.findViewById(R.id.level);
- mLevelSeekBar = nodeControlsContainer.findViewById(R.id.level_seekbar);
+ mLevelSeekBar = nodeControlsContainer.findViewById(R.id.level_seek_bar);
mLevelSeekBar.setProgress(0);
mLevelSeekBar.setMax(100);
mActionRead = nodeControlsContainer.findViewById(R.id.action_read);
- mActionRead.setOnClickListener(v -> {
- sendGenericLevelGet();
- showProgressbar();
- });
+ mActionRead.setOnClickListener(v -> sendGenericLevelGet());
mTransitionTimeSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
int lastValue = 0;
@@ -156,7 +155,6 @@ public void onStartTrackingTouch(final SeekBar seekBar) {
@Override
public void onStopTrackingTouch(final SeekBar seekBar) {
- showProgressbar();
final int level = seekBar.getProgress();
final int delay = mDelaySeekBar.getProgress();
final int genericLevel = ((level * 65535) / 100) - 32768;
@@ -212,21 +210,21 @@ protected void updateMeshMessage(final MeshMessage meshMessage) {
* Send generic on off get to mesh node
*/
public void sendGenericLevelGet() {
+ if (!checkConnectivity()) return;
final Element element = mViewModel.getSelectedElement().getValue();
if (element != null) {
final MeshModel model = mViewModel.getSelectedModel().getValue();
if (model != null) {
if (!model.getBoundAppKeyIndexes().isEmpty()) {
final int appKeyIndex = model.getBoundAppKeyIndexes().get(0);
- final byte[] appKey = model.getBoundAppKey(appKeyIndex).getKey();
+ final ApplicationKey appKey = mViewModel.getNetworkLiveData().getMeshNetwork().getAppKey(appKeyIndex);
final int address = element.getElementAddress();
Log.v(TAG, "Sending message to element's unicast address: " + MeshAddress.formatAddress(address, true));
-
final GenericLevelGet genericLevelGet = new GenericLevelGet(appKey);
- mViewModel.getMeshManagerApi().sendMeshMessage(address, genericLevelGet);
+ sendMessage(address, genericLevelGet);
} else {
- Toast.makeText(this, R.string.error_no_app_keys_bound, Toast.LENGTH_SHORT).show();
+ mViewModel.displaySnackBar(this, mContainer, getString(R.string.error_no_app_keys_bound), Snackbar.LENGTH_LONG);
}
}
}
@@ -239,6 +237,7 @@ public void sendGenericLevelGet() {
* @param delay message execution delay in 5ms steps. After this delay milliseconds the model will execute the required behaviour.
*/
public void sendGenericLevel(final int level, final Integer delay) {
+ if (!checkConnectivity()) return;
final ProvisionedMeshNode node = mViewModel.getSelectedMeshNode().getValue();
if (node != null) {
final Element element = mViewModel.getSelectedElement().getValue();
@@ -247,15 +246,13 @@ public void sendGenericLevel(final int level, final Integer delay) {
if (model != null) {
if (!model.getBoundAppKeyIndexes().isEmpty()) {
final int appKeyIndex = model.getBoundAppKeyIndexes().get(0);
- final byte[] appKey = model.getBoundAppKey(appKeyIndex).getKey();
+ final ApplicationKey appKey = mViewModel.getNetworkLiveData().getMeshNetwork().getAppKey(appKeyIndex);
final int address = element.getElementAddress();
- Log.v(TAG, "No subscription addresses found for model: " + CompositionDataParser.formatModelIdentifier(model.getModelId(), true)
- + ". Sending message to element's unicast address: " + MeshAddress.formatAddress(address, true));
- final GenericLevelSet genericLevelSet = new GenericLevelSet(appKey, mTransitionSteps, mTransitionStepResolution, delay, level, node.getReceivedSequenceNumber());
- mViewModel.getMeshManagerApi().sendMeshMessage(address, genericLevelSet);
- showProgressbar();
+ final GenericLevelSet genericLevelSet = new GenericLevelSet(appKey, mTransitionSteps, mTransitionStepResolution, delay, level,
+ node.getSequenceNumber());
+ sendMessage(address, genericLevelSet);
} else {
- Toast.makeText(this, R.string.error_no_app_keys_bound, Toast.LENGTH_SHORT).show();
+ mViewModel.displaySnackBar(this, mContainer, getString(R.string.error_no_app_keys_bound), Snackbar.LENGTH_LONG);
}
}
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/GenericOnOffServerActivity.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/GenericOnOffServerActivity.java
similarity index 87%
rename from Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/GenericOnOffServerActivity.java
rename to Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/GenericOnOffServerActivity.java
index b1e2986a9..d2f5095fe 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/GenericOnOffServerActivity.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/GenericOnOffServerActivity.java
@@ -1,18 +1,20 @@
-package no.nordicsemi.android.nrfmeshprovisioner;
+package no.nordicsemi.android.nrfmeshprovisioner.node;
-import android.arch.lifecycle.ViewModelProvider;
import android.os.Bundle;
-import android.support.constraint.ConstraintLayout;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.TextView;
-import android.widget.Toast;
+
+import com.google.android.material.snackbar.Snackbar;
import javax.inject.Inject;
+import androidx.constraintlayout.widget.ConstraintLayout;
+import androidx.lifecycle.ViewModelProvider;
+import no.nordicsemi.android.meshprovisioner.ApplicationKey;
import no.nordicsemi.android.meshprovisioner.models.GenericOnOffServerModel;
import no.nordicsemi.android.meshprovisioner.transport.Element;
import no.nordicsemi.android.meshprovisioner.transport.GenericOnOffGet;
@@ -21,9 +23,9 @@
import no.nordicsemi.android.meshprovisioner.transport.MeshMessage;
import no.nordicsemi.android.meshprovisioner.transport.MeshModel;
import no.nordicsemi.android.meshprovisioner.transport.ProvisionedMeshNode;
-import no.nordicsemi.android.meshprovisioner.utils.CompositionDataParser;
import no.nordicsemi.android.meshprovisioner.utils.MeshAddress;
import no.nordicsemi.android.meshprovisioner.utils.MeshParserUtils;
+import no.nordicsemi.android.nrfmeshprovisioner.R;
public class GenericOnOffServerActivity extends BaseModelConfigurationActivity {
@@ -67,7 +69,7 @@ protected void onCreate(Bundle savedInstanceState) {
sendGenericOnOff(false, delaySeekBar.getProgress());
}
} catch (IllegalArgumentException ex) {
- Toast.makeText(this, ex.getMessage(), Toast.LENGTH_SHORT).show();
+ mViewModel.displaySnackBar(this, mContainer, ex.getMessage(), Snackbar.LENGTH_LONG);
}
});
@@ -200,22 +202,22 @@ protected void updateMeshMessage(final MeshMessage meshMessage) {
* Send generic on off get to mesh node
*/
public void sendGenericOnOffGet() {
+ if (!checkConnectivity()) return;
final Element element = mViewModel.getSelectedElement().getValue();
- if(element != null) {
+ if (element != null) {
final MeshModel model = mViewModel.getSelectedModel().getValue();
if (model != null) {
if (!model.getBoundAppKeyIndexes().isEmpty()) {
final int appKeyIndex = model.getBoundAppKeyIndexes().get(0);
- final byte[] appKey = model.getBoundAppKey(appKeyIndex).getKey();
+ final ApplicationKey appKey = mViewModel.getNetworkLiveData().getMeshNetwork().getAppKey(appKeyIndex);
final int address = element.getElementAddress();
Log.v(TAG, "Sending message to element's unicast address: " + MeshAddress.formatAddress(address, true));
final GenericOnOffGet genericOnOffSet = new GenericOnOffGet(appKey);
- mViewModel.getMeshManagerApi().sendMeshMessage(address, genericOnOffSet);
- showProgressbar();
+ sendMessage(address, genericOnOffSet);
} else {
- Toast.makeText(this, R.string.error_no_app_keys_bound, Toast.LENGTH_SHORT).show();
+ mViewModel.displaySnackBar(this, mContainer, getString(R.string.error_no_app_keys_bound), Snackbar.LENGTH_LONG);
}
}
}
@@ -228,23 +230,22 @@ public void sendGenericOnOffGet() {
* @param delay message execution delay in 5ms steps. After this delay milliseconds the model will execute the required behaviour.
*/
public void sendGenericOnOff(final boolean state, final Integer delay) {
+ if (!checkConnectivity()) return;
final ProvisionedMeshNode node = mViewModel.getSelectedMeshNode().getValue();
- if(node != null) {
+ if (node != null) {
final Element element = mViewModel.getSelectedElement().getValue();
if (element != null) {
final MeshModel model = mViewModel.getSelectedModel().getValue();
if (model != null) {
if (!model.getBoundAppKeyIndexes().isEmpty()) {
final int appKeyIndex = model.getBoundAppKeyIndexes().get(0);
- final byte[] appKey = model.getBoundAppKey(appKeyIndex).getKey();
+ final ApplicationKey appKey = mViewModel.getNetworkLiveData().getMeshNetwork().getAppKey(appKeyIndex);
final int address = element.getElementAddress();
- Log.v(TAG, "No subscription addresses found for model: " + CompositionDataParser.formatModelIdentifier(model.getModelId(), true)
- + ". Sending message to element's unicast address: " + MeshAddress.formatAddress(address, true));
- final GenericOnOffSet genericOnOffSet = new GenericOnOffSet(appKey, state, node.getReceivedSequenceNumber(), mTransitionSteps, mTransitionStepResolution, delay);
- mViewModel.getMeshManagerApi().sendMeshMessage(address, genericOnOffSet);
- showProgressbar();
+ final GenericOnOffSet genericOnOffSet = new GenericOnOffSet(appKey, state,
+ node.getSequenceNumber(), mTransitionSteps, mTransitionStepResolution, delay);
+ sendMessage(address, genericOnOffSet);
} else {
- Toast.makeText(this, R.string.error_no_app_keys_bound, Toast.LENGTH_SHORT).show();
+ mViewModel.displaySnackBar(this, mContainer, getString(R.string.error_no_app_keys_bound), Snackbar.LENGTH_LONG);
}
}
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/ModelConfigurationActivity.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/ModelConfigurationActivity.java
similarity index 80%
rename from Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/ModelConfigurationActivity.java
rename to Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/ModelConfigurationActivity.java
index 352011592..4e1ae8549 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/ModelConfigurationActivity.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/ModelConfigurationActivity.java
@@ -1,4 +1,4 @@
-package no.nordicsemi.android.nrfmeshprovisioner;
+package no.nordicsemi.android.nrfmeshprovisioner.node;
import android.os.Bundle;
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/NodeConfigurationActivity.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/NodeConfigurationActivity.java
new file mode 100644
index 000000000..e5b7839a9
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/NodeConfigurationActivity.java
@@ -0,0 +1,543 @@
+/*
+ * Copyright (c) 2018, Nordic Semiconductor
+ * 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 no.nordicsemi.android.nrfmeshprovisioner.node;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
+import javax.inject.Inject;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.Toolbar;
+import androidx.coordinatorlayout.widget.CoordinatorLayout;
+import androidx.core.content.ContextCompat;
+import androidx.lifecycle.ViewModelProvider;
+import androidx.lifecycle.ViewModelProviders;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import butterknife.BindView;
+import butterknife.ButterKnife;
+import no.nordicsemi.android.meshprovisioner.MeshNetwork;
+import no.nordicsemi.android.meshprovisioner.models.SigModelParser;
+import no.nordicsemi.android.meshprovisioner.transport.ConfigCompositionDataGet;
+import no.nordicsemi.android.meshprovisioner.transport.ConfigCompositionDataStatus;
+import no.nordicsemi.android.meshprovisioner.transport.ConfigDefaultTtlGet;
+import no.nordicsemi.android.meshprovisioner.transport.ConfigDefaultTtlSet;
+import no.nordicsemi.android.meshprovisioner.transport.ConfigDefaultTtlStatus;
+import no.nordicsemi.android.meshprovisioner.transport.ConfigNodeReset;
+import no.nordicsemi.android.meshprovisioner.transport.ConfigNodeResetStatus;
+import no.nordicsemi.android.meshprovisioner.transport.ConfigProxyGet;
+import no.nordicsemi.android.meshprovisioner.transport.ConfigProxyStatus;
+import no.nordicsemi.android.meshprovisioner.transport.Element;
+import no.nordicsemi.android.meshprovisioner.transport.MeshMessage;
+import no.nordicsemi.android.meshprovisioner.transport.MeshModel;
+import no.nordicsemi.android.meshprovisioner.transport.ProvisionedMeshNode;
+import no.nordicsemi.android.meshprovisioner.transport.ProxyConfigFilterStatus;
+import no.nordicsemi.android.nrfmeshprovisioner.R;
+import no.nordicsemi.android.nrfmeshprovisioner.di.Injectable;
+import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentConfigurationComplete;
+import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentError;
+import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentProxySet;
+import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentTransactionStatus;
+import no.nordicsemi.android.nrfmeshprovisioner.keys.AddAppKeysActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.keys.AddNetKeysActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.node.adapter.ElementAdapter;
+import no.nordicsemi.android.nrfmeshprovisioner.node.dialog.DialogFragmentElementName;
+import no.nordicsemi.android.nrfmeshprovisioner.node.dialog.DialogFragmentNodeName;
+import no.nordicsemi.android.nrfmeshprovisioner.node.dialog.DialogFragmentResetNode;
+import no.nordicsemi.android.nrfmeshprovisioner.provisioners.dialogs.DialogFragmentTtl;
+import no.nordicsemi.android.nrfmeshprovisioner.utils.Utils;
+import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.NodeConfigurationViewModel;
+
+public class NodeConfigurationActivity extends AppCompatActivity implements Injectable,
+ DialogFragmentNodeName.DialogFragmentNodeNameListener,
+ DialogFragmentElementName.DialogFragmentElementNameListener,
+ DialogFragmentTtl.DialogFragmentTtlListener,
+ ElementAdapter.OnItemClickListener,
+ DialogFragmentResetNode.DialogFragmentNodeResetListener,
+ DialogFragmentConfigurationComplete.ConfigurationCompleteListener {
+
+ private static final String PROGRESS_BAR_STATE = "PROGRESS_BAR_STATE";
+ private static final String PROXY_STATE = "PROXY_STATE";
+ private static final String REQUESTED_PROXY_STATE = "REQUESTED_PROXY_STATE";
+
+ @Inject
+ ViewModelProvider.Factory mViewModelFactory;
+
+ @BindView(R.id.container)
+ CoordinatorLayout mContainer;
+ @BindView(R.id.action_get_composition_data)
+ Button actionGetCompositionData;
+ @BindView(R.id.node_proxy_state_card)
+ View mProxyStateCard;
+ @BindView(R.id.proxy_state_summary)
+ TextView mProxyStateRationaleSummary;
+ @BindView(R.id.action_get_default_ttl)
+ Button actionGetDefaultTtl;
+ @BindView(R.id.action_set_default_ttl)
+ Button actionSetDefaultTtl;
+ @BindView(R.id.action_get_proxy_state)
+ Button actionGetProxyState;
+ @BindView(R.id.action_set_proxy_state)
+ Button actionSetProxyState;
+ @BindView(R.id.action_reset_node)
+ Button actionResetNode;
+ @BindView(R.id.recycler_view_elements)
+ RecyclerView mRecyclerViewElements;
+ @BindView(R.id.configuration_progress_bar)
+ ProgressBar mProgressbar;
+
+ private NodeConfigurationViewModel mViewModel;
+ private Handler mHandler;
+ private boolean mProxyState;
+ private boolean mRequestedState = true;
+ private boolean mIsConnected;
+
+ private final Runnable mRunnableOperationTimeout = () -> {
+ hideProgressBar();
+ if (mViewModel.isActivityVisibile()) {
+ DialogFragmentTransactionStatus fragmentMessage = DialogFragmentTransactionStatus.
+ newInstance(getString(R.string.title_transaction_failed), getString(R.string.operation_timed_out));
+ fragmentMessage.show(getSupportFragmentManager(), null);
+ }
+ };
+
+ @Override
+ protected void onCreate(final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_node_configuration);
+ ButterKnife.bind(this);
+ mViewModel = ViewModelProviders.of(this, mViewModelFactory).get(NodeConfigurationViewModel.class);
+
+ if (savedInstanceState != null) {
+ if (savedInstanceState.getBoolean(PROGRESS_BAR_STATE)) {
+ mProgressbar.setVisibility(View.VISIBLE);
+ disableClickableViews();
+ } else {
+ mProgressbar.setVisibility(View.INVISIBLE);
+ enableClickableViews();
+ }
+ mRequestedState = savedInstanceState.getBoolean(PROXY_STATE, true);
+ mProxyState = savedInstanceState.getBoolean(PROXY_STATE, true);
+ }
+
+ mHandler = new Handler();
+ if (mViewModel.getSelectedMeshNode().getValue() == null) {
+ finish();
+ }
+ // Set up views
+ final Toolbar toolbar = findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+ //noinspection ConstantConditions
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+ getSupportActionBar().setTitle(R.string.title_node_configuration);
+
+ final View containerNodeName = findViewById(R.id.container_node_name);
+ containerNodeName.findViewById(R.id.image)
+ .setBackground(ContextCompat.getDrawable(this, R.drawable.ic_label_black_alpha_24dp));
+ final TextView nodeNameTitle = containerNodeName.findViewById(R.id.title);
+ nodeNameTitle.setText(R.string.title_node_name);
+ final TextView nodeNameView = containerNodeName.findViewById(R.id.text);
+ nodeNameView.setVisibility(View.VISIBLE);
+ containerNodeName.setOnClickListener(v -> {
+ final DialogFragmentNodeName fragment = DialogFragmentNodeName.
+ newInstance(nodeNameView.getText().toString());
+ fragment.show(getSupportFragmentManager(), null);
+ });
+ final Button actionDetails = findViewById(R.id.action_show_details);
+ actionDetails.setOnClickListener(v -> {
+ final Intent intent = new Intent(NodeConfigurationActivity.this, NodeDetailsActivity.class);
+ startActivity(intent);
+ });
+
+ final TextView noElementsFound = findViewById(R.id.no_elements);
+ final View compositionActionContainer = findViewById(R.id.composition_action_container);
+ mRecyclerViewElements.setLayoutManager(new LinearLayoutManager(this));
+ final ElementAdapter adapter = new ElementAdapter(this, mViewModel.getSelectedMeshNode());
+ adapter.setHasStableIds(true);
+ adapter.setOnItemClickListener(this);
+ mRecyclerViewElements.setAdapter(adapter);
+
+ final View containerNetKey = findViewById(R.id.container_net_keys);
+ containerNetKey.findViewById(R.id.image)
+ .setBackground(ContextCompat.getDrawable(this, R.drawable.ic_vpn_key_black_alpha_24dp));
+ final TextView keyTitle = containerNetKey.findViewById(R.id.title);
+ keyTitle.setText(R.string.title_net_keys);
+ final TextView netKeySummary = containerNetKey.findViewById(R.id.text);
+ netKeySummary.setVisibility(View.VISIBLE);
+ containerNetKey.setOnClickListener(v -> {
+ final Intent intent = new Intent(this, AddNetKeysActivity.class);
+ startActivity(intent);
+ });
+
+ final View containerAppKey = findViewById(R.id.container_app_keys);
+ containerAppKey.findViewById(R.id.image).
+ setBackground(ContextCompat.getDrawable(this, R.drawable.ic_vpn_key_black_alpha_24dp));
+ ((TextView) containerAppKey.findViewById(R.id.title)).setText(R.string.title_app_keys);
+ final TextView appKeySummary = containerAppKey.findViewById(R.id.text);
+ appKeySummary.setVisibility(View.VISIBLE);
+ containerAppKey.setOnClickListener(v -> {
+ final Intent intent = new Intent(this, AddAppKeysActivity.class);
+ startActivity(intent);
+ });
+
+ final View containerDefaultTtl = findViewById(R.id.container_ttl);
+ containerDefaultTtl.findViewById(R.id.image).
+ setBackground(ContextCompat.getDrawable(this, R.drawable.ic_numeric));
+ ((TextView) containerDefaultTtl.findViewById(R.id.title)).setText(R.string.title_ttl);
+ final TextView defaultTtlSummary = containerDefaultTtl.findViewById(R.id.text);
+ defaultTtlSummary.setVisibility(View.VISIBLE);
+
+ mViewModel.getSelectedMeshNode().observe(this, meshNode -> {
+ if (meshNode == null) {
+ finish();
+ return;
+ }
+ getSupportActionBar().setSubtitle(meshNode.getNodeName());
+ nodeNameView.setText(meshNode.getNodeName());
+
+ updateClickableViews();
+
+ if (!meshNode.getElements().isEmpty()) {
+ compositionActionContainer.setVisibility(View.GONE);
+ noElementsFound.setVisibility(View.INVISIBLE);
+ mRecyclerViewElements.setVisibility(View.VISIBLE);
+ } else {
+ noElementsFound.setVisibility(View.VISIBLE);
+ compositionActionContainer.setVisibility(View.VISIBLE);
+ mRecyclerViewElements.setVisibility(View.INVISIBLE);
+ }
+
+ if (!meshNode.getAddedNetKeys().isEmpty()) {
+ netKeySummary.setText(String.valueOf(meshNode.getAddedNetKeys().size()));
+ } else {
+ netKeySummary.setText(R.string.no_app_keys_added);
+ }
+
+ if (!meshNode.getAddedAppKeys().isEmpty()) {
+ appKeySummary.setText(String.valueOf(meshNode.getAddedAppKeys().size()));
+ } else {
+ appKeySummary.setText(R.string.no_app_keys_added);
+ }
+
+ if (meshNode.getTtl() != null) {
+ defaultTtlSummary.setText(String.valueOf(meshNode.getTtl()));
+ } else {
+ defaultTtlSummary.setText(R.string.unknown);
+ }
+ });
+
+ actionGetCompositionData.setOnClickListener(v -> {
+ if (!checkConnectivity()) return;
+ final ConfigCompositionDataGet configCompositionDataGet = new ConfigCompositionDataGet();
+ sendMessage(configCompositionDataGet);
+ });
+
+ actionGetDefaultTtl.setOnClickListener(v -> {
+ if (!checkConnectivity()) return;
+ final ConfigDefaultTtlGet defaultTtlGet = new ConfigDefaultTtlGet();
+ sendMessage(defaultTtlGet);
+ });
+
+ actionSetDefaultTtl.setOnClickListener(v -> {
+ final ProvisionedMeshNode node = mViewModel.getSelectedMeshNode().getValue();
+ if (node != null) {
+ DialogFragmentTtl fragmentTtl = DialogFragmentTtl.newInstance(node.getTtl() == null ? -1 : node.getTtl());
+ fragmentTtl.show(getSupportFragmentManager(), null);
+ }
+ });
+
+ actionGetProxyState.setOnClickListener(v -> {
+ if (!checkConnectivity()) return;
+ final ConfigProxyGet configProxyGet = new ConfigProxyGet();
+ sendMessage(configProxyGet);
+ });
+
+ actionSetProxyState.setOnClickListener(v -> {
+ final String message;
+ if (mProxyState) {
+ message = getString(R.string.proxy_set_off_rationale_summary);
+ } else {
+ message = getString(R.string.proxy_set_on_rationale_summary);
+ }
+ final DialogFragmentProxySet resetNodeFragment = DialogFragmentProxySet.
+ newInstance(getString(R.string.title_proxy_state_settings), message, !mProxyState);
+ resetNodeFragment.show(getSupportFragmentManager(), null);
+ });
+
+ actionResetNode.setOnClickListener(v -> {
+ if (!checkConnectivity()) return;
+ final DialogFragmentResetNode resetNodeFragment = DialogFragmentResetNode.
+ newInstance(getString(R.string.title_reset_node), getString(R.string.reset_node_rationale_summary));
+ resetNodeFragment.show(getSupportFragmentManager(), null);
+ });
+
+ mViewModel.getTransactionStatus().observe(this, transactionStatus -> {
+ if (transactionStatus != null) {
+ hideProgressBar();
+ final String message;
+ if (transactionStatus.isIncompleteTimerExpired()) {
+ message = getString(R.string.segments_not_received_timed_out);
+ } else {
+ message = getString(R.string.operation_timed_out);
+ }
+ DialogFragmentTransactionStatus fragmentMessage = DialogFragmentTransactionStatus.newInstance(getString(R.string.title_transaction_failed), message);
+ fragmentMessage.show(getSupportFragmentManager(), null);
+ }
+ });
+
+ mViewModel.isConnectedToProxy().observe(this, isConnected -> {
+ if (isConnected != null) {
+ mIsConnected = isConnected;
+ hideProgressBar();
+ }
+ updateClickableViews();
+ invalidateOptionsMenu();
+ });
+
+ mViewModel.getMeshMessage().observe(this, this::updateMeshMessage);
+
+ updateProxySettingsCardUi();
+
+ final Boolean isConnectedToNetwork = mViewModel.isConnectedToProxy().getValue();
+ if (isConnectedToNetwork != null) {
+ mIsConnected = isConnectedToNetwork;
+ }
+ invalidateOptionsMenu();
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mViewModel.setActivityVisible(true);
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(final Menu menu) {
+ if (mIsConnected) {
+ getMenuInflater().inflate(R.menu.disconnect, menu);
+ } else {
+ getMenuInflater().inflate(R.menu.connect, menu);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(@NonNull final MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ case R.id.action_connect:
+ mViewModel.navigateToScannerActivity(this, false, Utils.CONNECT_TO_NETWORK, false);
+ return true;
+ case R.id.action_disconnect:
+ mViewModel.disconnect();
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mViewModel.setActivityVisible(false);
+ if (isFinishing()) {
+ mHandler.removeCallbacksAndMessages(null);
+ }
+ }
+
+ @Override
+ public void onBackPressed() {
+ super.onBackPressed();
+ }
+
+ @Override
+ protected void onSaveInstanceState(@NonNull final Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putBoolean(PROGRESS_BAR_STATE, mProgressbar.getVisibility() == View.VISIBLE);
+ outState.putBoolean(PROXY_STATE, mProxyState);
+ outState.putBoolean(REQUESTED_PROXY_STATE, mRequestedState);
+ }
+
+ @Override
+ public void onElementClicked(@NonNull final Element element) {
+ final DialogFragmentElementName fragmentElementName = DialogFragmentElementName.newInstance(element);
+ fragmentElementName.show(getSupportFragmentManager(), null);
+ }
+
+ @Override
+ public void onModelClicked(@NonNull final ProvisionedMeshNode meshNode, @NonNull final Element element, @NonNull final MeshModel model) {
+ mViewModel.setSelectedElement(element);
+ mViewModel.setSelectedModel(model);
+ mViewModel.navigateToModelActivity(this, model);
+ }
+
+ @Override
+ public void onNodeReset() {
+ final ConfigNodeReset configNodeReset = new ConfigNodeReset();
+ sendMessage(configNodeReset);
+ }
+
+ @Override
+ public void onConfigurationCompleted() {
+ //Do nothing
+ }
+
+ @Override
+ public boolean onNodeNameUpdated(@NonNull final String nodeName) {
+ final MeshNetwork network = mViewModel.getNetworkLiveData().getMeshNetwork();
+ final ProvisionedMeshNode node = mViewModel.getSelectedMeshNode().getValue();
+ if (node != null) {
+ node.setNodeName(nodeName);
+ return network.updateNodeName(node, nodeName);
+ }
+ return false;
+ }
+
+ @Override
+ public boolean onElementNameUpdated(@NonNull final Element element, @NonNull final String name) {
+ final MeshNetwork network = mViewModel.getNetworkLiveData().getMeshNetwork();
+ if (network != null) {
+ network.updateElementName(element, name);
+ }
+
+ return true;
+ }
+
+ private void updateProxySettingsCardUi() {
+ final ProvisionedMeshNode meshNode = mViewModel.getSelectedMeshNode().getValue();
+ if (meshNode != null && meshNode.getNodeFeatures() != null && meshNode.getNodeFeatures().isProxyFeatureSupported()) {
+ mProxyStateCard.setVisibility(View.VISIBLE);
+ updateProxySettingsButtonUi();
+ }
+ }
+
+ private void updateProxySettingsButtonUi() {
+ if (mProxyState) {
+ mProxyStateRationaleSummary.setText(R.string.proxy_set_off_rationale);
+ actionSetProxyState.setText(R.string.action_proxy_state_set_off);
+ } else {
+ mProxyStateRationaleSummary.setText(R.string.proxy_set_on_rationale);
+ actionSetProxyState.setText(R.string.action_proxy_state_set_on);
+ }
+ }
+
+ private void showProgressbar() {
+ mHandler.postDelayed(mRunnableOperationTimeout, Utils.MESSAGE_TIME_OUT);
+ disableClickableViews();
+ mProgressbar.setVisibility(View.VISIBLE);
+ }
+
+ private void hideProgressBar() {
+ enableClickableViews();
+ mProgressbar.setVisibility(View.INVISIBLE);
+ mHandler.removeCallbacks(mRunnableOperationTimeout);
+ }
+
+ private void enableClickableViews() {
+ actionGetCompositionData.setEnabled(true);
+ actionGetDefaultTtl.setEnabled(true);
+ actionSetDefaultTtl.setEnabled(true);
+ actionGetProxyState.setEnabled(true);
+ actionSetProxyState.setEnabled(true);
+ actionResetNode.setEnabled(true);
+ }
+
+ private void disableClickableViews() {
+ actionGetCompositionData.setEnabled(false);
+ actionGetDefaultTtl.setEnabled(false);
+ actionSetDefaultTtl.setEnabled(false);
+ actionGetProxyState.setEnabled(false);
+ actionSetProxyState.setEnabled(false);
+ actionResetNode.setEnabled(false);
+ }
+
+ private void updateMeshMessage(final MeshMessage meshMessage) {
+ if (meshMessage instanceof ProxyConfigFilterStatus) {
+ hideProgressBar();
+ }
+ if (meshMessage instanceof ConfigCompositionDataStatus) {
+ hideProgressBar();
+ } else if (meshMessage instanceof ConfigDefaultTtlStatus) {
+ hideProgressBar();
+ } else if (meshMessage instanceof ConfigNodeResetStatus) {
+ hideProgressBar();
+ finish();
+ } else if (meshMessage instanceof ConfigProxyStatus) {
+ final ConfigProxyStatus status = (ConfigProxyStatus) meshMessage;
+ mProxyState = status.isProxyFeatureEnabled();
+ updateProxySettingsCardUi();
+ hideProgressBar();
+ }
+ }
+
+ @SuppressWarnings("BooleanMethodIsAlwaysInverted")
+ protected final boolean checkConnectivity() {
+ if (!mIsConnected) {
+ mViewModel.displayDisconnectedSnackBar(this, mContainer);
+ return false;
+ }
+ return true;
+ }
+
+ private void updateClickableViews() {
+ final ProvisionedMeshNode meshNode = mViewModel.getSelectedMeshNode().getValue();
+ if (meshNode != null && meshNode.isConfigured() &&
+ !mViewModel.isModelExists(SigModelParser.CONFIGURATION_SERVER))
+ disableClickableViews();
+ }
+
+ private void sendMessage(final MeshMessage meshMessage) {
+ try {
+ if (!checkConnectivity())
+ return;
+ final ProvisionedMeshNode node = mViewModel.getSelectedMeshNode().getValue();
+ if (node != null) {
+ mViewModel.getMeshManagerApi().createMeshPdu(node.getUnicastAddress(), meshMessage);
+ showProgressbar();
+ }
+ } catch (IllegalArgumentException ex) {
+ hideProgressBar();
+ final DialogFragmentError message = DialogFragmentError.
+ newInstance(getString(R.string.title_error), ex.getMessage());
+ message.show(getSupportFragmentManager(), null);
+ }
+ }
+
+ @Override
+ public boolean setDefaultTtl(final int ttl) {
+ final ConfigDefaultTtlSet ttlSet = new ConfigDefaultTtlSet(ttl);
+ sendMessage(ttlSet);
+ return true;
+ }
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/NodeDetailsActivity.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/NodeDetailsActivity.java
similarity index 72%
rename from Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/NodeDetailsActivity.java
rename to Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/NodeDetailsActivity.java
index d5bd521d9..10f8d78b3 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/NodeDetailsActivity.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/NodeDetailsActivity.java
@@ -20,40 +20,40 @@
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package no.nordicsemi.android.nrfmeshprovisioner;
+package no.nordicsemi.android.nrfmeshprovisioner.node;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
-import android.content.Intent;
import android.os.Bundle;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.LinearLayoutManager;
-import android.support.v7.widget.RecyclerView;
-import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import java.text.DateFormat;
-import java.util.ArrayList;
+import javax.inject.Inject;
+
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.Toolbar;
+import androidx.lifecycle.ViewModelProvider;
+import androidx.lifecycle.ViewModelProviders;
import butterknife.ButterKnife;
import no.nordicsemi.android.meshprovisioner.Features;
import no.nordicsemi.android.meshprovisioner.transport.ProvisionedMeshNode;
-import no.nordicsemi.android.meshprovisioner.utils.AddressUtils;
import no.nordicsemi.android.meshprovisioner.utils.CompanyIdentifiers;
import no.nordicsemi.android.meshprovisioner.utils.CompositionDataParser;
+import no.nordicsemi.android.meshprovisioner.utils.MeshAddress;
import no.nordicsemi.android.meshprovisioner.utils.MeshParserUtils;
-import no.nordicsemi.android.nrfmeshprovisioner.adapter.ElementAdapterDetails;
+import no.nordicsemi.android.nrfmeshprovisioner.R;
import no.nordicsemi.android.nrfmeshprovisioner.di.Injectable;
-import no.nordicsemi.android.nrfmeshprovisioner.utils.Utils;
+import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.NodeDetailsViewModel;
-public class NodeDetailsActivity extends AppCompatActivity implements Injectable, ElementAdapterDetails.OnItemClickListener {
+public class NodeDetailsActivity extends AppCompatActivity implements Injectable {
- private final static String TAG = NodeDetailsActivity.class.getSimpleName();
- private RecyclerView mRecyclerView;
+ @Inject
+ ViewModelProvider.Factory mViewModelFactory;
@Override
protected void onCreate(final Bundle savedInstanceState) {
@@ -61,11 +61,12 @@ protected void onCreate(final Bundle savedInstanceState) {
setContentView(R.layout.activity_node_details);
ButterKnife.bind(this);
- final Intent intent = getIntent();
- final ProvisionedMeshNode node = intent.getParcelableExtra(Utils.EXTRA_DEVICE);
- if(node == null)
+ final NodeDetailsViewModel viewModel = ViewModelProviders.of(this, mViewModelFactory).get(NodeDetailsViewModel.class);
+ if (viewModel.getSelectedMeshNode().getValue() == null) {
finish();
+ }
+ final ProvisionedMeshNode node = viewModel.getSelectedMeshNode().getValue();
final ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
final Toolbar toolbar = findViewById(R.id.toolbar);
@@ -73,11 +74,6 @@ protected void onCreate(final Bundle savedInstanceState) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setTitle(node.getNodeName());
- final View containerNodeName = findViewById(R.id.container_element_count);
- containerNodeName.setClickable(false);
- final TextView nodeName = containerNodeName.findViewById(R.id.text);
- nodeName.setText(node.getNodeName());
-
final View containerProvisioningTimeStamp = findViewById(R.id.container_timestamp);
containerProvisioningTimeStamp.setClickable(false);
final TextView timestamp = containerProvisioningTimeStamp.findViewById(R.id.text);
@@ -87,7 +83,7 @@ protected void onCreate(final Bundle savedInstanceState) {
final View containerUnicastAddress = findViewById(R.id.container_supported_algorithm);
containerUnicastAddress.setClickable(false);
final TextView unicastAddress = containerUnicastAddress.findViewById(R.id.text);
- unicastAddress.setText(MeshParserUtils.bytesToHex(AddressUtils.getUnicastAddressBytes(node.getUnicastAddress()), false));
+ unicastAddress.setText(MeshParserUtils.bytesToHex(MeshAddress.addressIntToBytes(node.getUnicastAddress()), false));
final View containerDeviceKey = findViewById(R.id.container_device_key);
containerDeviceKey.setClickable(false);
@@ -96,7 +92,7 @@ protected void onCreate(final Bundle savedInstanceState) {
final View copyDeviceKey = findViewById(R.id.copy);
copyDeviceKey.setOnClickListener(v -> {
- if(clipboard != null) {
+ if (clipboard != null) {
final ClipData clipDeviceKey = ClipData.newPlainText("Device Key", MeshParserUtils.bytesToHex(node.getDeviceKey(), false));
clipboard.setPrimaryClip(clipDeviceKey);
Toast.makeText(NodeDetailsActivity.this, R.string.device_key_clipboard_copied, Toast.LENGTH_SHORT).show();
@@ -106,16 +102,16 @@ protected void onCreate(final Bundle savedInstanceState) {
final View containerCompanyIdentifier = findViewById(R.id.container_company_identifier);
containerCompanyIdentifier.setClickable(false);
final TextView companyIdentifier = containerCompanyIdentifier.findViewById(R.id.text);
- if(node.getCompanyIdentifier() != null) {
+ if (node.getCompanyIdentifier() != null) {
companyIdentifier.setText(CompanyIdentifiers.getCompanyName(node.getCompanyIdentifier().shortValue()));
} else {
- companyIdentifier.setText(R.string.unavailable);
+ companyIdentifier.setText(R.string.unknown);
}
final View containerProductIdentifier = findViewById(R.id.container_product_identifier);
containerProductIdentifier.setClickable(false);
final TextView productIdentifier = containerProductIdentifier.findViewById(R.id.text);
- if(node.getProductIdentifier() != null) {
+ if (node.getProductIdentifier() != null) {
productIdentifier.setText(CompositionDataParser.formatProductIdentifier(node.getProductIdentifier().shortValue(), false));
} else {
productIdentifier.setText(R.string.unavailable);
@@ -124,7 +120,7 @@ protected void onCreate(final Bundle savedInstanceState) {
final View containerProductVersion = findViewById(R.id.container_product_version);
containerProductVersion.setClickable(false);
final TextView productVersion = containerProductVersion.findViewById(R.id.text);
- if(node.getVersionIdentifier() != null) {
+ if (node.getVersionIdentifier() != null) {
productVersion.setText(CompositionDataParser.formatVersionIdentifier(node.getVersionIdentifier().shortValue(), false));
} else {
productVersion.setText(R.string.unavailable);
@@ -133,7 +129,7 @@ protected void onCreate(final Bundle savedInstanceState) {
final View containerCrpl = findViewById(R.id.container_crpl);
containerCrpl.setClickable(false);
final TextView crpl = containerCrpl.findViewById(R.id.text);
- if(node.getCrpl() != null) {
+ if (node.getCrpl() != null) {
crpl.setText(CompositionDataParser.formatReplayProtectionCount(node.getCrpl().shortValue(), false));
} else {
crpl.setText(R.string.unavailable);
@@ -142,34 +138,18 @@ protected void onCreate(final Bundle savedInstanceState) {
final View containerFeatures = findViewById(R.id.container_features);
containerFeatures.setClickable(false);
final TextView features = containerFeatures.findViewById(R.id.text);
- if(node.getNodeFeatures() != null) {
+ if (node.getNodeFeatures() != null) {
features.setText(parseFeatures(node.getNodeFeatures()));
} else {
features.setText(R.string.unavailable);
}
-
- final TextView view = findViewById(R.id.no_elements_view);
- mRecyclerView = findViewById(R.id.recycler_view_elements);
- if(node.getElements().isEmpty()){
- view.setVisibility(View.VISIBLE);
- mRecyclerView.setVisibility(View.INVISIBLE);
- } else {
- view.setVisibility(View.GONE);
- mRecyclerView.setVisibility(View.VISIBLE);
- final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
- mRecyclerView.setLayoutManager(linearLayoutManager);
- final ElementAdapterDetails adapter = new ElementAdapterDetails(this, new ArrayList<>(node.getElements().values()));
- adapter.setOnItemClickListener(this);
- mRecyclerView.setAdapter(adapter);
- }
}
@Override
public boolean onOptionsItemSelected(final MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
+ if (item.getItemId() == android.R.id.home) {
+ onBackPressed();
+ return true;
}
return false;
}
@@ -189,24 +169,19 @@ public void onBackPressed() {
super.onBackPressed();
}
- @Override
- public void onItemClick(final int position) {
- mRecyclerView.scrollToPosition(position);
- }
-
/**
* Returns a String representation of the features
*/
- private String parseFeatures(final Features features){
+ private String parseFeatures(final Features features) {
return "Friend feature " + parseFeature(features.isFriendFeatureSupported()) + ", " +
"Low power feature " + parseFeature(features.isLowPowerFeatureSupported()) + ", " +
"Proxy feature " + parseFeature(features.isProxyFeatureSupported()) + ", " +
"Relay feature " + parseFeature(features.isRelayFeatureSupported());
}
- public String parseFeature(final boolean isSupported){
- if(isSupported){
+ public String parseFeature(final boolean isSupported) {
+ if (isSupported) {
return "supported";
} else {
return "unsupported";
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/PublicationSettingsActivity.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/PublicationSettingsActivity.java
new file mode 100644
index 000000000..adb365c74
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/PublicationSettingsActivity.java
@@ -0,0 +1,557 @@
+package no.nordicsemi.android.nrfmeshprovisioner.node;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.ScrollView;
+import android.widget.SeekBar;
+import android.widget.Switch;
+import android.widget.TextView;
+
+import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+import java.util.UUID;
+
+import javax.inject.Inject;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.Toolbar;
+import androidx.coordinatorlayout.widget.CoordinatorLayout;
+import androidx.lifecycle.ViewModelProvider;
+import androidx.lifecycle.ViewModelProviders;
+import butterknife.BindView;
+import butterknife.ButterKnife;
+import no.nordicsemi.android.meshprovisioner.ApplicationKey;
+import no.nordicsemi.android.meshprovisioner.Group;
+import no.nordicsemi.android.meshprovisioner.MeshNetwork;
+import no.nordicsemi.android.meshprovisioner.transport.ConfigModelPublicationSet;
+import no.nordicsemi.android.meshprovisioner.transport.ConfigModelPublicationVirtualAddressSet;
+import no.nordicsemi.android.meshprovisioner.transport.Element;
+import no.nordicsemi.android.meshprovisioner.transport.MeshMessage;
+import no.nordicsemi.android.meshprovisioner.transport.MeshModel;
+import no.nordicsemi.android.meshprovisioner.transport.ProvisionedMeshNode;
+import no.nordicsemi.android.meshprovisioner.transport.PublicationSettings;
+import no.nordicsemi.android.meshprovisioner.utils.AddressType;
+import no.nordicsemi.android.meshprovisioner.utils.MeshAddress;
+import no.nordicsemi.android.meshprovisioner.utils.MeshParserUtils;
+import no.nordicsemi.android.nrfmeshprovisioner.GroupCallbacks;
+import no.nordicsemi.android.nrfmeshprovisioner.R;
+import no.nordicsemi.android.nrfmeshprovisioner.di.Injectable;
+import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentError;
+import no.nordicsemi.android.nrfmeshprovisioner.keys.AppKeysActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.node.dialog.DialogFragmentPublishAddress;
+import no.nordicsemi.android.nrfmeshprovisioner.node.dialog.DialogFragmentPublishTtl;
+import no.nordicsemi.android.nrfmeshprovisioner.utils.Utils;
+import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.PublicationViewModel;
+
+public class PublicationSettingsActivity extends AppCompatActivity implements Injectable,
+ GroupCallbacks,
+ DialogFragmentPublishAddress.DialogFragmentPublicationListener,
+ DialogFragmentPublishTtl.DialogFragmentPublishTtlListener {
+
+ public static final int SET_PUBLICATION_SETTINGS = 2021;
+ public static final String RESULT_LABEL_UUID = "RESULT_LABEL_UUID";
+ public static final String RESULT_PUBLISH_ADDRESS = "RESULT_PUBLISH_ADDRESS";
+ public static final String RESULT_APP_KEY_INDEX = "RESULT_APP_KEY_INDEX";
+ public static final String RESULT_CREDENTIAL_FLAG = "RESULT_CREDENTIAL_FLAG";
+ public static final String RESULT_PUBLISH_TTL = "RESULT_PUBLISH_TTL";
+ public static final String RESULT_PUBLICATION_STEPS = "RESULT_PUBLICATION_STEPS";
+ public static final String RESULT_PUBLICATION_RESOLUTION = "RESULT_PUBLICATION_RESOLUTION";
+ public static final String RESULT_PUBLISH_RETRANSMIT_COUNT = "RESULT_PUBLISH_RETRANSMIT_COUNT";
+ public static final String RESULT_PUBLISH_RETRANSMIT_INTERVAL_STEPS = "RESULT_PUBLISH_RETRANSMIT_INTERVAL_STEPS";
+
+ private static final int DEFAULT_PUB_RETRANSMIT_COUNT = 1;
+ private static final int DEFAULT_PUB_RETRANSMIT_INTERVAL_STEPS = 1;
+ private static final int DEFAULT_PUBLICATION_STEPS = 0;
+ @SuppressWarnings("unused")
+ private static final int DEFAULT_PUBLICATION_RESOLUTION = MeshParserUtils.RESOLUTION_100_MS;
+
+ private PublicationViewModel mViewModel;
+ private MeshModel mMeshModel;
+ private UUID mLabelUUID;
+ private int mPublishAddress;
+ private Integer mAppKeyIndex;
+ private int mPublishTtl = MeshParserUtils.USE_DEFAULT_TTL;
+ private int mPublicationSteps = DEFAULT_PUBLICATION_STEPS;
+ private int mPublicationResolution;
+ private int mRetransmitCount = DEFAULT_PUB_RETRANSMIT_COUNT;
+ private int mRetransmitIntervalSteps = DEFAULT_PUB_RETRANSMIT_INTERVAL_STEPS;
+
+ @Inject
+ ViewModelProvider.Factory mViewModelFactory;
+
+ @BindView(R.id.container)
+ CoordinatorLayout mContainer;
+ @BindView(R.id.publish_address)
+ TextView mPublishAddressView;
+ @BindView(R.id.retransmit_count)
+ TextView mRetransmitCountView;
+ @BindView(R.id.retransmit_interval)
+ TextView mRetransmitInterval;
+ @BindView(R.id.app_key)
+ TextView mAppKeyView;
+ @BindView(R.id.publication_ttl)
+ TextView mPublishTtlView;
+ @BindView(R.id.friendship_credential_flag)
+ Switch mActionFriendshipCredentialSwitch;
+ @BindView(R.id.retransmission_seek_bar)
+ SeekBar mRetransmissionCountSeekBar;
+ @BindView(R.id.interval_steps_seek_bar)
+ SeekBar mRetransmitIntervalSeekBar;
+ @BindView(R.id.publish_interval_seek_bar)
+ SeekBar mPublicationIntervalSeekBar;
+ @BindView(R.id.pub_interval)
+ TextView mPublicationInterval;
+ @BindView(R.id.fab_apply)
+ ExtendedFloatingActionButton fabApply;
+
+ private boolean mIsConnected;
+
+ @SuppressWarnings("ConstantConditions")
+ @Override
+ protected void onCreate(@Nullable final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_publication_settings);
+ ButterKnife.bind(this);
+
+ mViewModel = ViewModelProviders.of(this, mViewModelFactory).get(PublicationViewModel.class);
+
+ final MeshModel meshModel = mMeshModel = mViewModel.getSelectedModel().getValue();
+ if (meshModel == null)
+ finish();
+
+ //Setup views
+ final Toolbar toolbar = findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+ //noinspection ConstantConditions
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+ getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_close_white_24dp);
+ getSupportActionBar().setTitle(R.string.title_publication_settings);
+
+ final ScrollView scrollView = findViewById(R.id.scroll_view);
+ final View actionPublishAddress = findViewById(R.id.container_publish_address);
+ final View actionKeyIndex = findViewById(R.id.container_app_key_index);
+ final View actionPublishTtl = findViewById(R.id.container_publication_ttl);
+
+ scrollView.getViewTreeObserver().addOnScrollChangedListener(() -> {
+ if (scrollView.getScrollY() == 0) {
+ fabApply.extend(true);
+ } else {
+ fabApply.shrink(true);
+ }
+ });
+
+ actionPublishAddress.setOnClickListener(v -> {
+ List groups = mViewModel.getNetworkLiveData().getMeshNetwork().getGroups();
+ final DialogFragmentPublishAddress fragmentPublishAddress = DialogFragmentPublishAddress.
+ newInstance(meshModel.getPublicationSettings(), new ArrayList<>(groups));
+ fragmentPublishAddress.show(getSupportFragmentManager(), null);
+ });
+
+ actionKeyIndex.setOnClickListener(v -> {
+ final Intent bindAppKeysIntent = new Intent(this, AppKeysActivity.class);
+ bindAppKeysIntent.putExtra(Utils.EXTRA_DATA, Utils.PUBLICATION_APP_KEY);
+ startActivityForResult(bindAppKeysIntent, Utils.SELECT_KEY);
+ });
+
+ actionPublishTtl.setOnClickListener(v -> {
+ if (meshModel != null) {
+ if (meshModel.getPublicationSettings() != null) {
+ final DialogFragmentPublishTtl fragmentPublishTtl = DialogFragmentPublishTtl
+ .newInstance(meshModel.getPublicationSettings().getPublishTtl());
+ fragmentPublishTtl.show(getSupportFragmentManager(), null);
+ } else {
+ final DialogFragmentPublishTtl fragmentPublishTtl = DialogFragmentPublishTtl
+ .newInstance(MeshParserUtils.USE_DEFAULT_TTL);
+ fragmentPublishTtl.show(getSupportFragmentManager(), null);
+ }
+ }
+ });
+
+ mPublicationIntervalSeekBar.setMax(234);
+ mPublicationIntervalSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
+ int lastValue = 0;
+
+ @Override
+ public void onProgressChanged(final SeekBar seekBar, final int progress, final boolean fromUser) {
+ if (progress == 0) {
+ lastValue = progress;
+ mPublicationSteps = progress;
+ mPublicationResolution = 0;
+ mPublicationInterval.setText(R.string.disabled);
+ } else if (progress >= 1 && progress <= 63) {
+ lastValue = progress;
+ mPublicationResolution = 0;
+ mPublicationSteps = progress;
+ mPublicationInterval.setText(getString(R.string.time_ms, PublicationSettings.getPublishPeriod(mPublicationResolution, mPublicationSteps)));
+ } else if (progress >= 64 && progress <= 120) {
+ if (progress > lastValue) {
+ mPublicationSteps = progress - 57;
+ lastValue = progress;
+ } else if (progress < lastValue) {
+ mPublicationSteps = -(57 - progress);
+ }
+ mPublicationResolution = 1;
+ mPublicationInterval.setText(getString(R.string.time_s, PublicationSettings.getPublishPeriod(mPublicationResolution, mPublicationSteps)));
+ } else if (progress >= 121 && progress <= 177) {
+ if (progress > lastValue) {
+ mPublicationSteps = progress - 114;
+ lastValue = progress;
+ } else if (progress < lastValue) {
+ mPublicationSteps = -(114 - progress);
+ }
+ mPublicationResolution = 2;
+ mPublicationInterval.setText(getString(R.string.time_s, PublicationSettings.getPublishPeriod(mPublicationResolution, mPublicationSteps)));
+ } else if (progress >= 178 && progress <= 234) {
+ if (progress >= lastValue) {
+ mPublicationSteps = progress - 171;
+ lastValue = progress;
+ } else {
+ mPublicationSteps = -(171 - progress);
+ }
+ mPublicationResolution = 3;
+ mPublicationInterval.setText(getString(R.string.time_m, PublicationSettings.getPublishPeriod(mPublicationResolution, mPublicationSteps)));
+ }
+ }
+
+ @Override
+ public void onStartTrackingTouch(final SeekBar seekBar) {
+
+ }
+
+ @Override
+ public void onStopTrackingTouch(final SeekBar seekBar) {
+
+ }
+ });
+
+ mRetransmissionCountSeekBar.setMax(PublicationSettings.MAX_PUBLICATION_RETRANSMIT_COUNT);
+ mRetransmissionCountSeekBar.incrementProgressBy(1);
+ mRetransmissionCountSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
+ @Override
+ public void onProgressChanged(final SeekBar seekBar, final int progress, final boolean fromUser) {
+ if (fromUser) {
+ mRetransmitCount = progress;
+ }
+ if (progress == 0) {
+ mRetransmitCountView.setText(R.string.disabled);
+ mRetransmitInterval.setText(R.string.disabled);
+ mRetransmitIntervalSeekBar.setEnabled(false);
+ } else {
+ if (!mRetransmitIntervalSeekBar.isEnabled())
+ mRetransmitIntervalSeekBar.setEnabled(true);
+ mRetransmitInterval.setText(getString(R.string.time_ms, PublicationSettings.
+ parseRetransmitIntervalSteps(mRetransmitIntervalSeekBar.getProgress())));
+ mRetransmitCountView.setText(getResources().getQuantityString(R.plurals.retransmit_count,
+ progress, mRetransmitCount));
+ }
+ }
+
+ @Override
+ public void onStartTrackingTouch(final SeekBar seekBar) {
+
+ }
+
+ @Override
+ public void onStopTrackingTouch(final SeekBar seekBar) {
+ }
+ });
+
+ mRetransmitIntervalSeekBar.setMax(PublicationSettings.getMaxRetransmissionInterval());
+ mRetransmitIntervalSeekBar.incrementProgressBy(1);
+ mRetransmitIntervalSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
+ @Override
+ public void onProgressChanged(final SeekBar seekBar, final int progress, final boolean fromUser) {
+ mRetransmitInterval.setText(getString(R.string.time_ms, progress));
+ if (fromUser) {
+ mRetransmitIntervalSteps = PublicationSettings.parseRetransmitIntervalSteps(progress);
+ }
+ }
+
+ @Override
+ public void onStartTrackingTouch(final SeekBar seekBar) {
+
+ }
+
+ @Override
+ public void onStopTrackingTouch(final SeekBar seekBar) {
+ }
+ });
+
+ fabApply.setOnClickListener(v -> {
+ if (!checkConnectivity()) return;
+ setPublication();
+ });
+
+ mViewModel.isConnectedToProxy().observe(this, isConnected -> {
+ if (isConnected != null) {
+ mIsConnected = isConnected;
+ }
+ invalidateOptionsMenu();
+ });
+
+ if (savedInstanceState == null) {
+ //noinspection ConstantConditions
+ updatePublicationValues(meshModel);
+ }
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(final Menu menu) {
+ if (mIsConnected) {
+ getMenuInflater().inflate(R.menu.disconnect, menu);
+ } else {
+ getMenuInflater().inflate(R.menu.connect, menu);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(final MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ case R.id.action_connect:
+ mViewModel.navigateToScannerActivity(this, false, Utils.CONNECT_TO_NETWORK, false);
+ return true;
+ case R.id.action_disconnect:
+ mViewModel.disconnect();
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ @Override
+ public void onBackPressed() {
+ super.onBackPressed();
+ }
+
+ @Override
+ protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ if (requestCode == Utils.SELECT_KEY) {
+ if (resultCode == RESULT_OK) {
+ final ApplicationKey appKey = data.getParcelableExtra(AppKeysActivity.RESULT_APP_KEY);
+ if (appKey != null) {
+ mAppKeyIndex = appKey.getKeyIndex();
+ mAppKeyView.setText(getString(R.string.app_key_index, appKey.getKeyIndex()));
+ }
+ }
+ }
+ }
+
+ @Override
+ protected void onSaveInstanceState(@NonNull final Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putSerializable(RESULT_LABEL_UUID, mLabelUUID);
+ outState.putInt(RESULT_PUBLISH_ADDRESS, mPublishAddress);
+ outState.putInt(RESULT_APP_KEY_INDEX, mAppKeyIndex);
+ outState.putBoolean(RESULT_CREDENTIAL_FLAG, mActionFriendshipCredentialSwitch.isChecked());
+ outState.putInt(RESULT_PUBLISH_TTL, mPublishTtl);
+ outState.putInt(RESULT_PUBLICATION_STEPS, mPublicationSteps);
+ outState.putInt(RESULT_PUBLICATION_RESOLUTION, mPublicationResolution);
+ outState.putInt(RESULT_PUBLISH_RETRANSMIT_COUNT, mRetransmitCount);
+ outState.putInt(RESULT_PUBLISH_RETRANSMIT_INTERVAL_STEPS, mRetransmitIntervalSteps);
+ }
+
+ @Override
+ protected void onRestoreInstanceState(final Bundle savedInstanceState) {
+ super.onRestoreInstanceState(savedInstanceState);
+ mLabelUUID = (UUID) savedInstanceState.getSerializable(RESULT_LABEL_UUID);
+ mPublishAddress = savedInstanceState.getInt(RESULT_PUBLISH_ADDRESS);
+ mAppKeyIndex = savedInstanceState.getInt(RESULT_APP_KEY_INDEX);
+ mPublishTtl = savedInstanceState.getInt(RESULT_PUBLISH_TTL);
+ mPublicationSteps = savedInstanceState.getInt(RESULT_PUBLICATION_STEPS);
+ mPublicationResolution = savedInstanceState.getInt(RESULT_PUBLICATION_RESOLUTION);
+ mRetransmitCount = savedInstanceState.getInt(RESULT_PUBLISH_RETRANSMIT_COUNT);
+ mRetransmitIntervalSteps = savedInstanceState.getInt(RESULT_PUBLISH_RETRANSMIT_INTERVAL_STEPS);
+ updateUi(savedInstanceState.getBoolean(RESULT_CREDENTIAL_FLAG));
+ }
+
+ @Override
+ public Group createGroup(@NonNull final String name) {
+ final MeshNetwork network = mViewModel.getNetworkLiveData().getMeshNetwork();
+ if (network != null) {
+ return network.createGroup(network.getSelectedProvisioner(), name);
+ }
+ return null;
+ }
+
+ @Override
+ public Group createGroup(@NonNull final UUID uuid, final String name) {
+ final MeshNetwork network = mViewModel.getNetworkLiveData().getMeshNetwork();
+ if (network != null) {
+ return network.createGroup(uuid, null, name);
+ }
+ return null;
+ }
+
+ @Override
+ public boolean onGroupAdded(@NonNull final Group group) {
+ final MeshNetwork network = mViewModel.getNetworkLiveData().getMeshNetwork();
+ if (network != null) {
+ if (network.addGroup(group)) {
+ onPublishAddressSet(group);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean onGroupAdded(@NonNull final String name, final int address) {
+ final MeshNetwork network = mViewModel.getNetworkLiveData().getMeshNetwork();
+ if (network != null) {
+ final Group group = network.createGroup(network.getSelectedProvisioner(), address, name);
+ if (group != null) {
+ if (network.addGroup(group)) {
+ onPublishAddressSet(group);
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void onPublishAddressSet(final int address) {
+ mLabelUUID = null;
+ mPublishAddress = address;
+ mPublishAddressView.setText(MeshAddress.formatAddress(address, true));
+ }
+
+ @Override
+ public void onPublishAddressSet(@NonNull final Group group) {
+ mLabelUUID = group.getAddressLabel();
+ mPublishAddress = group.getAddress();
+ mPublishAddressView.setText(MeshAddress.formatAddress(group.getAddress(), true));
+ }
+
+ @Override
+ public void setPublishTtl(final int ttl) {
+ mPublishTtl = ttl;
+ updateTtlUi(ttl);
+ }
+
+ private void updatePublicationValues(@NonNull final MeshModel model) {
+ final PublicationSettings publicationSettings = model.getPublicationSettings();
+
+ //Default app key index to the 0th key in the list of bound app keys
+ if (!model.getBoundAppKeyIndexes().isEmpty()) {
+ mAppKeyIndex = mMeshModel.getBoundAppKeyIndexes().get(0);
+ }
+
+ if (publicationSettings != null) {
+ mPublishAddress = publicationSettings.getPublishAddress();
+ mLabelUUID = publicationSettings.getLabelUUID();
+
+ mActionFriendshipCredentialSwitch.setChecked(publicationSettings.getCredentialFlag());
+ mPublishTtl = publicationSettings.getPublishTtl();
+
+ mPublicationSteps = publicationSettings.getPublicationSteps();
+ mPublicationResolution = publicationSettings.getPublicationResolution();
+
+ mRetransmitCount = publicationSettings.getPublishRetransmitCount();
+ mRetransmitIntervalSteps = publicationSettings.getPublishRetransmitIntervalSteps();
+
+ if (!model.getBoundAppKeyIndexes().isEmpty()) {
+ mAppKeyIndex = publicationSettings.getAppKeyIndex();
+ }
+ updateUi(publicationSettings.getCredentialFlag());
+ }
+ updateTtlUi(mPublishTtl);
+ }
+
+ private void updateUi(final boolean credentialFlag) {
+ if (mLabelUUID == null) {
+ mPublishAddressView.setText(MeshAddress.formatAddress(mPublishAddress, true));
+ } else {
+ mPublishAddressView.setText(mLabelUUID.toString().toUpperCase(Locale.US));
+ }
+
+ if (MeshAddress.isValidUnassignedAddress(mPublishAddress)) {
+ mPublishAddressView.setText(R.string.not_assigned);
+ } else {
+ mPublishAddressView.setText(MeshAddress.formatAddress(mPublishAddress, true));
+ }
+ final MeshNetwork network = mViewModel.getNetworkLiveData().getMeshNetwork();
+ mAppKeyView.setText(getString(R.string.app_key_index, mAppKeyIndex));
+ if (network != null) {
+ final ApplicationKey key = network.getAppKey(mAppKeyIndex);
+ if (key != null) {
+ mAppKeyView.setText(getString(R.string.app_key_name_and_index, key.getName(), mAppKeyIndex));
+ } else {
+ mAppKeyView.setText(getString(R.string.unavailable));
+ }
+ } else {
+ mAppKeyView.setText(getString(R.string.unavailable));
+ }
+
+ mActionFriendshipCredentialSwitch.setChecked(credentialFlag);
+
+ final int period = PublicationSettings.getPublishPeriod(mPublicationResolution, mPublicationSteps);
+ mPublicationIntervalSeekBar.setProgress(mPublicationSteps);
+ mPublicationInterval.setText(getString(R.string.time_ms, period));
+
+ mRetransmissionCountSeekBar.setProgress(mRetransmitCount);
+ final int retransmissionInterval = PublicationSettings.getRetransmissionInterval(mRetransmitIntervalSteps);
+ mRetransmitIntervalSeekBar.setProgress(retransmissionInterval);
+
+ }
+
+ private void updateTtlUi(final int ttl) {
+ if (MeshParserUtils.isDefaultPublishTtl(ttl)) {
+ mPublishTtlView.setText(getString(R.string.uses_default_ttl));
+ } else {
+ mPublishTtlView.setText(String.valueOf(ttl));
+ }
+ }
+
+ private void setPublication() {
+ final ProvisionedMeshNode node = mViewModel.getSelectedMeshNode().getValue();
+ final Element element = mViewModel.getSelectedElement().getValue();
+ final MeshModel model = mViewModel.getSelectedModel().getValue();
+ final MeshMessage configModelPublicationSet;
+ if (node != null && element != null && model != null) {
+ final AddressType type = MeshAddress.getAddressType(mPublishAddress);
+ if (type != null && type != AddressType.VIRTUAL_ADDRESS) {
+ configModelPublicationSet = new ConfigModelPublicationSet(element.getElementAddress(),
+ mPublishAddress, mAppKeyIndex, mActionFriendshipCredentialSwitch.isChecked(), mPublishTtl,
+ mPublicationSteps, mPublicationResolution, mRetransmitCount, mRetransmitIntervalSteps, model.getModelId());
+ } else {
+ configModelPublicationSet = new ConfigModelPublicationVirtualAddressSet(element.getElementAddress(),
+ mLabelUUID, mAppKeyIndex, mActionFriendshipCredentialSwitch.isChecked(), mPublishTtl,
+ mPublicationSteps, mPublicationResolution, mRetransmitCount, mRetransmitIntervalSteps, model.getModelId());
+ }
+ try {
+ mViewModel.getMeshManagerApi().createMeshPdu(node.getUnicastAddress(), configModelPublicationSet);
+ } catch (IllegalArgumentException ex) {
+ final DialogFragmentError message = DialogFragmentError.
+ newInstance(getString(R.string.title_error), ex.getMessage());
+ message.show(getSupportFragmentManager(), null);
+ return;
+ }
+ }
+ final Intent returnIntent = new Intent();
+ setResult(Activity.RESULT_OK, returnIntent);
+ finish();
+ }
+
+ protected final boolean checkConnectivity() {
+ if (!mIsConnected) {
+ mViewModel.displayDisconnectedSnackBar(this, mContainer);
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/VendorModelActivity.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/VendorModelActivity.java
similarity index 92%
rename from Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/VendorModelActivity.java
rename to Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/VendorModelActivity.java
index a4bfd120d..d1a489cbf 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/VendorModelActivity.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/VendorModelActivity.java
@@ -1,10 +1,10 @@
-package no.nordicsemi.android.nrfmeshprovisioner;
+package no.nordicsemi.android.nrfmeshprovisioner.node;
-import android.arch.lifecycle.ViewModelProvider;
+import androidx.lifecycle.ViewModelProvider;
import android.os.Bundle;
-import android.support.constraint.ConstraintLayout;
-import android.support.design.widget.TextInputEditText;
-import android.support.design.widget.TextInputLayout;
+import androidx.constraintlayout.widget.ConstraintLayout;
+import com.google.android.material.textfield.TextInputEditText;
+import com.google.android.material.textfield.TextInputLayout;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
@@ -19,6 +19,7 @@
import javax.inject.Inject;
import no.nordicsemi.android.meshprovisioner.models.VendorModel;
+import no.nordicsemi.android.meshprovisioner.ApplicationKey;
import no.nordicsemi.android.meshprovisioner.transport.Element;
import no.nordicsemi.android.meshprovisioner.transport.MeshMessage;
import no.nordicsemi.android.meshprovisioner.transport.MeshModel;
@@ -26,6 +27,7 @@
import no.nordicsemi.android.meshprovisioner.transport.VendorModelMessageStatus;
import no.nordicsemi.android.meshprovisioner.transport.VendorModelMessageUnacked;
import no.nordicsemi.android.meshprovisioner.utils.MeshParserUtils;
+import no.nordicsemi.android.nrfmeshprovisioner.R;
import no.nordicsemi.android.nrfmeshprovisioner.utils.HexKeyListener;
import no.nordicsemi.android.nrfmeshprovisioner.utils.Utils;
@@ -96,8 +98,8 @@ public void afterTextChanged(final Editable s) {
actionSend.setOnClickListener(v -> {
messageContainer.setVisibility(View.GONE);
receivedMessage.setText("");
- final String opCode = opCodeEditText.getText().toString().trim();
- final String parameters = parametersEditText.getText().toString().trim();
+ final String opCode = opCodeEditText.getEditableText().toString().trim();
+ final String parameters = parametersEditText.getEditableText().toString().trim();
if (!validateOpcode(opCode, opCodeLayout))
return;
@@ -212,14 +214,14 @@ public void sendVendorModelMessage(final int opcode, final byte[] parameters, fi
final VendorModel model = (VendorModel) mViewModel.getSelectedModel().getValue();
if (model != null) {
final int appKeyIndex = model.getBoundAppKeyIndexes().get(0);
- final byte[] appKey = model.getBoundAppKey(appKeyIndex).getKey();
+ final ApplicationKey appKey = mViewModel.getNetworkLiveData().getMeshNetwork().getAppKey(appKeyIndex);
final MeshMessage message;
if (acknowledged) {
message = new VendorModelMessageAcked(appKey, model.getModelId(), model.getCompanyIdentifier(), opcode, parameters);
} else {
message = new VendorModelMessageUnacked(appKey, model.getModelId(), model.getCompanyIdentifier(), opcode, parameters);
}
- mViewModel.getMeshManagerApi().sendMeshMessage(element.getElementAddress(), message);
+ sendMessage(element.getElementAddress(), message);
}
}
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/ElementAdapter.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/adapter/ElementAdapter.java
similarity index 73%
rename from Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/ElementAdapter.java
rename to Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/adapter/ElementAdapter.java
index 9f27ff769..77eb2c35f 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/ElementAdapter.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/adapter/ElementAdapter.java
@@ -20,16 +20,13 @@
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package no.nordicsemi.android.nrfmeshprovisioner.adapter;
+package no.nordicsemi.android.nrfmeshprovisioner.node.adapter;
-import android.arch.lifecycle.LiveData;
import android.content.Context;
-import android.support.annotation.NonNull;
-import android.support.constraint.ConstraintLayout;
-import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -37,6 +34,11 @@
import java.util.ArrayList;
import java.util.List;
+import androidx.annotation.NonNull;
+import androidx.constraintlayout.widget.ConstraintLayout;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.lifecycle.LiveData;
+import androidx.recyclerview.widget.RecyclerView;
import butterknife.BindView;
import butterknife.ButterKnife;
import no.nordicsemi.android.meshprovisioner.models.VendorModel;
@@ -44,21 +46,18 @@
import no.nordicsemi.android.meshprovisioner.transport.MeshModel;
import no.nordicsemi.android.meshprovisioner.transport.ProvisionedMeshNode;
import no.nordicsemi.android.meshprovisioner.utils.CompositionDataParser;
-import no.nordicsemi.android.meshprovisioner.utils.MeshAddress;
-import no.nordicsemi.android.nrfmeshprovisioner.NodeConfigurationActivity;
import no.nordicsemi.android.nrfmeshprovisioner.R;
public class ElementAdapter extends RecyclerView.Adapter {
private final Context mContext;
private final List mElements = new ArrayList<>();
- private final String TAG = ElementAdapter.class.getSimpleName();
private OnItemClickListener mOnItemClickListener;
private ProvisionedMeshNode mProvisionedMeshNode;
- public ElementAdapter(final NodeConfigurationActivity nodeConfigurationActivity, final LiveData meshNodeLiveData) {
- this.mContext = nodeConfigurationActivity.getApplicationContext();
- meshNodeLiveData.observe(nodeConfigurationActivity, meshNode -> {
+ public ElementAdapter(@NonNull final Context context, @NonNull final LiveData meshNodeLiveData) {
+ this.mContext = context.getApplicationContext();
+ meshNodeLiveData.observe((LifecycleOwner) context, meshNode -> {
if (meshNode != null) {
mProvisionedMeshNode = meshNode;
mElements.clear();
@@ -69,7 +68,7 @@ public ElementAdapter(final NodeConfigurationActivity nodeConfigurationActivity,
}
- public void setOnItemClickListener(final ElementAdapter.OnItemClickListener listener) {
+ public void setOnItemClickListener(@NonNull final ElementAdapter.OnItemClickListener listener) {
mOnItemClickListener = listener;
}
@@ -83,24 +82,23 @@ public ViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int
@Override
public void onBindViewHolder(@NonNull final ViewHolder holder, final int position) {
final Element element = mElements.get(position);
- holder.mElementContainer.setTag(element.getElementAddress());
final int modelCount = element.getMeshModels().size();
- holder.mElementTitle.setText(mContext.getString(R.string.element_address, MeshAddress.formatAddress(element.getElementAddress(), true)));
+ holder.mElementTitle.setText(element.getName());
holder.mElementSubtitle.setText(mContext.getString(R.string.model_count, modelCount));
final List models = new ArrayList<>(element.getMeshModels().values());
inflateModelViews(holder, models);
}
-
private void inflateModelViews(final ViewHolder holder, final List models) {
//Remove all child views to avoid duplicating
holder.mModelContainer.removeAllViews();
- for (MeshModel model : models) {
+ for (int i = 0; i < models.size(); i++) {
+ final MeshModel model = models.get(i);
final View modelView = LayoutInflater.from(mContext).inflate(R.layout.model_item, holder.mElementContainer, false);
modelView.setTag(model.getModelId());
- final TextView modelNameView = modelView.findViewById(R.id.address);
- final TextView modelIdView = modelView.findViewById(R.id.model_id);
+ final TextView modelNameView = modelView.findViewById(R.id.title);
+ final TextView modelIdView = modelView.findViewById(R.id.subtitle);
modelNameView.setText(model.getModelName());
if (model instanceof VendorModel) {
modelIdView.setText(mContext.getString(R.string.format_vendor_model_id, CompositionDataParser.formatModelIdentifier(model.getModelId(), true)));
@@ -111,8 +109,7 @@ private void inflateModelViews(final ViewHolder holder, final List mo
modelView.setOnClickListener(v -> {
final int position = holder.getAdapterPosition();
final Element element = mElements.get(position);
- final MeshModel model1 = element.getMeshModels().get(v.getTag());
- mOnItemClickListener.onElementItemClick(mProvisionedMeshNode, element, model1);
+ mOnItemClickListener.onModelClicked(mProvisionedMeshNode, element, model);
});
holder.mModelContainer.addView(modelView);
}
@@ -132,9 +129,10 @@ public boolean isEmpty() {
return getItemCount() == 0;
}
- @FunctionalInterface
public interface OnItemClickListener {
- void onElementItemClick(final ProvisionedMeshNode meshNode, final Element element, final MeshModel model);
+ void onElementClicked(@NonNull final Element element);
+
+ void onModelClicked(@NonNull final ProvisionedMeshNode meshNode, @NonNull final Element element, @NonNull final MeshModel model);
}
final class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
@@ -147,31 +145,31 @@ final class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickLi
@BindView(R.id.element_subtitle)
TextView mElementSubtitle;
@BindView(R.id.element_expand)
- ImageView mElementExpand;
+ ImageButton mElementExpand;
+ @BindView(R.id.edit)
+ ImageButton mEdit;
@BindView(R.id.model_container)
LinearLayout mModelContainer;
private ViewHolder(final View view) {
super(view);
ButterKnife.bind(this, view);
- mElementContainer.setOnClickListener(this);
-
+ mElementExpand.setOnClickListener(this);
+ mEdit.setOnClickListener(this);
}
@Override
public void onClick(final View v) {
- switch (v.getId()) {
- case R.id.element_item_container:
- if (mModelContainer.getVisibility() == View.VISIBLE) {
- mElementExpand.setImageResource(R.drawable.ic_round_expand_more_black_alpha_24dp);
- mModelContainer.setVisibility(View.GONE);
- } else {
- mElementExpand.setImageResource(R.drawable.ic_round_expand_less_black_alpha_24dp);
- mModelContainer.setVisibility(View.VISIBLE);
- }
- break;
- default:
- break;
+ if (v.getId() == R.id.element_expand) {
+ if (mModelContainer.getVisibility() == View.VISIBLE) {
+ mElementExpand.setImageResource(R.drawable.ic_round_expand_more_black_alpha_24dp);
+ mModelContainer.setVisibility(View.GONE);
+ } else {
+ mElementExpand.setImageResource(R.drawable.ic_round_expand_less_black_alpha_24dp);
+ mModelContainer.setVisibility(View.VISIBLE);
+ }
+ } else if (v.getId() == R.id.edit) {
+ mOnItemClickListener.onElementClicked(mElements.get(getAdapterPosition()));
}
}
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/NodeAdapter.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/adapter/NodeAdapter.java
similarity index 61%
rename from Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/NodeAdapter.java
rename to Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/adapter/NodeAdapter.java
index 90808fb39..624eff14a 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/adapter/NodeAdapter.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/adapter/NodeAdapter.java
@@ -20,13 +20,9 @@
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package no.nordicsemi.android.nrfmeshprovisioner.adapter;
+package no.nordicsemi.android.nrfmeshprovisioner.node.adapter;
-import android.arch.lifecycle.LiveData;
-import android.support.annotation.NonNull;
-import android.support.v4.app.FragmentActivity;
-import android.support.v7.widget.AppCompatImageButton;
-import android.support.v7.widget.RecyclerView;
+import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -37,33 +33,38 @@
import java.util.List;
import java.util.Map;
+import androidx.annotation.NonNull;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.lifecycle.LiveData;
+import androidx.recyclerview.widget.RecyclerView;
import butterknife.BindView;
import butterknife.ButterKnife;
import no.nordicsemi.android.meshprovisioner.transport.Element;
import no.nordicsemi.android.meshprovisioner.transport.ProvisionedMeshNode;
-import no.nordicsemi.android.meshprovisioner.utils.AddressUtils;
import no.nordicsemi.android.meshprovisioner.utils.CompanyIdentifiers;
+import no.nordicsemi.android.meshprovisioner.utils.MeshAddress;
import no.nordicsemi.android.meshprovisioner.utils.MeshParserUtils;
import no.nordicsemi.android.nrfmeshprovisioner.R;
+import no.nordicsemi.android.nrfmeshprovisioner.widgets.RemovableViewHolder;
public class NodeAdapter extends RecyclerView.Adapter {
- private Integer mUnicastAddress;
- private int mNodeIndex = -1;
- private final FragmentActivity mContext;
+ private final Context mContext;
private final List mNodes = new ArrayList<>();
private OnItemClickListener mOnItemClickListener;
- public NodeAdapter(final FragmentActivity fragmentActivity, LiveData> provisionedNodesLiveData) {
- this.mContext = fragmentActivity;
- provisionedNodesLiveData.observe(fragmentActivity, provisionedNodes -> {
- if (provisionedNodes != null) {
+ public NodeAdapter(@NonNull final Context context,
+ @NonNull final LiveData> provisionedNodesLiveData) {
+ this.mContext = context;
+ provisionedNodesLiveData.observe((LifecycleOwner) context, nodes -> {
+ if (nodes != null) {
mNodes.clear();
- mNodes.addAll(provisionedNodes);
+ mNodes.addAll(nodes);
+ notifyDataSetChanged();
}
});
}
- public void setOnItemClickListener(final OnItemClickListener listener) {
+ public void setOnItemClickListener(@NonNull final OnItemClickListener listener) {
mOnItemClickListener = listener;
}
@@ -77,18 +78,25 @@ public ViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int
@Override
public void onBindViewHolder(@NonNull final ViewHolder holder, final int position) {
final ProvisionedMeshNode node = mNodes.get(position);
- holder.name.setText(node.getNodeName());
- holder.unicastAddress.setText(MeshParserUtils.bytesToHex(AddressUtils.getUnicastAddressBytes(node.getUnicastAddress()), false));
- final Map elements = node.getElements();
- if (!elements.isEmpty()) {
- holder.nodeInfoContainer.setVisibility(View.VISIBLE);
- holder.companyIdentifier.setText(CompanyIdentifiers.getCompanyName(node.getCompanyIdentifier().shortValue()));
- holder.elements.setText(String.valueOf(elements.size()));
- holder.models.setText(String.valueOf(getModels(elements)));
- } else {
- holder.companyIdentifier.setText(R.string.unknown);
- holder.elements.setText(String.valueOf(node.getNumberOfElements()));
- holder.models.setText(R.string.unknown);
+ if (node != null) {
+ holder.name.setText(node.getNodeName());
+ holder.unicastAddress.setText(MeshParserUtils.bytesToHex(MeshAddress.addressIntToBytes(node.getUnicastAddress()), false));
+ final Map elements = node.getElements();
+ if (!elements.isEmpty()) {
+ holder.nodeInfoContainer.setVisibility(View.VISIBLE);
+ if (node.getCompanyIdentifier() != null) {
+ holder.companyIdentifier.setText(CompanyIdentifiers.getCompanyName(node.getCompanyIdentifier().shortValue()));
+ } else {
+ holder.companyIdentifier.setText(R.string.unknown);
+ }
+ holder.elements.setText(String.valueOf(elements.size()));
+ holder.models.setText(String.valueOf(getModels(elements)));
+ } else {
+ holder.companyIdentifier.setText(R.string.unknown);
+ holder.elements.setText(String.valueOf(node.getNumberOfElements()));
+ holder.models.setText(R.string.unknown);
+ }
+ //holder.getSwipeableView().setTag(node);
}
}
@@ -97,6 +105,13 @@ public int getItemCount() {
return mNodes.size();
}
+ public ProvisionedMeshNode getItem(final int position) {
+ if (mNodes.size() > 0 && position > -1) {
+ return mNodes.get(position);
+ }
+ return null;
+ }
+
public boolean isEmpty() {
return getItemCount() == 0;
}
@@ -109,34 +124,12 @@ private int getModels(final Map elements) {
return models;
}
- public void selectConnectedMeshNode(final Integer unicastAddress) {
- if (unicastAddress != null) {
- final int index = mNodeIndex = getMeshNodeIndex(unicastAddress);
- if (index > -1) {
- notifyItemChanged(mNodeIndex);
- }
- } else {
- notifyItemChanged(mNodeIndex);
- }
- mUnicastAddress = unicastAddress;
- }
-
- private int getMeshNodeIndex(final int unicastAddress) {
- for (int i = 0; i < mNodes.size(); i++) {
- if (unicastAddress == mNodes.get(i).getUnicastAddress()) {
- return i;
- }
- }
- return -1;
- }
-
+ @FunctionalInterface
public interface OnItemClickListener {
void onConfigureClicked(final ProvisionedMeshNode node);
-
- void onDetailsClicked(final ProvisionedMeshNode node);
}
- final class ViewHolder extends RecyclerView.ViewHolder {
+ final class ViewHolder extends RemovableViewHolder {
@BindView(R.id.container)
FrameLayout container;
@@ -152,25 +145,13 @@ final class ViewHolder extends RecyclerView.ViewHolder {
TextView elements;
@BindView(R.id.models)
TextView models;
- @BindView(R.id.action_configure)
- AppCompatImageButton configure;
private ViewHolder(final View provisionedView) {
super(provisionedView);
ButterKnife.bind(this, provisionedView);
-
- configure.setOnClickListener(v -> {
-
- if (mOnItemClickListener != null) {
- mOnItemClickListener.onConfigureClicked(mNodes.get(getAdapterPosition()));
- }
-
- });
-
container.setOnClickListener(v -> {
-
if (mOnItemClickListener != null) {
- mOnItemClickListener.onDetailsClicked(mNodes.get(getAdapterPosition()));
+ mOnItemClickListener.onConfigureClicked(mNodes.get(getAdapterPosition()));
}
});
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/BottomSheetDetailsDialogFragment.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/dialog/BottomSheetDetailsDialogFragment.java
similarity index 88%
rename from Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/BottomSheetDetailsDialogFragment.java
rename to Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/dialog/BottomSheetDetailsDialogFragment.java
index 510ba703f..109aba4d4 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/BottomSheetDetailsDialogFragment.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/dialog/BottomSheetDetailsDialogFragment.java
@@ -1,15 +1,15 @@
-package no.nordicsemi.android.nrfmeshprovisioner;
+package no.nordicsemi.android.nrfmeshprovisioner.node.dialog;
import android.app.Activity;
-import android.arch.lifecycle.ViewModelProvider;
+import androidx.lifecycle.ViewModelProvider;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.design.widget.BottomSheetDialogFragment;
-import android.support.design.widget.TextInputEditText;
-import android.support.design.widget.TextInputLayout;
-import android.support.v7.widget.LinearLayoutManager;
-import android.support.v7.widget.RecyclerView;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
+import com.google.android.material.textfield.TextInputEditText;
+import com.google.android.material.textfield.TextInputLayout;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
@@ -24,6 +24,7 @@
import no.nordicsemi.android.meshprovisioner.Group;
import no.nordicsemi.android.meshprovisioner.transport.Element;
import no.nordicsemi.android.meshprovisioner.transport.MeshModel;
+import no.nordicsemi.android.nrfmeshprovisioner.R;
import no.nordicsemi.android.nrfmeshprovisioner.adapter.GroupModelAdapter;
public class BottomSheetDetailsDialogFragment extends BottomSheetDialogFragment implements GroupModelAdapter.OnItemClickListener {
@@ -84,7 +85,7 @@ public View onCreateView(@NonNull final LayoutInflater inflater, @Nullable final
final Button actionApply = rootView.findViewById(R.id.action_apply);
actionApply.setOnClickListener(v -> {
- final String groupName = mGroupNameTextInput.getEditableText().toString();
+ final String groupName = mGroupNameTextInput.getEditableText().toString().trim();
if (validateInput(groupName)) {
hideKeyboard();
mGroupNameTextInput.clearFocus();
@@ -114,7 +115,7 @@ private boolean validateInput(final String groupName) {
return !TextUtils.isEmpty(groupName);
}
- public void hideKeyboard() {
+ private void hideKeyboard() {
final InputMethodManager imm = (InputMethodManager) requireActivity().getSystemService(Activity.INPUT_METHOD_SERVICE);
if (imm != null) {
imm.hideSoftInputFromWindow(mGroupNameTextInput.getWindowToken(), 0);
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/BottomSheetLevelDialogFragment.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/dialog/BottomSheetLevelDialogFragment.java
similarity index 94%
rename from Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/BottomSheetLevelDialogFragment.java
rename to Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/dialog/BottomSheetLevelDialogFragment.java
index 504801cc6..cc8a6d681 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/BottomSheetLevelDialogFragment.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/dialog/BottomSheetLevelDialogFragment.java
@@ -1,9 +1,9 @@
-package no.nordicsemi.android.nrfmeshprovisioner;
+package no.nordicsemi.android.nrfmeshprovisioner.node.dialog;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.design.widget.BottomSheetDialogFragment;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -11,6 +11,7 @@
import android.widget.TextView;
import no.nordicsemi.android.meshprovisioner.utils.MeshParserUtils;
+import no.nordicsemi.android.nrfmeshprovisioner.R;
public class BottomSheetLevelDialogFragment extends BottomSheetDialogFragment {
private static final String KEY_INDEX = "KEY_INDEX";
@@ -20,7 +21,7 @@ public class BottomSheetLevelDialogFragment extends BottomSheetDialogFragment {
private int mTransitionStepResolution;
private int mTransitionSteps;
- interface BottomSheetLevelListener {
+ public interface BottomSheetLevelListener {
void toggleLevel(final int keyIndex, final int level, final int mTransitionSteps, final int mTransitionStepResolution, final int progress);
}
@@ -57,7 +58,7 @@ public View onCreateView(@NonNull final LayoutInflater inflater, @Nullable final
final TextView delayTime = nodeControlsContainer.findViewById(R.id.delay_time);
final TextView level = nodeControlsContainer.findViewById(R.id.level);
- final SeekBar levelSeekBar = nodeControlsContainer.findViewById(R.id.level_seekbar);
+ final SeekBar levelSeekBar = nodeControlsContainer.findViewById(R.id.level_seek_bar);
levelSeekBar.setProgress(0);
levelSeekBar.setMax(100);
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/BottomSheetOnOffDialogFragment.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/dialog/BottomSheetOnOffDialogFragment.java
similarity index 94%
rename from Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/BottomSheetOnOffDialogFragment.java
rename to Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/dialog/BottomSheetOnOffDialogFragment.java
index 5528bea51..0d244417b 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/BottomSheetOnOffDialogFragment.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/dialog/BottomSheetOnOffDialogFragment.java
@@ -1,9 +1,9 @@
-package no.nordicsemi.android.nrfmeshprovisioner;
+package no.nordicsemi.android.nrfmeshprovisioner.node.dialog;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.design.widget.BottomSheetDialogFragment;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -13,14 +13,15 @@
import android.widget.Toast;
import no.nordicsemi.android.meshprovisioner.utils.MeshParserUtils;
+import no.nordicsemi.android.nrfmeshprovisioner.R;
public class BottomSheetOnOffDialogFragment extends BottomSheetDialogFragment {
private static final String KEY_INDEX = "KEY_INDEX";
private int mKeyIndex;
- protected int mTransitionStepResolution;
- protected int mTransitionSteps;
+ private int mTransitionStepResolution;
+ private int mTransitionSteps;
- interface BottomSheetOnOffListener {
+ public interface BottomSheetOnOffListener {
void toggle(final int mKeyIndex, final boolean state, final int mTransitionSteps, final int mTransitionStepResolution, final int progress);
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/BottomSheetVendorDialogFragment.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/dialog/BottomSheetVendorDialogFragment.java
similarity index 92%
rename from Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/BottomSheetVendorDialogFragment.java
rename to Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/dialog/BottomSheetVendorDialogFragment.java
index bd2312130..6d8757767 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/BottomSheetVendorDialogFragment.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/dialog/BottomSheetVendorDialogFragment.java
@@ -1,11 +1,6 @@
-package no.nordicsemi.android.nrfmeshprovisioner;
+package no.nordicsemi.android.nrfmeshprovisioner.node.dialog;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.design.widget.BottomSheetDialogFragment;
-import android.support.design.widget.TextInputEditText;
-import android.support.design.widget.TextInputLayout;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
@@ -17,7 +12,14 @@
import android.widget.CheckBox;
import android.widget.TextView;
+import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
+import com.google.android.material.textfield.TextInputEditText;
+import com.google.android.material.textfield.TextInputLayout;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import no.nordicsemi.android.meshprovisioner.utils.MeshParserUtils;
+import no.nordicsemi.android.nrfmeshprovisioner.R;
import no.nordicsemi.android.nrfmeshprovisioner.utils.HexKeyListener;
import no.nordicsemi.android.nrfmeshprovisioner.utils.Utils;
@@ -31,7 +33,7 @@ public class BottomSheetVendorDialogFragment extends BottomSheetDialogFragment {
private View messageContainer;
private TextView receivedMessage;
- interface BottomSheetVendorModelControlsListener {
+ public interface BottomSheetVendorModelControlsListener {
void sendVendorModelMessage(final int modelId, final int keyIndex, final int opCode, final byte[] parameters, final boolean acknowledged);
}
@@ -109,8 +111,8 @@ public void afterTextChanged(final Editable s) {
actionSend.setOnClickListener(v -> {
messageContainer.setVisibility(View.GONE);
receivedMessage.setText("");
- final String opCode = opCodeEditText.getText().toString().trim();
- final String parameters = parametersEditText.getText().toString().trim();
+ final String opCode = opCodeEditText.getEditableText().toString().trim();
+ final String parameters = parametersEditText.getEditableText().toString().trim();
if (!validateOpcode(opCode, opCodeLayout))
return;
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/dialog/DialogFragmentElementName.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/dialog/DialogFragmentElementName.java
new file mode 100644
index 000000000..e6753ddc8
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/dialog/DialogFragmentElementName.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2018, Nordic Semiconductor
+ * 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 no.nordicsemi.android.nrfmeshprovisioner.node.dialog;
+
+import android.annotation.SuppressLint;
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.text.Editable;
+import android.text.TextUtils;
+import android.text.TextWatcher;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.TextView;
+
+import com.google.android.material.textfield.TextInputEditText;
+import com.google.android.material.textfield.TextInputLayout;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.DialogFragment;
+import butterknife.BindView;
+import butterknife.ButterKnife;
+import no.nordicsemi.android.meshprovisioner.transport.Element;
+import no.nordicsemi.android.nrfmeshprovisioner.R;
+
+public class DialogFragmentElementName extends DialogFragment {
+
+ private static final String ELEMENT = "ELEMENT";
+
+ //UI Bindings
+ @BindView(R.id.text_input_layout)
+ TextInputLayout elementNameInputLayout;
+ @BindView(R.id.text_input)
+ TextInputEditText elementNameInput;
+
+ private Element mElement;
+
+ public static DialogFragmentElementName newInstance(@NonNull final Element element) {
+ DialogFragmentElementName fragmentNetworkKey = new DialogFragmentElementName();
+ final Bundle args = new Bundle();
+ args.putParcelable(ELEMENT, element);
+ fragmentNetworkKey.setArguments(args);
+ return fragmentNetworkKey;
+ }
+
+ @Override
+ public void onCreate(@Nullable final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ if (getArguments() != null) {
+ mElement = getArguments().getParcelable(ELEMENT);
+ }
+ }
+
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(final Bundle savedInstanceState) {
+ @SuppressLint("InflateParams") final View rootView = LayoutInflater.from(getContext()).inflate(R.layout.dialog_fragment_name, null);
+
+ //Bind ui
+ ButterKnife.bind(this, rootView);
+ final TextView summary = rootView.findViewById(R.id.summary);
+ elementNameInputLayout.setHint(getString(R.string.hint_friendly_name));
+ elementNameInput.setText(mElement.getName());
+ elementNameInput.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(final CharSequence s, final int start, final int count, final int after) {
+
+ }
+
+ @Override
+ public void onTextChanged(final CharSequence s, final int start, final int before, final int count) {
+ if (TextUtils.isEmpty(s.toString().trim())) {
+ elementNameInputLayout.setError(getString(R.string.error_empty_name));
+ } else {
+ elementNameInputLayout.setError(null);
+ }
+ }
+
+ @Override
+ public void afterTextChanged(final Editable s) {
+
+ }
+ });
+
+ final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(requireContext()).setView(rootView)
+ .setPositiveButton(R.string.ok, null).setNegativeButton(R.string.cancel, null);
+
+ alertDialogBuilder.setIcon(R.drawable.ic_label_black_alpha_24dp);
+ alertDialogBuilder.setTitle(R.string.title_element_name);
+ summary.setText(R.string.element_name_rationale);
+
+ final AlertDialog alertDialog = alertDialogBuilder.show();
+ alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(v -> {
+ final String elementName = elementNameInput.getEditableText().toString().trim();
+ if (!TextUtils.isEmpty(elementName)) {
+ if (((DialogFragmentElementNameListener) requireContext()).onElementNameUpdated(mElement, elementName)) {
+ dismiss();
+ }
+ }
+ });
+
+ return alertDialog;
+ }
+
+ public interface DialogFragmentElementNameListener {
+
+ boolean onElementNameUpdated(@NonNull final Element element, @NonNull final String name);
+
+ }
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentNetworkTransmitSettings.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/dialog/DialogFragmentNetworkTransmitSettings.java
similarity index 80%
rename from Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentNetworkTransmitSettings.java
rename to Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/dialog/DialogFragmentNetworkTransmitSettings.java
index ca22a4f31..64cd16436 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentNetworkTransmitSettings.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/dialog/DialogFragmentNetworkTransmitSettings.java
@@ -1,12 +1,13 @@
-package no.nordicsemi.android.nrfmeshprovisioner.dialog;
+package no.nordicsemi.android.nrfmeshprovisioner.node.dialog;
-import android.app.AlertDialog;
+import android.annotation.SuppressLint;
+import androidx.appcompat.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.v4.app.DialogFragment;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.DialogFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.SeekBar;
@@ -21,8 +22,8 @@ public class DialogFragmentNetworkTransmitSettings extends DialogFragment {
private static final String TAG = DialogFragmentNetworkTransmitSettings.class.getSimpleName();
- public static final String TRANSMIT_COUNT = "TRANSMIT_COUNT";
- public static final String TRANSMIT_INTERVAL_STEPS = "TRANSMIT_INTERVAL_STEPS";
+ private static final String TRANSMIT_COUNT = "TRANSMIT_COUNT";
+ private static final String TRANSMIT_INTERVAL_STEPS = "TRANSMIT_INTERVAL_STEPS";
private static final int MIN_TRANSMIT_COUNT = 0;
private static final int MAX_TRANSMIT_COUNT = 0b111;
@@ -64,6 +65,7 @@ public void onCreate(@Nullable final Bundle savedInstanceState) {
@NonNull
@Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
+ @SuppressLint("InflateParams")
final View rootView = LayoutInflater.from(getContext()).inflate(R.layout.dialog_fragment_network_transmit_settings, null);
ButterKnife.bind(this, rootView);
@@ -108,7 +110,7 @@ public void onStopTrackingTouch(SeekBar seekBar) {
}
});
- final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getContext()).setView(rootView)
+ final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(requireContext()).setView(rootView)
.setPositiveButton(R.string.ok, null).setNegativeButton(R.string.cancel, null);
alertDialogBuilder.setIcon(R.drawable.ic_repeat_black_24dp);
@@ -116,13 +118,8 @@ public void onStopTrackingTouch(SeekBar seekBar) {
final AlertDialog alertDialog = alertDialogBuilder.show();
alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(v -> {
- if (getParentFragment() == null) {
- ((DialogFragmentNetworkTransmitSettings.DialogFragmentNetworkTransmitSettingsListener) getActivity())
- .onNetworkTransmitSettingsEntered(mTransmitCount, mTransmitIntervalSteps);
- } else {
- ((DialogFragmentNetworkTransmitSettings.DialogFragmentNetworkTransmitSettingsListener) getParentFragment())
- .onNetworkTransmitSettingsEntered(mTransmitCount, mTransmitIntervalSteps);
- }
+ ((DialogFragmentNetworkTransmitSettings.DialogFragmentNetworkTransmitSettingsListener) requireActivity())
+ .onNetworkTransmitSettingsEntered(mTransmitCount, mTransmitIntervalSteps);
dismiss();
});
@@ -132,15 +129,15 @@ public void onStopTrackingTouch(SeekBar seekBar) {
private void setTransmitCount(final int transmitCount) {
mTransmitCount = transmitCount;
final int transmitCountActual = mTransmitCount + 1;
- networkTransmitCountText.setText(getResources().getString(
- R.string.text_network_transmit_count, transmitCountActual));
+ networkTransmitCountText.setText(getResources().getQuantityString(
+ R.plurals.transmit_count, transmitCountActual, transmitCountActual));
}
private void setTransmitIntervalSteps(final int transmitIntervalSteps) {
mTransmitIntervalSteps = transmitIntervalSteps;
final int transmitIntervalMilliseconds = (mTransmitIntervalSteps + 1) * 10;
networkTransmitIntervalStepsText.setText(getResources().getString(
- R.string.text_network_transmit_interval_steps, transmitIntervalMilliseconds));
+ R.string.time_ms, transmitIntervalMilliseconds));
}
public interface DialogFragmentNetworkTransmitSettingsListener {
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentNodeName.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/dialog/DialogFragmentNodeName.java
similarity index 76%
rename from Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentNodeName.java
rename to Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/dialog/DialogFragmentNodeName.java
index 28b9b40cd..a6c5db201 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentNodeName.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/dialog/DialogFragmentNodeName.java
@@ -20,23 +20,26 @@
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package no.nordicsemi.android.nrfmeshprovisioner.dialog;
+package no.nordicsemi.android.nrfmeshprovisioner.node.dialog;
-import android.app.AlertDialog;
+import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.design.widget.TextInputEditText;
-import android.support.design.widget.TextInputLayout;
-import android.support.v4.app.DialogFragment;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
+import android.widget.TextView;
+import com.google.android.material.textfield.TextInputEditText;
+import com.google.android.material.textfield.TextInputLayout;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.DialogFragment;
import butterknife.BindView;
import butterknife.ButterKnife;
import no.nordicsemi.android.nrfmeshprovisioner.R;
@@ -72,11 +75,12 @@ public void onCreate(@Nullable final Bundle savedInstanceState) {
@NonNull
@Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
- final View rootView = LayoutInflater.from(getContext()).inflate(R.layout.dialog_fragment_name, null);
+ @SuppressLint("InflateParams") final View rootView = LayoutInflater.from(getContext()).inflate(R.layout.dialog_fragment_name, null);
//Bind ui
ButterKnife.bind(this, rootView);
- nodeNameInputLayout.setHint(getString(R.string.hint_node_name));
+ final TextView summary = rootView.findViewById(R.id.summary);
+ nodeNameInputLayout.setHint(getString(R.string.hint_friendly_name));
nodeNameInput.setText(mNodeName);
nodeNameInput.addTextChangedListener(new TextWatcher() {
@Override
@@ -86,8 +90,8 @@ public void beforeTextChanged(final CharSequence s, final int start, final int c
@Override
public void onTextChanged(final CharSequence s, final int start, final int before, final int count) {
- if (TextUtils.isEmpty(s.toString())) {
- nodeNameInputLayout.setError(getString(R.string.error_node_name));
+ if (TextUtils.isEmpty(s.toString().trim())) {
+ nodeNameInputLayout.setError(getString(R.string.error_empty_name));
} else {
nodeNameInputLayout.setError(null);
}
@@ -99,19 +103,20 @@ public void afterTextChanged(final Editable s) {
}
});
- final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getContext()).setView(rootView)
+ final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(requireContext()).setView(rootView)
.setPositiveButton(R.string.ok, null).setNegativeButton(R.string.cancel, null);
- alertDialogBuilder.setIcon(R.drawable.ic_vpn_key_black_alpha_24dp);
+ alertDialogBuilder.setIcon(R.drawable.ic_label_black_alpha_24dp);
alertDialogBuilder.setTitle(R.string.title_node_name);
- alertDialogBuilder.setMessage(R.string.name_rationale);
+ summary.setText(R.string.node_name_rationale);
final AlertDialog alertDialog = alertDialogBuilder.show();
alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(v -> {
- final String nodeName = nodeNameInput.getText().toString();
+ final String nodeName = nodeNameInput.getEditableText().toString().trim();
if (!TextUtils.isEmpty(nodeName)) {
- ((DialogFragmentNodeNameListener) getContext()).onNodeNameUpdated(nodeName);
- dismiss();
+ if (((DialogFragmentNodeNameListener) requireContext()).onNodeNameUpdated(nodeName)) {
+ dismiss();
+ }
}
});
@@ -120,7 +125,7 @@ public void afterTextChanged(final Editable s) {
public interface DialogFragmentNodeNameListener {
- void onNodeNameUpdated(final String nodeName);
+ boolean onNodeNameUpdated(@NonNull final String nodeName);
}
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentPubRetransmitIntervalSteps.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/dialog/DialogFragmentPubRetransmitIntervalSteps.java
similarity index 83%
rename from Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentPubRetransmitIntervalSteps.java
rename to Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/dialog/DialogFragmentPubRetransmitIntervalSteps.java
index 6674ecaf0..e874ef9d5 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentPubRetransmitIntervalSteps.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/dialog/DialogFragmentPubRetransmitIntervalSteps.java
@@ -20,17 +20,18 @@
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package no.nordicsemi.android.nrfmeshprovisioner.dialog;
+package no.nordicsemi.android.nrfmeshprovisioner.node.dialog;
-import android.app.AlertDialog;
+import android.annotation.SuppressLint;
+import androidx.appcompat.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.design.widget.TextInputEditText;
-import android.support.design.widget.TextInputLayout;
-import android.support.v4.app.DialogFragment;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import com.google.android.material.textfield.TextInputEditText;
+import com.google.android.material.textfield.TextInputLayout;
+import androidx.fragment.app.DialogFragment;
import android.text.Editable;
import android.text.InputType;
import android.text.TextUtils;
@@ -52,7 +53,7 @@ public class DialogFragmentPubRetransmitIntervalSteps extends DialogFragment {
@BindView(R.id.text_input_layout)
TextInputLayout intervalStepsInputLayout;
@BindView(R.id.text_input)
- TextInputEditText intevalStepsInput;
+ TextInputEditText intervalStepsInput;
private int mRetransmitCount;
@@ -75,6 +76,7 @@ public void onCreate(@Nullable final Bundle savedInstanceState) {
@NonNull
@Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
+ @SuppressLint("InflateParams")
final View rootView = LayoutInflater.from(getContext()).inflate(R.layout.dialog_fragment_publication_parameters, null);
//Bind ui
@@ -82,11 +84,11 @@ public Dialog onCreateDialog(final Bundle savedInstanceState) {
((TextView)rootView.findViewById(R.id.summary)).setText(R.string.dialog_summary_interval_steps);
final String retransmitCount = String.valueOf(mRetransmitCount);
- intevalStepsInput.setInputType(InputType.TYPE_CLASS_NUMBER);
+ intervalStepsInput.setInputType(InputType.TYPE_CLASS_NUMBER);
intervalStepsInputLayout.setHint(getString(R.string.hint_publication_interval_steps));
- intevalStepsInput.setText(retransmitCount);
- intevalStepsInput.setSelection(retransmitCount.length());
- intevalStepsInput.addTextChangedListener(new TextWatcher() {
+ intervalStepsInput.setText(retransmitCount);
+ intervalStepsInput.setSelection(retransmitCount.length());
+ intervalStepsInput.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(final CharSequence s, final int start, final int count, final int after) {
@@ -107,7 +109,7 @@ public void afterTextChanged(final Editable s) {
}
});
- final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getContext()).setView(rootView)
+ final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(requireContext()).setView(rootView)
.setPositiveButton(R.string.ok, null).setNegativeButton(R.string.cancel, null);
alertDialogBuilder.setIcon(R.drawable.ic_index);
@@ -115,13 +117,10 @@ public void afterTextChanged(final Editable s) {
final AlertDialog alertDialog = alertDialogBuilder.show();
alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(v -> {
- final String ivIndexInput = this.intevalStepsInput.getText().toString();
+ final String ivIndexInput = this.intervalStepsInput.getEditableText().toString().trim();
if (validateInput(ivIndexInput)) {
- if (getParentFragment() == null) {
- ((DialogFragmentIntervalStepsListener) getActivity()).setRetransmitIntervalSteps(Integer.parseInt(ivIndexInput, 16));
- } else {
- ((DialogFragmentIntervalStepsListener) getParentFragment()).setRetransmitIntervalSteps(Integer.parseInt(ivIndexInput, 16));
- }
+ ((DialogFragmentIntervalStepsListener) requireActivity()).
+ setRetransmitIntervalSteps(Integer.parseInt(ivIndexInput, 16));
dismiss();
}
});
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentPublicationResolution.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/dialog/DialogFragmentPublicationResolution.java
similarity index 86%
rename from Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentPublicationResolution.java
rename to Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/dialog/DialogFragmentPublicationResolution.java
index 3c1ad9c87..e6b437766 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentPublicationResolution.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/dialog/DialogFragmentPublicationResolution.java
@@ -1,12 +1,12 @@
-package no.nordicsemi.android.nrfmeshprovisioner.dialog;
+package no.nordicsemi.android.nrfmeshprovisioner.node.dialog;
-import android.app.AlertDialog;
+import androidx.appcompat.app.AlertDialog;
import android.app.Dialog;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.v4.app.DialogFragment;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.DialogFragment;
import no.nordicsemi.android.meshprovisioner.utils.MeshParserUtils;
import no.nordicsemi.android.nrfmeshprovisioner.R;
@@ -36,16 +36,16 @@ public void onCreate(@Nullable final Bundle savedInstanceState) {
@Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
- final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getContext())
+ final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(requireContext())
.setIcon(R.drawable.ic_linear_scale_black_alpha_24dp)
.setTitle(R.string.title_publication_resolution)
.setSingleChoiceItems(R.array.arr_publication_resolution, mPublicationResolution, null)
.setPositiveButton(R.string.ok, (dialog, which) -> {
final int index = ((AlertDialog) dialog).getListView().getCheckedItemPosition();
- ((DialogFragmentPublicationResolutionListener) getActivity()).setPublicationResolution(getResolution(index)); })
+ ((DialogFragmentPublicationResolutionListener) requireActivity()).setPublicationResolution(getResolution(index));})
.setNegativeButton(R.string.cancel, (dialog, which) -> {
final int index = ((AlertDialog) dialog).getListView().getCheckedItemPosition();
- ((DialogFragmentPublicationResolutionListener) getActivity()).setPublicationResolution(getResolution(index));
+ ((DialogFragmentPublicationResolutionListener) requireActivity()).setPublicationResolution(getResolution(index));
});
return alertDialogBuilder.create();
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentPublicationSteps.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/dialog/DialogFragmentPublicationSteps.java
similarity index 86%
rename from Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentPublicationSteps.java
rename to Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/dialog/DialogFragmentPublicationSteps.java
index 145c4437e..51caeea14 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentPublicationSteps.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/dialog/DialogFragmentPublicationSteps.java
@@ -20,17 +20,18 @@
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package no.nordicsemi.android.nrfmeshprovisioner.dialog;
+package no.nordicsemi.android.nrfmeshprovisioner.node.dialog;
-import android.app.AlertDialog;
+import android.annotation.SuppressLint;
+import androidx.appcompat.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.design.widget.TextInputEditText;
-import android.support.design.widget.TextInputLayout;
-import android.support.v4.app.DialogFragment;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import com.google.android.material.textfield.TextInputEditText;
+import com.google.android.material.textfield.TextInputLayout;
+import androidx.fragment.app.DialogFragment;
import android.text.Editable;
import android.text.InputType;
import android.text.TextUtils;
@@ -75,11 +76,13 @@ public void onCreate(@Nullable final Bundle savedInstanceState) {
@NonNull
@Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
+ @SuppressLint("InflateParams")
final View rootView = LayoutInflater.from(getContext()).inflate(R.layout.dialog_fragment_publication_parameters, null);
//Bind ui
ButterKnife.bind(this, rootView);
- ((TextView)rootView.findViewById(R.id.summary)).setText(R.string.dialog_summary_publication_steps);
+ ((TextView)rootView.findViewById(R.id.summary)).
+ setText(R.string.dialog_summary_publication_steps);
final String publicationSteps = String.valueOf(mPublicationSteps);
publicationStepsInput.setInputType(InputType.TYPE_CLASS_NUMBER);
@@ -107,7 +110,7 @@ public void afterTextChanged(final Editable s) {
}
});
- final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getContext()).setView(rootView)
+ final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(requireContext()).setView(rootView)
.setPositiveButton(R.string.ok, null).setNegativeButton(R.string.cancel, null);
alertDialogBuilder.setIcon(R.drawable.ic_index);
@@ -115,13 +118,10 @@ public void afterTextChanged(final Editable s) {
final AlertDialog alertDialog = alertDialogBuilder.show();
alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(v -> {
- final String publicationStepsInput = this.publicationStepsInput.getText().toString();
+ final String publicationStepsInput = this.publicationStepsInput.getEditableText().toString().trim();
if (validateInput(publicationStepsInput)) {
- if (getParentFragment() == null) {
- ((DialogFragmentPublicationStepsListener) getActivity()).setPublicationSteps(Integer.parseInt(publicationStepsInput, 16));
- } else {
- ((DialogFragmentPublicationStepsListener) getParentFragment()).setPublicationSteps(Integer.parseInt(publicationStepsInput, 16));
- }
+ ((DialogFragmentPublicationStepsListener) requireActivity()).
+ setPublicationSteps(Integer.valueOf(publicationStepsInput));
dismiss();
}
});
@@ -129,7 +129,6 @@ public void afterTextChanged(final Editable s) {
return alertDialog;
}
-
private boolean validateInput(final String input) {
try {
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/dialog/DialogFragmentPublishAddress.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/dialog/DialogFragmentPublishAddress.java
new file mode 100644
index 000000000..980707350
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/dialog/DialogFragmentPublishAddress.java
@@ -0,0 +1,519 @@
+/*
+ * Copyright (c) 2018, Nordic Semiconductor
+ * 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 no.nordicsemi.android.nrfmeshprovisioner.node.dialog;
+
+import android.annotation.SuppressLint;
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.text.Editable;
+import android.text.TextUtils;
+import android.text.TextWatcher;
+import android.text.method.KeyListener;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.Button;
+import android.widget.RadioButton;
+import android.widget.Spinner;
+import android.widget.TextView;
+
+import com.google.android.material.textfield.TextInputEditText;
+import com.google.android.material.textfield.TextInputLayout;
+
+import java.util.ArrayList;
+import java.util.Locale;
+import java.util.UUID;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.DialogFragment;
+import butterknife.BindView;
+import butterknife.ButterKnife;
+import no.nordicsemi.android.meshprovisioner.Group;
+import no.nordicsemi.android.meshprovisioner.transport.PublicationSettings;
+import no.nordicsemi.android.meshprovisioner.utils.AddressType;
+import no.nordicsemi.android.meshprovisioner.utils.MeshAddress;
+import no.nordicsemi.android.nrfmeshprovisioner.GroupCallbacks;
+import no.nordicsemi.android.nrfmeshprovisioner.R;
+import no.nordicsemi.android.nrfmeshprovisioner.adapter.AddressTypeAdapter;
+import no.nordicsemi.android.nrfmeshprovisioner.adapter.GroupAdapterSpinner;
+import no.nordicsemi.android.nrfmeshprovisioner.utils.AddressTypes;
+import no.nordicsemi.android.nrfmeshprovisioner.utils.HexKeyListener;
+import no.nordicsemi.android.nrfmeshprovisioner.utils.Utils;
+
+import static no.nordicsemi.android.nrfmeshprovisioner.utils.AddressTypes.ALL_FRIENDS;
+import static no.nordicsemi.android.nrfmeshprovisioner.utils.AddressTypes.ALL_NODES;
+import static no.nordicsemi.android.nrfmeshprovisioner.utils.AddressTypes.ALL_PROXIES;
+import static no.nordicsemi.android.nrfmeshprovisioner.utils.AddressTypes.ALL_RELAYS;
+import static no.nordicsemi.android.nrfmeshprovisioner.utils.AddressTypes.GROUP_ADDRESS;
+import static no.nordicsemi.android.nrfmeshprovisioner.utils.AddressTypes.UNICAST_ADDRESS;
+import static no.nordicsemi.android.nrfmeshprovisioner.utils.AddressTypes.VIRTUAL_ADDRESS;
+
+public class DialogFragmentPublishAddress extends DialogFragment {
+
+ private static final String PUBLICATION_SETTINGS = "PUBLICATION_SETTINGS";
+ private static final String GROUPS = "GROUPS";
+ private static final String GROUP = "GROUP";
+ private static final String UUID_KEY = "UUID";
+ private ArrayList mGroups = new ArrayList<>();
+ private PublicationSettings mPublicationSettings;
+ private static final AddressTypes[] addressTypes = {UNICAST_ADDRESS, GROUP_ADDRESS, ALL_PROXIES, ALL_FRIENDS, ALL_RELAYS, ALL_NODES, VIRTUAL_ADDRESS};
+
+ //UI Bindings
+ @BindView(R.id.summary)
+ TextView summary;
+ @BindView(R.id.address_types)
+ Spinner addressTypesSpinnerView;
+ @BindView(R.id.label_container)
+ View labelContainer;
+ @BindView(R.id.uuid_label)
+ TextView labelUuidView;
+ @BindView(R.id.group_container)
+ View groupContainer;
+ @BindView(R.id.radio_select_group)
+ RadioButton selectGroup;
+ @BindView(R.id.radio_create_group)
+ RadioButton createGroup;
+ @BindView(R.id.groups)
+ Spinner groups;
+ @BindView(R.id.group_name_layout)
+ TextInputLayout groupNameInputLayout;
+ @BindView(R.id.name_input)
+ TextInputEditText groupNameInput;
+ @BindView(R.id.group_address_layout)
+ TextInputLayout addressInputLayout;
+ @BindView(R.id.address_input)
+ TextInputEditText addressInput;
+ @BindView(R.id.no_groups_configured)
+ TextView noGroups;
+ private Button mGenerateLabelUUID;
+
+ private AddressTypeAdapter mAdapterSpinner;
+ private Group mGroup;
+
+ public interface DialogFragmentPublicationListener {
+
+ void onPublishAddressSet(final int publishAddress);
+
+ void onPublishAddressSet(@NonNull final Group group);
+
+ }
+
+ public static DialogFragmentPublishAddress newInstance(@NonNull final PublicationSettings publicationSettings,
+ @NonNull final ArrayList groups) {
+ DialogFragmentPublishAddress fragmentPublishAddress = new DialogFragmentPublishAddress();
+ final Bundle args = new Bundle();
+ args.putParcelable(PUBLICATION_SETTINGS, publicationSettings);
+ args.putParcelableArrayList(GROUPS, groups);
+ fragmentPublishAddress.setArguments(args);
+ return fragmentPublishAddress;
+ }
+
+ @Override
+ public void onCreate(@Nullable final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ if (getArguments() != null) {
+ mPublicationSettings = getArguments().getParcelable(PUBLICATION_SETTINGS);
+ mGroups = getArguments().getParcelableArrayList(GROUPS);
+ }
+ }
+
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(final Bundle savedInstanceState) {
+ @SuppressLint("InflateParams") final View rootView = LayoutInflater.from(getContext()).
+ inflate(R.layout.dialog_fragment_group_subscription, null);
+
+ //Bind ui
+ ButterKnife.bind(this, rootView);
+ if (savedInstanceState != null) {
+ labelUuidView.setText(savedInstanceState.getString(UUID_KEY));
+ mGroup = savedInstanceState.getParcelable(GROUP);
+ } else {
+ mGroup = ((GroupCallbacks) requireActivity()).createGroup();
+ }
+
+ setAddressType();
+ summary.setText(R.string.publish_address_dialog_summary);
+ addressTypesSpinnerView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(final AdapterView> parent, final View view, final int position, final long id) {
+ updateAddress(mAdapterSpinner.getItem(position));
+ }
+
+ @Override
+ public void onNothingSelected(final AdapterView> parent) {
+
+ }
+ });
+
+ selectGroup.setOnCheckedChangeListener((buttonView, isChecked) -> {
+ groupNameInputLayout.setEnabled(!isChecked);
+ groupNameInputLayout.setError(null);
+ addressInputLayout.setEnabled(!isChecked);
+ addressInputLayout.setError(null);
+ groups.setEnabled(isChecked);
+ createGroup.setChecked(!isChecked);
+ });
+
+ createGroup.setOnCheckedChangeListener((buttonView, isChecked) -> {
+ groupNameInputLayout.setEnabled(isChecked);
+ groupNameInputLayout.setError(null);
+ addressInputLayout.setEnabled(isChecked);
+ addressInputLayout.setError(null);
+ groups.setEnabled(!isChecked);
+ selectGroup.setChecked(!isChecked);
+ });
+
+ final GroupAdapterSpinner adapter = new GroupAdapterSpinner(requireContext(), mGroups);
+ groups.setAdapter(adapter);
+
+ if (mGroups.isEmpty()) {
+ selectGroup.setEnabled(false);
+ groups.setEnabled(false);
+ createGroup.setChecked(true);
+ } else {
+ selectGroup.setChecked(true);
+ createGroup.setChecked(false);
+ }
+
+ final KeyListener hexKeyListener = new HexKeyListener();
+ addressInput.setKeyListener(hexKeyListener);
+ addressInput.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(final CharSequence s, final int start, final int count, final int after) {
+
+ }
+
+ @Override
+ public void onTextChanged(final CharSequence s, final int start, final int before, final int count) {
+ mGroup = null;
+ if (TextUtils.isEmpty(s.toString())) {
+ addressInputLayout.setError(getString(R.string.error_empty_group_address));
+ } else {
+ addressInputLayout.setError(null);
+ }
+ }
+
+ @Override
+ public void afterTextChanged(final Editable s) {
+
+ }
+ });
+
+ final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(requireContext()).
+ setIcon(R.drawable.ic_lan_black_alpha_24dp).
+ setTitle(R.string.title_publish_address).
+ setView(rootView).
+ setPositiveButton(R.string.ok, null).
+ setNegativeButton(R.string.cancel, null).
+ setNeutralButton(R.string.generate_uuid, null);
+
+ final AlertDialog alertDialog = alertDialogBuilder.show();
+ alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(v -> setPublishAddress());
+
+ mGenerateLabelUUID = alertDialog.getButton(DialogInterface.BUTTON_NEUTRAL);
+ mGenerateLabelUUID.setOnClickListener(v -> {
+ final UUID uuid = MeshAddress.generateRandomLabelUUID();
+ labelUuidView.setText(uuid.toString().toUpperCase(Locale.US));
+ generateVirtualAddress(uuid);
+ });
+
+ return alertDialog;
+ }
+
+ @Override
+ public void onSaveInstanceState(@NonNull final Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putString(UUID_KEY, labelUuidView.getText().toString());
+ outState.putParcelable(GROUP, mGroup);
+ }
+
+ private void setPublishAddress() {
+ final String input = addressInput.getEditableText().toString().trim();
+ final int address;
+ final AddressTypes type = (AddressTypes) addressTypesSpinnerView.getSelectedItem();
+ switch (type) {
+ case UNICAST_ADDRESS:
+ if (validateInput(input)) {
+ address = Integer.parseInt(input, 16);
+ ((DialogFragmentPublicationListener) requireActivity())
+ .onPublishAddressSet(address);
+ dismiss();
+ }
+ break;
+ case GROUP_ADDRESS:
+ try {
+ if (createGroup.isChecked()) {
+ final String name = groupNameInput.getEditableText().toString().trim();
+ final String groupAddress = addressInput.getEditableText().toString().trim();
+ if (validateInput(name, groupAddress)) {
+ if (mGroup != null) {
+ ((DialogFragmentPublicationListener) requireActivity()).
+ onPublishAddressSet(mGroup);
+ dismiss();
+ } else {
+ if (((GroupCallbacks) requireActivity())
+ .onGroupAdded(name, Integer.parseInt(groupAddress, 16))) {
+ dismiss();
+ }
+ }
+ }
+ } else {
+ final Group group = (Group) groups.getSelectedItem();
+ ((DialogFragmentPublicationListener) requireActivity()).onPublishAddressSet(group);
+ dismiss();
+ }
+ } catch (IllegalArgumentException ex) {
+ addressInputLayout.setError(ex.getMessage());
+ }
+ break;
+ case ALL_PROXIES:
+ ((DialogFragmentPublicationListener) requireActivity()).onPublishAddressSet(MeshAddress.ALL_PROXIES_ADDRESS);
+ dismiss();
+ break;
+ case ALL_FRIENDS:
+ ((DialogFragmentPublicationListener) requireActivity()).onPublishAddressSet(MeshAddress.ALL_FRIENDS_ADDRESS);
+ dismiss();
+ break;
+ case ALL_RELAYS:
+ ((DialogFragmentPublicationListener) requireActivity()).onPublishAddressSet(MeshAddress.ALL_RELAYS_ADDRESS);
+ dismiss();
+ break;
+ case ALL_NODES:
+ ((DialogFragmentPublicationListener) requireActivity()).onPublishAddressSet(MeshAddress.ALL_NODES_ADDRESS);
+ dismiss();
+ break;
+ case VIRTUAL_ADDRESS:
+ Group group = null;
+ try {
+ final UUID uuid = UUID.fromString(labelUuidView.getText().toString().trim());
+ final String name = groupNameInput.getEditableText().toString().trim();
+ group = ((GroupCallbacks) requireActivity()).createGroup(uuid, name);
+ if (group != null) {
+ if (((GroupCallbacks) requireActivity()).onGroupAdded(group)) {
+ dismiss();
+ }
+ }
+ } catch (IllegalArgumentException ex) {
+ if (group != null) {
+ ((DialogFragmentPublicationListener) requireActivity()).onPublishAddressSet(group);
+ dismiss();
+ }
+ }
+ break;
+ }
+ }
+
+ private void setAddressType() {
+ int address = 0;
+ if (mPublicationSettings != null) {
+ address = mPublicationSettings.getPublishAddress();
+ }
+
+ mAdapterSpinner = new AddressTypeAdapter(requireContext(), addressTypes);
+ addressTypesSpinnerView.setAdapter(mAdapterSpinner);
+ final AddressType type = MeshAddress.getAddressType(address);
+ if (type != null) {
+ switch (type) {
+ default:
+ if (address == MeshAddress.ALL_PROXIES_ADDRESS) {
+ addressTypesSpinnerView.setSelection(2);
+ } else if (address == MeshAddress.ALL_FRIENDS_ADDRESS) {
+ addressTypesSpinnerView.setSelection(3);
+ } else if (address == MeshAddress.ALL_RELAYS_ADDRESS) {
+ addressTypesSpinnerView.setSelection(4);
+ } else {
+ addressTypesSpinnerView.setSelection(5);
+ }
+ break;
+ case UNICAST_ADDRESS:
+ addressTypesSpinnerView.setSelection(0);
+ break;
+ case GROUP_ADDRESS:
+ addressTypesSpinnerView.setSelection(1);
+ break;
+ case VIRTUAL_ADDRESS:
+ addressTypesSpinnerView.setSelection(addressTypes.length - 1);
+ break;
+ }
+ }
+ }
+
+ private void updateAddress(@NonNull final AddressTypes addressType) {
+ int address = 0;
+ if (mPublicationSettings != null) {
+ address = mPublicationSettings.getPublishAddress();
+ }
+
+ switch (addressType) {
+ default:
+ case UNICAST_ADDRESS:
+ addressInput.getEditableText().clear();
+ updateFixedGroupAddressVisibility(MeshAddress.ALL_PROXIES_ADDRESS, true);
+ break;
+ case GROUP_ADDRESS:
+ final int index = getGroupIndex(address);
+ groups.setSelection(index);
+ addressInputLayout.setEnabled(false);
+ groupNameInputLayout.setVisibility(View.VISIBLE);
+ groupContainer.setVisibility(View.VISIBLE);
+ labelContainer.setVisibility(View.GONE);
+ mGenerateLabelUUID.setVisibility(View.GONE);
+ final Group group = ((GroupCallbacks) requireActivity())
+ .createGroup(groupNameInput.getEditableText().toString().trim());
+ if (group != null) {
+ addressInput.setText(MeshAddress.formatAddress(group.getAddress(), false));
+ }
+ break;
+ case ALL_PROXIES:
+ updateFixedGroupAddressVisibility(MeshAddress.ALL_PROXIES_ADDRESS, false);
+ break;
+ case ALL_FRIENDS:
+ updateFixedGroupAddressVisibility(MeshAddress.ALL_FRIENDS_ADDRESS, false);
+ break;
+ case ALL_RELAYS:
+ updateFixedGroupAddressVisibility(MeshAddress.ALL_RELAYS_ADDRESS, false);
+ break;
+ case ALL_NODES:
+ updateFixedGroupAddressVisibility(MeshAddress.ALL_NODES_ADDRESS, false);
+ break;
+ case VIRTUAL_ADDRESS:
+ if (mPublicationSettings != null && mPublicationSettings.getLabelUUID() != null) {
+ labelUuidView.setText(mPublicationSettings.getLabelUUID().toString().toUpperCase(Locale.US));
+ }
+ labelContainer.setVisibility(View.VISIBLE);
+ mGenerateLabelUUID.setVisibility(View.VISIBLE);
+ addressInputLayout.setEnabled(false);
+ groupNameInputLayout.setVisibility(View.VISIBLE);
+ groupContainer.setVisibility(View.VISIBLE);
+ groupContainer.setVisibility(View.GONE);
+ generateVirtualAddress(UUID.fromString(labelUuidView.getText().toString()));
+ break;
+ }
+ }
+
+ private void updateFixedGroupAddressVisibility(final int address, final boolean enabled) {
+ addressInput.setText(MeshAddress.formatAddress(address, false));
+ addressInputLayout.setEnabled(enabled);
+ groupNameInputLayout.setVisibility(View.GONE);
+ groupContainer.setVisibility(View.GONE);
+ labelContainer.setVisibility(View.GONE);
+ mGenerateLabelUUID.setVisibility(View.GONE);
+ }
+
+ private void generateVirtualAddress(@NonNull final UUID uuid) {
+ final Group group1 = ((GroupCallbacks) requireActivity()).createGroup(uuid, groupNameInput.getEditableText().toString().trim());
+ if (group1 != null) {
+ addressInput.setText(MeshAddress.formatAddress(group1.getAddress(), false));
+ }
+ }
+
+ private int getGroupIndex(final int address) {
+ for (int i = 0; i < mGroups.size(); i++) {
+ if (address == mGroups.get(i).getAddress()) {
+ return i;
+ }
+ }
+ return 0;
+ }
+
+ private boolean validateInput(@NonNull final String input) {
+
+ try {
+ if (input.length() % 4 != 0 || !input.matches(Utils.HEX_PATTERN)) {
+ addressInputLayout.setError(getString(R.string.invalid_address_value));
+ return false;
+ }
+ final AddressTypes type = (AddressTypes) addressTypesSpinnerView.getSelectedItem();
+
+ final int address = Integer.parseInt(input, 16);
+ switch (type) {
+ default:
+ if (!MeshAddress.isValidUnassignedAddress(address)) {
+ addressInputLayout.setError(getString(R.string.invalid_address_value));
+ return false;
+ }
+ return true;
+ case UNICAST_ADDRESS:
+ if (!MeshAddress.isValidUnicastAddress(address)) {
+ addressInputLayout.setError(getString(R.string.invalid_unicast_address));
+ return false;
+ }
+ return true;
+ case GROUP_ADDRESS:
+ if (!MeshAddress.isValidGroupAddress(address)) {
+ addressInputLayout.setError(getString(R.string.invalid_group_address));
+ return false;
+ }
+ for (Group group : mGroups) {
+ if (address == group.getAddress()) {
+ addressInputLayout.setError(getString(R.string.error_group_address_in_used));
+ return false;
+ }
+ }
+ return true;
+ case VIRTUAL_ADDRESS:
+ //do nothing since the library generates it
+ return true;
+ }
+ } catch (IllegalArgumentException ex) {
+ addressInputLayout.setError(ex.getMessage());
+ return false;
+ }
+ }
+
+ private boolean validateInput(@NonNull final String name,
+ @NonNull final String address) {
+ try {
+ if (TextUtils.isEmpty(name)) {
+ groupNameInputLayout.setError(getString(R.string.error_empty_group_name));
+ return false;
+ }
+ if (address.length() % 4 != 0 || !address.matches(Utils.HEX_PATTERN)) {
+ addressInputLayout.setError(getString(R.string.invalid_address_value));
+ return false;
+ }
+
+ final int groupAddress = Integer.valueOf(address, 16);
+ if (!MeshAddress.isValidGroupAddress(groupAddress)) {
+ addressInputLayout.setError(getString(R.string.invalid_address_value));
+ return false;
+ }
+
+ for (Group group : mGroups) {
+ if (groupAddress == group.getAddress()) {
+ addressInputLayout.setError(getString(R.string.error_group_address_in_used));
+ return false;
+ }
+ }
+ } catch (IllegalArgumentException ex) {
+ addressInputLayout.setError(ex.getMessage());
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentPublishTtl.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/dialog/DialogFragmentPublishTtl.java
similarity index 86%
rename from Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentPublishTtl.java
rename to Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/dialog/DialogFragmentPublishTtl.java
index e6d2b93d1..246752933 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentPublishTtl.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/dialog/DialogFragmentPublishTtl.java
@@ -20,17 +20,19 @@
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package no.nordicsemi.android.nrfmeshprovisioner.dialog;
+package no.nordicsemi.android.nrfmeshprovisioner.node.dialog;
-import android.app.AlertDialog;
+import androidx.appcompat.app.AlertDialog;
+
+import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.design.widget.TextInputEditText;
-import android.support.design.widget.TextInputLayout;
-import android.support.v4.app.DialogFragment;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import com.google.android.material.textfield.TextInputEditText;
+import com.google.android.material.textfield.TextInputLayout;
+import androidx.fragment.app.DialogFragment;
import android.text.Editable;
import android.text.InputType;
import android.text.TextUtils;
@@ -76,7 +78,7 @@ public void onCreate(@Nullable final Bundle savedInstanceState) {
@NonNull
@Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
- final View rootView = LayoutInflater.from(getContext()).inflate(R.layout.dialog_fragment_publish_ttl_input, null);
+ @SuppressLint("InflateParams") final View rootView = LayoutInflater.from(getContext()).inflate(R.layout.dialog_fragment_publish_ttl_input, null);
ButterKnife.bind(this, rootView);
chkPublishTtl.setOnCheckedChangeListener((buttonView, isChecked) -> {
@@ -95,7 +97,7 @@ public void beforeTextChanged(final CharSequence s, final int start, final int c
@Override
public void onTextChanged(final CharSequence s, final int start, final int before, final int count) {
if (TextUtils.isEmpty(s.toString())) {
- ttlInputLayout.setError(getString(R.string.error_empty_publish_ttl));
+ ttlInputLayout.setError(getString(R.string.error_empty_ttl));
} else {
ttlInputLayout.setError(null);
}
@@ -107,22 +109,21 @@ public void afterTextChanged(final Editable s) {
}
});
- final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getContext()).setView(rootView)
+ final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(requireContext()).setView(rootView)
.setPositiveButton(R.string.ok, null).setNegativeButton(R.string.cancel, null);
alertDialogBuilder.setIcon(R.drawable.ic_timer);
alertDialogBuilder.setTitle(R.string.title_publish_ttl);
- alertDialogBuilder.setMessage(R.string.dialog_summary_publish_ttl);
final AlertDialog alertDialog = alertDialogBuilder.show();
alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(v -> {
if(chkPublishTtl.isChecked()) {
- ((DialogFragmentPublishTtlListener) getActivity()).setPublishTtl(MeshParserUtils.USE_DEFAULT_TTL);
+ ((DialogFragmentPublishTtlListener) requireActivity()).setPublishTtl(MeshParserUtils.USE_DEFAULT_TTL);
dismiss();
} else {
- final String publishTtl = ttlInput.getText().toString();
+ final String publishTtl = ttlInput.getEditableText().toString().trim();
if (validateInput(publishTtl)) {
- ((DialogFragmentPublishTtlListener) getActivity()).setPublishTtl(Integer.parseInt(publishTtl));
+ ((DialogFragmentPublishTtlListener) requireActivity()).setPublishTtl(Integer.parseInt(publishTtl));
dismiss();
}
}
@@ -148,7 +149,7 @@ public void afterTextChanged(final Editable s) {
private boolean validateInput(final String input) {
try {
if(TextUtils.isEmpty(input)){
- ttlInputLayout.setError(getString(R.string.error_empty_publish_ttl));
+ ttlInputLayout.setError(getString(R.string.error_empty_ttl));
return false;
}
if(!MeshParserUtils.isValidTtl(Integer.parseInt(input))) {
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentResetNode.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/dialog/DialogFragmentResetNode.java
similarity index 87%
rename from Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentResetNode.java
rename to Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/dialog/DialogFragmentResetNode.java
index 64622ddad..e6204bda2 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentResetNode.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/dialog/DialogFragmentResetNode.java
@@ -20,14 +20,15 @@
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package no.nordicsemi.android.nrfmeshprovisioner.dialog;
+package no.nordicsemi.android.nrfmeshprovisioner.node.dialog;
import android.app.Dialog;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v7.app.AlertDialog;
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AlertDialog;
import no.nordicsemi.android.nrfmeshprovisioner.R;
+import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentMessage;
public class DialogFragmentResetNode extends DialogFragmentMessage {
@@ -52,11 +53,11 @@ public void onCreate(Bundle savedInstanceState) {
@NonNull
@Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
- alertDialogBuilder = new AlertDialog.Builder(getActivity());
+ alertDialogBuilder = new AlertDialog.Builder(requireActivity());
alertDialogBuilder.setIcon(R.drawable.ic_reset_black_24dp_alpha);
alertDialogBuilder.setNegativeButton(getString(R.string.no), null);
alertDialogBuilder.setPositiveButton(getString(R.string.yes), (dialog, which) -> (
- (DialogFragmentNodeResetListener)getActivity()).onNodeReset());
+ (DialogFragmentNodeResetListener)requireActivity()).onNodeReset());
return super.onCreateDialog(savedInstanceState);
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentRetransmitCount.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/dialog/DialogFragmentRetransmitCount.java
similarity index 88%
rename from Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentRetransmitCount.java
rename to Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/dialog/DialogFragmentRetransmitCount.java
index aaa3f5290..2c1bf91f6 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentRetransmitCount.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/dialog/DialogFragmentRetransmitCount.java
@@ -20,17 +20,19 @@
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package no.nordicsemi.android.nrfmeshprovisioner.dialog;
+package no.nordicsemi.android.nrfmeshprovisioner.node.dialog;
-import android.app.AlertDialog;
+import androidx.appcompat.app.AlertDialog;
+
+import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.design.widget.TextInputEditText;
-import android.support.design.widget.TextInputLayout;
-import android.support.v4.app.DialogFragment;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import com.google.android.material.textfield.TextInputEditText;
+import com.google.android.material.textfield.TextInputLayout;
+import androidx.fragment.app.DialogFragment;
import android.text.Editable;
import android.text.InputType;
import android.text.TextUtils;
@@ -75,7 +77,7 @@ public void onCreate(@Nullable final Bundle savedInstanceState) {
@NonNull
@Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
- final View rootView = LayoutInflater.from(getContext()).inflate(R.layout.dialog_fragment_publication_parameters, null);
+ @SuppressLint("InflateParams") final View rootView = LayoutInflater.from(getContext()).inflate(R.layout.dialog_fragment_publication_parameters, null);
//Bind ui
ButterKnife.bind(this, rootView);
@@ -107,7 +109,7 @@ public void afterTextChanged(final Editable s) {
}
});
- final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getContext()).setView(rootView)
+ final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(requireContext()).setView(rootView)
.setPositiveButton(R.string.ok, null).setNegativeButton(R.string.cancel, null);
alertDialogBuilder.setIcon(R.drawable.ic_numeric);
@@ -115,10 +117,10 @@ public void afterTextChanged(final Editable s) {
final AlertDialog alertDialog = alertDialogBuilder.show();
alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(v -> {
- final String ivIndexInput = this.retransmitInput.getText().toString();
+ final String ivIndexInput = this.retransmitInput.getEditableText().toString().trim();
if (validateInput(ivIndexInput)) {
if (getParentFragment() == null) {
- ((DialogFragmentRetransmitCountListener) getActivity()).setRetransmitCount(Integer.parseInt(ivIndexInput, 16));
+ ((DialogFragmentRetransmitCountListener) requireActivity()).setRetransmitCount(Integer.parseInt(ivIndexInput, 16));
} else {
((DialogFragmentRetransmitCountListener) getParentFragment()).setRetransmitCount(Integer.parseInt(ivIndexInput, 16));
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogRelayRetransmitSettings.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/dialog/DialogRelayRetransmitSettings.java
similarity index 87%
rename from Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogRelayRetransmitSettings.java
rename to Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/dialog/DialogRelayRetransmitSettings.java
index 7e7dd813f..880e9a977 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogRelayRetransmitSettings.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/node/dialog/DialogRelayRetransmitSettings.java
@@ -1,11 +1,12 @@
-package no.nordicsemi.android.nrfmeshprovisioner.dialog;
+package no.nordicsemi.android.nrfmeshprovisioner.node.dialog;
-import android.app.AlertDialog;
+import android.annotation.SuppressLint;
+import androidx.appcompat.app.AlertDialog;
import android.app.Dialog;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.v4.app.DialogFragment;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.DialogFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.SeekBar;
@@ -22,9 +23,9 @@ public class DialogRelayRetransmitSettings extends DialogFragment {
private static final String TAG = DialogRelayRetransmitSettings.class.getSimpleName();
- public static final String RELAY = "RELAY";
- public static final String TRANSMIT_COUNT = "TRANSMIT_COUNT";
- public static final String TRANSMIT_INTERVAL_STEPS = "TRANSMIT_INTERVAL_STEPS";
+ private static final String RELAY = "RELAY";
+ private static final String TRANSMIT_COUNT = "TRANSMIT_COUNT";
+ private static final String TRANSMIT_INTERVAL_STEPS = "TRANSMIT_INTERVAL_STEPS";
private static final int MIN_RETRANSMIT_COUNT = 0;
private static final int MAX_RETRANSMIT_COUNT = 0b111;
@@ -71,6 +72,7 @@ public void onCreate(@Nullable final Bundle savedInstanceState) {
@NonNull
@Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
+ @SuppressLint("InflateParams")
final View rootView = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_fragment_relay_settings, null);
ButterKnife.bind(this, rootView);
@@ -118,7 +120,7 @@ public void onStopTrackingTouch(SeekBar seekBar) {
}
});
- return new AlertDialog.Builder(getContext())
+ return new AlertDialog.Builder(requireContext())
.setView(rootView)
.setPositiveButton(R.string.ok, (dialog, which) -> {
if (getParentFragment() == null) {
@@ -140,15 +142,15 @@ private void setRelay(final int relay) {
private void setRelayRetransmitCount(final int relayRetransmitCount) {
mTransmitCount = relayRetransmitCount;
- relayRetransmitCountText.setText(getResources().getString(
- R.string.text_network_transmit_count, relayRetransmitCount));
+ relayRetransmitCountText.setText(getResources().getQuantityString(
+ R.plurals.transmit_count, relayRetransmitCount, relayRetransmitCount));
}
private void setRelayRetransmitIntervalSteps(final int transmitIntervalSteps) {
mTransmitIntervalSteps = transmitIntervalSteps;
final int transmitIntervalMilliseconds = transmitIntervalSteps * 10;
relayRetransmitIntervalStepsText.setText(getResources().getString(
- R.string.text_network_transmit_interval_steps, transmitIntervalMilliseconds));
+ R.string.time_ms, transmitIntervalMilliseconds));
}
public interface DialogFragmentRelaySettingsListener {
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/provisioners/AddProvisionerActivity.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/provisioners/AddProvisionerActivity.java
new file mode 100644
index 000000000..e8a31468c
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/provisioners/AddProvisionerActivity.java
@@ -0,0 +1,331 @@
+/*
+ * Copyright (c) 2018, Nordic Semiconductor
+ * 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 no.nordicsemi.android.nrfmeshprovisioner.provisioners;
+
+import android.bluetooth.BluetoothAdapter;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.CheckBox;
+import android.widget.TextView;
+
+import javax.inject.Inject;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.Toolbar;
+import androidx.core.content.ContextCompat;
+import androidx.lifecycle.ViewModelProvider;
+import androidx.lifecycle.ViewModelProviders;
+import no.nordicsemi.android.meshprovisioner.AllocatedGroupRange;
+import no.nordicsemi.android.meshprovisioner.AllocatedSceneRange;
+import no.nordicsemi.android.meshprovisioner.AllocatedUnicastRange;
+import no.nordicsemi.android.meshprovisioner.MeshNetwork;
+import no.nordicsemi.android.meshprovisioner.Provisioner;
+import no.nordicsemi.android.meshprovisioner.utils.MeshAddress;
+import no.nordicsemi.android.nrfmeshprovisioner.R;
+import no.nordicsemi.android.nrfmeshprovisioner.di.Injectable;
+import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentError;
+import no.nordicsemi.android.nrfmeshprovisioner.provisioners.dialogs.DialogFragmentProvisionerAddress;
+import no.nordicsemi.android.nrfmeshprovisioner.provisioners.dialogs.DialogFragmentProvisionerName;
+import no.nordicsemi.android.nrfmeshprovisioner.provisioners.dialogs.DialogFragmentTtl;
+import no.nordicsemi.android.nrfmeshprovisioner.provisioners.dialogs.DialogFragmentUnassign;
+import no.nordicsemi.android.nrfmeshprovisioner.utils.Utils;
+import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.AddProvisionerViewModel;
+import no.nordicsemi.android.nrfmeshprovisioner.widgets.RangeView;
+
+public class AddProvisionerActivity extends AppCompatActivity implements Injectable,
+ DialogFragmentProvisionerName.DialogFragmentProvisionerNameListener,
+ DialogFragmentTtl.DialogFragmentTtlListener,
+ DialogFragmentProvisionerAddress.ProvisionerAddressListener,
+ DialogFragmentUnassign.DialogFragmentUnassignListener {
+
+ @Inject
+ ViewModelProvider.Factory mViewModelFactory;
+
+ private TextView provisionerName;
+ private TextView provisionerUnicast;
+ private TextView provisionerTtl;
+ private RangeView unicastRangeView;
+ private RangeView groupRangeView;
+ private RangeView sceneRangeView;
+
+ private AddProvisionerViewModel mViewModel;
+ private Provisioner mProvisioner;
+
+
+ @Override
+ protected void onCreate(@Nullable final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_edit_provisioner);
+ mViewModel = ViewModelProviders.of(this, mViewModelFactory).get(AddProvisionerViewModel.class);
+
+ //Bind ui
+ final Toolbar toolbar = findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+ //noinspection ConstantConditions
+ getSupportActionBar().setTitle(R.string.title_add_provisioner);
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+ getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_close_white_24dp);
+
+ final View containerProvisionerName = findViewById(R.id.container_name);
+ containerProvisionerName.findViewById(R.id.image).
+ setBackground(ContextCompat.getDrawable(this, R.drawable.ic_label_outline_black_alpha_24dp));
+ ((TextView) containerProvisionerName.findViewById(R.id.title)).setText(R.string.name);
+ provisionerName = containerProvisionerName.findViewById(R.id.text);
+ provisionerName.setVisibility(View.VISIBLE);
+
+ final View containerUnicast = findViewById(R.id.container_unicast);
+ containerUnicast.setClickable(false);
+ containerUnicast.findViewById(R.id.image).
+ setBackground(ContextCompat.getDrawable(this, R.drawable.ic_index));
+ ((TextView) containerUnicast.findViewById(R.id.title)).setText(R.string.title_unicast_address);
+ provisionerUnicast = containerUnicast.findViewById(R.id.text);
+ provisionerUnicast.setVisibility(View.VISIBLE);
+
+ final View containerTtl = findViewById(R.id.container_ttl);
+ containerTtl.setClickable(false);
+ containerTtl.findViewById(R.id.image).
+ setBackground(ContextCompat.getDrawable(this, R.drawable.ic_timer));
+ ((TextView) containerTtl.findViewById(R.id.title)).setText(R.string.title_ttl);
+ provisionerTtl = containerTtl.findViewById(R.id.text);
+ provisionerTtl.setVisibility(View.VISIBLE);
+
+ final CheckBox checkBox = findViewById(R.id.check_provisioner);
+ checkBox.setOnCheckedChangeListener((buttonView, isChecked) -> {
+ if (mProvisioner != null) {
+ mProvisioner.setLastSelected(isChecked);
+ }
+ });
+
+ final View containerUnicastRange = findViewById(R.id.container_unicast_range);
+ containerUnicastRange.setClickable(false);
+ containerUnicastRange.findViewById(R.id.image).
+ setBackground(ContextCompat.getDrawable(this, R.drawable.ic_lan_black_alpha_24dp));
+ ((TextView) containerUnicastRange.findViewById(R.id.title)).setText(R.string.title_unicast_addresses);
+ unicastRangeView = containerUnicastRange.findViewById(R.id.range_view);
+
+ final View containerGroupRange = findViewById(R.id.container_group_range);
+ containerGroupRange.setClickable(false);
+ containerGroupRange.findViewById(R.id.image).
+ setBackground(ContextCompat.getDrawable(this, R.drawable.ic_outline_group_work_black_alpha_24dp));
+ ((TextView) containerGroupRange.findViewById(R.id.title)).setText(R.string.title_group_addresses);
+ groupRangeView = containerGroupRange.findViewById(R.id.range_view);
+
+ final View containerSceneRange = findViewById(R.id.container_scene_range);
+ containerSceneRange.setClickable(false);
+ containerSceneRange.findViewById(R.id.image).
+ setBackground(ContextCompat.getDrawable(this, R.drawable.ic_arrow_collapse_black_alpha_24dp));
+ ((TextView) containerSceneRange.findViewById(R.id.title)).setText(R.string.title_scenes);
+ sceneRangeView = containerSceneRange.findViewById(R.id.range_view);
+
+ containerProvisionerName.setOnClickListener(v -> {
+ if (mProvisioner != null) {
+ final DialogFragmentProvisionerName fragment = DialogFragmentProvisionerName.newInstance(mProvisioner.getProvisionerName());
+ fragment.show(getSupportFragmentManager(), null);
+ }
+ });
+
+ containerUnicast.setOnClickListener(v -> {
+ if (mProvisioner != null) {
+ final DialogFragmentProvisionerAddress fragment = DialogFragmentProvisionerAddress.newInstance(mProvisioner.getProvisionerAddress());
+ fragment.show(getSupportFragmentManager(), null);
+ }
+ });
+
+ containerTtl.setOnClickListener(v -> {
+ if (mProvisioner != null) {
+ final DialogFragmentTtl fragment = DialogFragmentTtl.newInstance(mProvisioner.getGlobalTtl());
+ fragment.show(getSupportFragmentManager(), null);
+ }
+ });
+
+ containerUnicastRange.setOnClickListener(v -> {
+ if (mProvisioner != null) {
+ final Intent intent = new Intent(this, RangesActivity.class);
+ intent.putExtra(Utils.RANGE_TYPE, Utils.UNICAST_RANGE);
+ startActivity(intent);
+ }
+ });
+
+ containerGroupRange.setOnClickListener(v -> {
+ if (mProvisioner != null) {
+ final Intent intent = new Intent(this, RangesActivity.class);
+ intent.putExtra(Utils.RANGE_TYPE, Utils.GROUP_RANGE);
+ startActivity(intent);
+ }
+ });
+
+ containerSceneRange.setOnClickListener(v -> {
+ if (mProvisioner != null) {
+ final Intent intent = new Intent(this, RangesActivity.class);
+ intent.putExtra(Utils.RANGE_TYPE, Utils.SCENE_RANGE);
+ startActivity(intent);
+ }
+ });
+
+ if (savedInstanceState == null) {
+ final MeshNetwork network = mViewModel.getMeshManagerApi().getMeshNetwork();
+ if (network != null) {
+ final AllocatedUnicastRange unicastRange = network.nextAvailableUnicastAddressRange(0x199A);
+ final AllocatedGroupRange groupRange = network.nextAvailableGroupAddressRange(0x0C9A);
+ final AllocatedSceneRange sceneRange = network.nextAvailableSceneAddressRange(0x3334);
+ final Provisioner provisioner = network.createProvisioner("nRF Mesh Provisioner", unicastRange, groupRange, sceneRange);
+ final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+ provisioner.setProvisionerName(adapter.getName());
+ mViewModel.setSelectedProvisioner(provisioner);
+ }
+ }
+
+ mViewModel.getSelectedProvisioner().observe(this, provisioner -> {
+ if (provisioner != null) {
+ mProvisioner = provisioner;
+ updateUi();
+ }
+ });
+
+ updateUi();
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.menu_save, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(final MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ case R.id.action_save:
+ if (save()) {
+ onBackPressed();
+ }
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean onNameChanged(@NonNull final String name) {
+ if (mProvisioner != null) {
+ mProvisioner.setProvisionerName(name);
+ updateUi();
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean setAddress(final int sourceAddress) {
+ if (mProvisioner != null) {
+ if (mProvisioner.assignProvisionerAddress(sourceAddress)) {
+ updateUi();
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void unassignProvisioner() {
+ if (mProvisioner != null) {
+ final DialogFragmentUnassign fragmentUnassign = DialogFragmentUnassign
+ .newInstance(getString(R.string.title_unassign_provisioner), getString(R.string.summary_unassign_provisioner));
+ fragmentUnassign.show(getSupportFragmentManager(), null);
+ }
+ }
+
+ @Override
+ public void onProvisionerUnassigned() {
+ if (mProvisioner != null) {
+ final MeshNetwork network = mViewModel.getMeshManagerApi().getMeshNetwork();
+ if (network != null) {
+ provisionerUnicast.setText(R.string.unicast_address_unassigned);
+ mProvisioner.assignProvisionerAddress(null);
+ network.disableConfigurationCapabilities(mProvisioner);
+ }
+ }
+ }
+
+ @Override
+ public boolean setDefaultTtl(final int ttl) {
+ if (mProvisioner != null) {
+ mProvisioner.setGlobalTtl(ttl);
+ return true;
+ }
+ return false;
+ }
+
+ private void updateUi() {
+ if (mProvisioner != null) {
+ provisionerName.setText(mProvisioner.getProvisionerName());
+ if (mProvisioner.getProvisionerAddress() == null) {
+ provisionerUnicast.setText(R.string.not_assigned);
+ } else {
+ provisionerUnicast.setText(MeshAddress.formatAddress(mProvisioner.getProvisionerAddress(), true));
+ }
+
+ unicastRangeView.clearRanges();
+ groupRangeView.clearRanges();
+ sceneRangeView.clearRanges();
+
+ unicastRangeView.addRanges(mProvisioner.getAllocatedUnicastRanges());
+ groupRangeView.addRanges(mProvisioner.getAllocatedGroupRanges());
+ sceneRangeView.addRanges(mProvisioner.getAllocatedSceneRanges());
+
+ final MeshNetwork network = mViewModel.getMeshManagerApi().getMeshNetwork();
+ if (network != null) {
+ final String ttl = String.valueOf(mProvisioner.getGlobalTtl());
+ provisionerTtl.setText(ttl);
+ unicastRangeView.clearOtherRanges();
+ groupRangeView.clearOtherRanges();
+ sceneRangeView.clearOtherRanges();
+ for (Provisioner other : network.getProvisioners()) {
+ unicastRangeView.addOtherRanges(other.getAllocatedUnicastRanges());
+ groupRangeView.addOtherRanges(other.getAllocatedGroupRanges());
+ sceneRangeView.addOtherRanges(other.getAllocatedSceneRanges());
+ }
+ }
+ }
+ }
+
+ private boolean save() {
+ final MeshNetwork network = mViewModel.getMeshManagerApi().getMeshNetwork();
+ if (network != null) {
+ try {
+ return network.addProvisioner(mProvisioner);
+ } catch (IllegalArgumentException ex) {
+ final DialogFragmentError fragment = DialogFragmentError.
+ newInstance(getString(R.string.title_error), ex.getMessage());
+ fragment.show(getSupportFragmentManager(), null);
+ }
+ }
+ return false;
+ }
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/provisioners/EditProvisionerActivity.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/provisioners/EditProvisionerActivity.java
new file mode 100644
index 000000000..87fd7b44b
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/provisioners/EditProvisionerActivity.java
@@ -0,0 +1,333 @@
+/*
+ * Copyright (c) 2018, Nordic Semiconductor
+ * 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 no.nordicsemi.android.nrfmeshprovisioner.provisioners;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.CheckBox;
+import android.widget.TextView;
+
+import javax.inject.Inject;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.Toolbar;
+import androidx.core.content.ContextCompat;
+import androidx.lifecycle.ViewModelProvider;
+import androidx.lifecycle.ViewModelProviders;
+import no.nordicsemi.android.meshprovisioner.MeshNetwork;
+import no.nordicsemi.android.meshprovisioner.Provisioner;
+import no.nordicsemi.android.meshprovisioner.utils.MeshAddress;
+import no.nordicsemi.android.nrfmeshprovisioner.R;
+import no.nordicsemi.android.nrfmeshprovisioner.di.Injectable;
+import no.nordicsemi.android.nrfmeshprovisioner.dialog.DialogFragmentError;
+import no.nordicsemi.android.nrfmeshprovisioner.provisioners.dialogs.DialogFragmentProvisionerAddress;
+import no.nordicsemi.android.nrfmeshprovisioner.provisioners.dialogs.DialogFragmentProvisionerName;
+import no.nordicsemi.android.nrfmeshprovisioner.provisioners.dialogs.DialogFragmentTtl;
+import no.nordicsemi.android.nrfmeshprovisioner.provisioners.dialogs.DialogFragmentUnassign;
+import no.nordicsemi.android.nrfmeshprovisioner.utils.Utils;
+import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.EditProvisionerViewModel;
+import no.nordicsemi.android.nrfmeshprovisioner.widgets.RangeView;
+
+public class EditProvisionerActivity extends AppCompatActivity implements Injectable,
+ DialogFragmentProvisionerName.DialogFragmentProvisionerNameListener,
+ DialogFragmentTtl.DialogFragmentTtlListener,
+ DialogFragmentProvisionerAddress.ProvisionerAddressListener,
+ DialogFragmentUnassign.DialogFragmentUnassignListener {
+
+ @Inject
+ ViewModelProvider.Factory mViewModelFactory;
+
+ private TextView provisionerName;
+ private TextView provisionerUnicast;
+ private TextView provisionerTtl;
+ private RangeView unicastRangeView;
+ private RangeView groupRangeView;
+ private RangeView sceneRangeView;
+ private View selectProvisioner;
+ private CheckBox checkBox;
+
+
+ private EditProvisionerViewModel mViewModel;
+ private Provisioner mProvisioner;
+
+ @Override
+ protected void onCreate(@Nullable final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_edit_provisioner);
+ mViewModel = ViewModelProviders.of(this, mViewModelFactory).get(EditProvisionerViewModel.class);
+
+ //Bind ui
+ final Toolbar toolbar = findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+ //noinspection ConstantConditions
+ getSupportActionBar().setTitle(R.string.title_edit_provisioner);
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+
+ final View containerProvisionerName = findViewById(R.id.container_name);
+ containerProvisionerName.findViewById(R.id.image).
+ setBackground(ContextCompat.getDrawable(this, R.drawable.ic_label_black_alpha_24dp));
+ ((TextView) containerProvisionerName.findViewById(R.id.title)).setText(R.string.name);
+ provisionerName = containerProvisionerName.findViewById(R.id.text);
+ provisionerName.setVisibility(View.VISIBLE);
+
+ final View containerUnicast = findViewById(R.id.container_unicast);
+ containerUnicast.setClickable(false);
+ containerUnicast.findViewById(R.id.image).
+ setBackground(ContextCompat.getDrawable(this, R.drawable.ic_index));
+ ((TextView) containerUnicast.findViewById(R.id.title)).setText(R.string.title_unicast_address);
+ provisionerUnicast = containerUnicast.findViewById(R.id.text);
+ provisionerUnicast.setVisibility(View.VISIBLE);
+
+ final View containerTtl = findViewById(R.id.container_ttl);
+ containerTtl.setClickable(false);
+ containerTtl.findViewById(R.id.image).
+ setBackground(ContextCompat.getDrawable(this, R.drawable.ic_timer));
+ ((TextView) containerTtl.findViewById(R.id.title)).setText(R.string.title_ttl);
+ provisionerTtl = containerTtl.findViewById(R.id.text);
+ provisionerTtl.setVisibility(View.VISIBLE);
+
+ selectProvisioner = findViewById(R.id.select_provisioner_container);
+ checkBox = findViewById(R.id.check_provisioner);
+ checkBox.setOnCheckedChangeListener((buttonView, isChecked) -> {
+ if (mProvisioner != null) {
+ mProvisioner.setLastSelected(isChecked);
+ }
+ });
+
+ final View containerUnicastRange = findViewById(R.id.container_unicast_range);
+ containerUnicastRange.setClickable(false);
+ containerUnicastRange.findViewById(R.id.image).
+ setBackground(ContextCompat.getDrawable(this, R.drawable.ic_lan_black_alpha_24dp));
+ ((TextView) containerUnicastRange.findViewById(R.id.title)).setText(R.string.title_unicast_addresses);
+ unicastRangeView = containerUnicastRange.findViewById(R.id.range_view);
+
+ final View containerGroupRange = findViewById(R.id.container_group_range);
+ containerGroupRange.setClickable(false);
+ containerGroupRange.findViewById(R.id.image).
+ setBackground(ContextCompat.getDrawable(this, R.drawable.ic_outline_group_work_black_alpha_24dp));
+ ((TextView) containerGroupRange.findViewById(R.id.title)).setText(R.string.title_group_addresses);
+ groupRangeView = containerGroupRange.findViewById(R.id.range_view);
+
+ final View containerSceneRange = findViewById(R.id.container_scene_range);
+ containerSceneRange.setClickable(false);
+ containerSceneRange.findViewById(R.id.image).
+ setBackground(ContextCompat.getDrawable(this, R.drawable.ic_scene_black_alpha_24dp));
+ ((TextView) containerSceneRange.findViewById(R.id.title)).setText(R.string.title_scenes);
+ sceneRangeView = containerSceneRange.findViewById(R.id.range_view);
+
+ containerProvisionerName.setOnClickListener(v -> {
+ if (mProvisioner != null) {
+ final DialogFragmentProvisionerName fragment = DialogFragmentProvisionerName.newInstance(mProvisioner.getProvisionerName());
+ fragment.show(getSupportFragmentManager(), null);
+ }
+ });
+
+ containerUnicast.setOnClickListener(v -> {
+ if (mProvisioner != null) {
+ final DialogFragmentProvisionerAddress fragment = DialogFragmentProvisionerAddress.newInstance(mProvisioner.getProvisionerAddress());
+ fragment.show(getSupportFragmentManager(), null);
+ }
+ });
+
+ containerTtl.setOnClickListener(v -> {
+ if (mProvisioner != null) {
+ final DialogFragmentTtl fragment = DialogFragmentTtl.newInstance(mProvisioner.getGlobalTtl());
+ fragment.show(getSupportFragmentManager(), null);
+ }
+ });
+
+ containerUnicastRange.setOnClickListener(v -> {
+ if (mProvisioner != null) {
+ mViewModel.setSelectedProvisioner(mProvisioner);
+ final Intent intent = new Intent(this, RangesActivity.class);
+ intent.putExtra(Utils.RANGE_TYPE, Utils.UNICAST_RANGE);
+ startActivity(intent);
+ }
+ });
+
+ containerGroupRange.setOnClickListener(v -> {
+ if (mProvisioner != null) {
+ mViewModel.setSelectedProvisioner(mProvisioner);
+ final Intent intent = new Intent(this, RangesActivity.class);
+ intent.putExtra(Utils.RANGE_TYPE, Utils.GROUP_RANGE);
+ startActivity(intent);
+ }
+ });
+
+ containerSceneRange.setOnClickListener(v -> {
+ if (mProvisioner != null) {
+ mViewModel.setSelectedProvisioner(mProvisioner);
+ final Intent intent = new Intent(this, RangesActivity.class);
+ intent.putExtra(Utils.RANGE_TYPE, Utils.SCENE_RANGE);
+ startActivity(intent);
+ }
+ });
+
+ mViewModel.getSelectedProvisioner().observe(this, provisioner -> {
+ if (provisioner != null) {
+ mProvisioner = provisioner;
+ updateUi(provisioner);
+ }
+ });
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(final MenuItem item) {
+ if (item.getItemId() == android.R.id.home) {
+ onBackPressed();
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void onBackPressed() {
+ if (save()) {
+ super.onBackPressed();
+ }
+ }
+
+ @Override
+ public boolean onNameChanged(@NonNull final String name) {
+ if (mProvisioner != null) {
+ mProvisioner.setProvisionerName(name);
+ final Provisioner provisioner = mProvisioner;
+ if (save(provisioner)) {
+ provisionerName.setText(mProvisioner.getProvisionerName());
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean setAddress(final int sourceAddress) {
+ if (mProvisioner != null) {
+ if (mProvisioner.assignProvisionerAddress(sourceAddress)) {
+ final Provisioner provisioner = mProvisioner;
+ if (save(provisioner)) {
+ provisionerUnicast.setText(MeshAddress.formatAddress(sourceAddress, true));
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void unassignProvisioner() {
+ if (mProvisioner != null) {
+ final DialogFragmentUnassign fragmentUnassign = DialogFragmentUnassign
+ .newInstance(getString(R.string.title_unassign_provisioner), getString(R.string.summary_unassign_provisioner));
+ fragmentUnassign.show(getSupportFragmentManager(), null);
+ }
+ }
+
+ @Override
+ public void onProvisionerUnassigned() {
+ if (mProvisioner != null) {
+ final MeshNetwork network = mViewModel.getMeshManagerApi().getMeshNetwork();
+ if (network != null) {
+ provisionerUnicast.setText(R.string.unicast_address_unassigned);
+ mProvisioner.assignProvisionerAddress(null);
+ network.disableConfigurationCapabilities(mProvisioner);
+ }
+ }
+ }
+
+ @Override
+ public boolean setDefaultTtl(final int ttl) {
+ if (mProvisioner != null) {
+ mProvisioner.setGlobalTtl(ttl);
+ final Provisioner provisioner = mProvisioner;
+ if (save(provisioner)) {
+ provisionerTtl.setText(String.valueOf(ttl));
+ }
+ return true;
+ }
+ return false;
+ }
+
+ private void updateUi(@NonNull final Provisioner provisioner) {
+ provisionerName.setText(provisioner.getProvisionerName());
+ if (provisioner.getProvisionerAddress() == null) {
+ provisionerUnicast.setText(R.string.unicast_address_unassigned);
+ } else {
+ provisionerUnicast.setText(MeshAddress.formatAddress(provisioner.getProvisionerAddress(), true));
+ }
+ if (provisioner.isLastSelected()) {
+ selectProvisioner.setVisibility(View.GONE);
+ } else {
+ checkBox.setChecked(provisioner.isLastSelected());
+ }
+ unicastRangeView.clearRanges();
+ groupRangeView.clearRanges();
+ sceneRangeView.clearRanges();
+ unicastRangeView.addRanges(provisioner.getAllocatedUnicastRanges());
+ groupRangeView.addRanges(provisioner.getAllocatedGroupRanges());
+ sceneRangeView.addRanges(provisioner.getAllocatedSceneRanges());
+
+ final MeshNetwork network = mViewModel.getMeshManagerApi().getMeshNetwork();
+ if (network != null) {
+ final String ttl = String.valueOf(provisioner.getGlobalTtl());
+ provisionerTtl.setText(ttl);
+
+ unicastRangeView.clearOtherRanges();
+ groupRangeView.clearOtherRanges();
+ sceneRangeView.clearOtherRanges();
+ for (Provisioner other : network.getProvisioners()) {
+ if (!other.getProvisionerUuid().equalsIgnoreCase(provisioner.getProvisionerUuid())) {
+ unicastRangeView.addOtherRanges(other.getAllocatedUnicastRanges());
+ groupRangeView.addOtherRanges(other.getAllocatedGroupRanges());
+ sceneRangeView.addOtherRanges(other.getAllocatedSceneRanges());
+ }
+ }
+ }
+ }
+
+ private boolean save() {
+ final MeshNetwork network = mViewModel.getMeshManagerApi().getMeshNetwork();
+ if (network != null) {
+ try {
+ return network.updateProvisioner(mProvisioner);
+ } catch (IllegalArgumentException ex) {
+ final DialogFragmentError fragment = DialogFragmentError.
+ newInstance(getString(R.string.title_error), ex.getMessage());
+ fragment.show(getSupportFragmentManager(), null);
+ }
+ }
+ return false;
+ }
+
+ private boolean save(@NonNull final Provisioner provisioner) {
+ final MeshNetwork network = mViewModel.getMeshManagerApi().getMeshNetwork();
+ if (network != null) {
+ return network.updateProvisioner(provisioner);
+ }
+ return false;
+ }
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/provisioners/ProvisionersActivity.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/provisioners/ProvisionersActivity.java
new file mode 100644
index 000000000..0bd522c00
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/provisioners/ProvisionersActivity.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2018, Nordic Semiconductor
+ * 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 no.nordicsemi.android.nrfmeshprovisioner.provisioners;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.ScrollView;
+import android.widget.TextView;
+
+import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton;
+import com.google.android.material.snackbar.Snackbar;
+
+import javax.inject.Inject;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.Toolbar;
+import androidx.cardview.widget.CardView;
+import androidx.coordinatorlayout.widget.CoordinatorLayout;
+import androidx.core.content.ContextCompat;
+import androidx.lifecycle.ViewModelProvider;
+import androidx.lifecycle.ViewModelProviders;
+import androidx.recyclerview.widget.ItemTouchHelper;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import butterknife.BindView;
+import butterknife.ButterKnife;
+import no.nordicsemi.android.meshprovisioner.MeshNetwork;
+import no.nordicsemi.android.meshprovisioner.Provisioner;
+import no.nordicsemi.android.meshprovisioner.utils.MeshAddress;
+import no.nordicsemi.android.nrfmeshprovisioner.R;
+import no.nordicsemi.android.nrfmeshprovisioner.di.Injectable;
+import no.nordicsemi.android.nrfmeshprovisioner.provisioners.adapter.ProvisionerAdapter;
+import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.ProvisionersViewModel;
+import no.nordicsemi.android.nrfmeshprovisioner.widgets.ItemTouchHelperAdapter;
+import no.nordicsemi.android.nrfmeshprovisioner.widgets.RemovableItemTouchHelperCallback;
+import no.nordicsemi.android.nrfmeshprovisioner.widgets.RemovableViewHolder;
+
+public class ProvisionersActivity extends AppCompatActivity implements Injectable,
+ ProvisionerAdapter.OnItemClickListener,
+ ItemTouchHelperAdapter {
+
+ @Inject
+ ViewModelProvider.Factory mViewModelFactory;
+
+ //UI Bindings
+ @BindView(R.id.toolbar)
+ Toolbar mToolbar;
+ @BindView(R.id.container)
+ CoordinatorLayout container;
+ @BindView(R.id.scroll_container)
+ ScrollView scrollView;
+ @BindView(R.id.provisioners_card)
+ CardView mProvisionersCard;
+ @BindView(R.id.recycler_view_provisioners)
+ RecyclerView mRecyclerView;
+
+ private ProvisionersViewModel mViewModel;
+ private ProvisionerAdapter mAdapter;
+
+ @Override
+ protected void onCreate(@Nullable final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_provisioners);
+ mViewModel = ViewModelProviders.of(this, mViewModelFactory).get(ProvisionersViewModel.class);
+
+ //Bind ui
+ ButterKnife.bind(this);
+
+ setSupportActionBar(mToolbar);
+ //noinspection ConstantConditions
+ getSupportActionBar().setTitle(R.string.title_manage_provisioners);
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+
+ final View containerProvisioner = findViewById(R.id.container_current_provisioner);
+ containerProvisioner.findViewById(R.id.image).
+ setBackground(ContextCompat.getDrawable(this, R.drawable.ic_account_key_black_alpha_24dp));
+ final TextView provisionerTitle = containerProvisioner.findViewById(R.id.title);
+ final TextView provisionerView = containerProvisioner.findViewById(R.id.text);
+ provisionerView.setVisibility(View.VISIBLE);
+
+ final ExtendedFloatingActionButton fab = findViewById(R.id.fab_add);
+
+ mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
+ mRecyclerView.setItemAnimator(null);
+
+ final ItemTouchHelper.Callback itemTouchHelperCallback = new RemovableItemTouchHelperCallback(this);
+ final ItemTouchHelper mItemTouchHelper = new ItemTouchHelper(itemTouchHelperCallback);
+ mItemTouchHelper.attachToRecyclerView(mRecyclerView);
+ mAdapter = new ProvisionerAdapter(this, mViewModel.getNetworkLiveData());
+ mAdapter.setOnItemClickListener(this);
+ mRecyclerView.setAdapter(mAdapter);
+
+ mViewModel.getNetworkLiveData().observe(this, meshNetworkLiveData -> {
+ final MeshNetwork network = meshNetworkLiveData.getMeshNetwork();
+ if (network != null) {
+ final Provisioner provisioner = network.getSelectedProvisioner();
+ provisionerTitle.setText(provisioner.getProvisionerName());
+ if (provisioner.getProvisionerAddress() == null) {
+ provisionerView.setText(R.string.unicast_address_unassigned);
+ } else {
+ if (MeshAddress.isValidUnicastAddress(provisioner.getProvisionerAddress())) {
+ provisionerView.setText(getString(R.string.unicast_address,
+ MeshAddress.formatAddress(provisioner.getProvisionerAddress(), true)));
+ } else {
+ provisionerView.setText(R.string.unicast_address_unassigned);
+ }
+ }
+
+ if (network.getProvisioners().size() > 1) {
+ mProvisionersCard.setVisibility(View.VISIBLE);
+ } else {
+ mProvisionersCard.setVisibility(View.GONE);
+ }
+ }
+ });
+
+ containerProvisioner.setOnClickListener(v -> {
+ final MeshNetwork network = mViewModel.getNetworkLiveData().getMeshNetwork();
+ if (network != null) {
+ final Provisioner provisioner = network.getSelectedProvisioner();
+ mViewModel.setSelectedProvisioner(provisioner);
+ final Intent intent = new Intent(this, EditProvisionerActivity.class);
+ startActivity(intent);
+ }
+ });
+
+ fab.setOnClickListener(v -> {
+ final Intent intent = new Intent(this, AddProvisionerActivity.class);
+ startActivity(intent);
+ });
+
+ scrollView.getViewTreeObserver().addOnScrollChangedListener(() -> {
+ if (scrollView.getScrollY() == 0) {
+ fab.extend(true);
+ } else {
+ fab.shrink(true);
+ }
+ });
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(final Menu menu) {
+ return super.onCreateOptionsMenu(menu);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(final MenuItem item) {
+ if (item.getItemId() == android.R.id.home) {
+ onBackPressed();
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void onItemClick(final int position, @NonNull final Provisioner provisioner) {
+ mViewModel.setSelectedProvisioner(provisioner);
+ final Intent intent = new Intent(this, EditProvisionerActivity.class);
+ startActivity(intent);
+ }
+
+ @Override
+ public void onItemDismiss(final RemovableViewHolder viewHolder) {
+ final int position = viewHolder.getAdapterPosition();
+ final Provisioner provisioner = mAdapter.getItem(position);
+ final MeshNetwork network = mViewModel.getNetworkLiveData().getMeshNetwork();
+ try {
+ if (network != null) {
+ if (network.removeProvisioner(provisioner)) {
+ displaySnackBar(provisioner);
+ }
+ }
+ } catch (Exception ex) {
+ mAdapter.notifyDataSetChanged();
+ mViewModel.displaySnackBar(this, container, ex.getMessage(), Snackbar.LENGTH_LONG);
+ }
+ }
+
+ @Override
+ public void onItemDismissFailed(final RemovableViewHolder viewHolder) {
+
+ }
+
+ private void displaySnackBar(@NonNull final Provisioner provisioner) {
+ Snackbar.make(container, getString(R.string.provisioner_deleted), Snackbar.LENGTH_LONG)
+ .setAction(getString(R.string.undo), view -> {
+ final MeshNetwork network = mViewModel.getNetworkLiveData().getMeshNetwork();
+ if (network != null) {
+ network.addProvisioner(provisioner);
+ }
+ })
+ .setActionTextColor(getResources().getColor(R.color.colorPrimaryDark))
+ .show();
+ }
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/provisioners/RangeListener.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/provisioners/RangeListener.java
new file mode 100644
index 000000000..1b4c33e55
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/provisioners/RangeListener.java
@@ -0,0 +1,10 @@
+package no.nordicsemi.android.nrfmeshprovisioner.provisioners;
+
+import androidx.annotation.NonNull;
+import no.nordicsemi.android.meshprovisioner.Range;
+
+public interface RangeListener {
+
+ void addRange(@NonNull final Range range);
+
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/provisioners/RangesActivity.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/provisioners/RangesActivity.java
new file mode 100644
index 000000000..f76af0b72
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/provisioners/RangesActivity.java
@@ -0,0 +1,452 @@
+/*
+ * Copyright (c) 2018, Nordic Semiconductor
+ * 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 no.nordicsemi.android.nrfmeshprovisioner.provisioners;
+
+import android.os.Bundle;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.TextView;
+
+import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton;
+import com.google.android.material.snackbar.Snackbar;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.Toolbar;
+import androidx.coordinatorlayout.widget.CoordinatorLayout;
+import androidx.lifecycle.ViewModelProvider;
+import androidx.lifecycle.ViewModelProviders;
+import androidx.recyclerview.widget.DefaultItemAnimator;
+import androidx.recyclerview.widget.DividerItemDecoration;
+import androidx.recyclerview.widget.ItemTouchHelper;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import butterknife.BindView;
+import butterknife.ButterKnife;
+import no.nordicsemi.android.meshprovisioner.AddressRange;
+import no.nordicsemi.android.meshprovisioner.AllocatedGroupRange;
+import no.nordicsemi.android.meshprovisioner.AllocatedSceneRange;
+import no.nordicsemi.android.meshprovisioner.AllocatedUnicastRange;
+import no.nordicsemi.android.meshprovisioner.MeshNetwork;
+import no.nordicsemi.android.meshprovisioner.Provisioner;
+import no.nordicsemi.android.meshprovisioner.Range;
+import no.nordicsemi.android.meshprovisioner.utils.MeshAddress;
+import no.nordicsemi.android.nrfmeshprovisioner.R;
+import no.nordicsemi.android.nrfmeshprovisioner.di.Injectable;
+import no.nordicsemi.android.nrfmeshprovisioner.provisioners.adapter.RangeAdapter;
+import no.nordicsemi.android.nrfmeshprovisioner.provisioners.dialogs.DialogFragmentGroupRange;
+import no.nordicsemi.android.nrfmeshprovisioner.provisioners.dialogs.DialogFragmentSceneRange;
+import no.nordicsemi.android.nrfmeshprovisioner.provisioners.dialogs.DialogFragmentUnicastRange;
+import no.nordicsemi.android.nrfmeshprovisioner.utils.Utils;
+import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.RangesViewModel;
+import no.nordicsemi.android.nrfmeshprovisioner.widgets.ItemTouchHelperAdapter;
+import no.nordicsemi.android.nrfmeshprovisioner.widgets.RangeView;
+import no.nordicsemi.android.nrfmeshprovisioner.widgets.RemovableItemTouchHelperCallback;
+import no.nordicsemi.android.nrfmeshprovisioner.widgets.RemovableViewHolder;
+
+public class RangesActivity extends AppCompatActivity implements Injectable,
+ RangeAdapter.OnItemClickListener,
+ ItemTouchHelperAdapter,
+ RangeListener {
+
+ @Inject
+ ViewModelProvider.Factory mViewModelFactory;
+
+ //UI Bindings
+ @BindView(android.R.id.empty)
+ View mEmptyView;
+ @BindView(R.id.container)
+ CoordinatorLayout container;
+ @BindView(R.id.fab_resolve)
+ ExtendedFloatingActionButton mFabResolve;
+ private RangeView mRangeView;
+ private int mType;
+ private RangesViewModel mViewModel;
+ private RangeAdapter mRangeAdapter;
+ private Provisioner mProvisioner;
+
+ private final Comparator addressRangeComparator = (addressRange1, addressRange2) ->
+ Integer.compare(addressRange1.getLowAddress(), addressRange2.getLowAddress());
+
+ private final Comparator sceneRangeComparator = (sceneRange1, sceneRange2) ->
+ Integer.compare(sceneRange1.getFirstScene(), sceneRange2.getFirstScene());
+
+ @SuppressWarnings("ConstantConditions")
+ @Override
+ protected void onCreate(@Nullable final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_ranges);
+ ButterKnife.bind(this);
+ mViewModel = ViewModelProviders.of(this, mViewModelFactory).get(RangesViewModel.class);
+ mType = getIntent().getExtras().getInt(Utils.RANGE_TYPE);
+
+ //Bind ui
+ final Toolbar toolbar = findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+
+ final RecyclerView recyclerView = findViewById(R.id.recycler_view);
+ final View rangesContainer = findViewById(R.id.info_ranges);
+ rangesContainer.findViewById(R.id.container).setVisibility(View.VISIBLE);
+ mRangeView = rangesContainer.findViewById(R.id.range);
+ final TextView startAddress = rangesContainer.findViewById(R.id.start_address);
+ final TextView endAddress = rangesContainer.findViewById(R.id.end_address);
+ final ExtendedFloatingActionButton fab_add = findViewById(R.id.fab_add);
+
+ mProvisioner = mViewModel.getSelectedProvisioner().getValue();
+
+ switch (mType) {
+ case Utils.GROUP_RANGE:
+ startAddress.setText(MeshAddress.formatAddress(MeshAddress.START_GROUP_ADDRESS, true));
+ endAddress.setText(MeshAddress.formatAddress(MeshAddress.END_GROUP_ADDRESS, true));
+ getSupportActionBar().setTitle(R.string.title_edit_group_ranges);
+ mRangeAdapter = new RangeAdapter(this,
+ mProvisioner.getProvisionerUuid(),
+ mProvisioner.getAllocatedGroupRanges(),
+ mViewModel.getNetworkLiveData().getProvisioners());
+ break;
+ case Utils.SCENE_RANGE:
+ startAddress.setText(MeshAddress.formatAddress(0x0000, true));
+ endAddress.setText(MeshAddress.formatAddress(0xFFFF, true));
+ getSupportActionBar().setTitle(R.string.title_edit_scene_ranges);
+ mRangeAdapter = new RangeAdapter(this,
+ mProvisioner.getProvisionerUuid(),
+ mProvisioner.getAllocatedSceneRanges(),
+ mViewModel.getNetworkLiveData().getProvisioners());
+ break;
+ default:
+ case Utils.UNICAST_RANGE:
+ startAddress.setText(MeshAddress.formatAddress(MeshAddress.START_UNICAST_ADDRESS, true));
+ endAddress.setText(MeshAddress.formatAddress(MeshAddress.END_UNICAST_ADDRESS, true));
+ getSupportActionBar().setTitle(R.string.title_edit_unicast_ranges);
+ mRangeAdapter = new RangeAdapter(this,
+ mProvisioner.getProvisionerUuid(),
+ mProvisioner.getAllocatedUnicastRanges(),
+ mViewModel.getNetworkLiveData().getProvisioners());
+ break;
+ }
+
+ mRangeAdapter.setOnItemClickListener(this);
+
+ recyclerView.setLayoutManager(new LinearLayoutManager(this));
+ final DividerItemDecoration dividerItemDecoration =
+ new DividerItemDecoration(recyclerView.getContext(), DividerItemDecoration.VERTICAL);
+ recyclerView.addItemDecoration(dividerItemDecoration);
+ recyclerView.setItemAnimator(new DefaultItemAnimator());
+ recyclerView.setAdapter(mRangeAdapter);
+ final ItemTouchHelper.Callback itemTouchHelperCallback = new RemovableItemTouchHelperCallback(this);
+ final ItemTouchHelper itemTouchHelper = new ItemTouchHelper(itemTouchHelperCallback);
+ itemTouchHelper.attachToRecyclerView(recyclerView);
+
+ fab_add.setOnClickListener(v -> {
+ switch (mType) {
+ case Utils.GROUP_RANGE:
+ final DialogFragmentGroupRange groupRange = DialogFragmentGroupRange.newInstance(null);
+ groupRange.show(getSupportFragmentManager(), null);
+ break;
+ case Utils.SCENE_RANGE:
+ final DialogFragmentSceneRange sceneRange = DialogFragmentSceneRange.newInstance(null);
+ sceneRange.show(getSupportFragmentManager(), null);
+ break;
+ default:
+ case Utils.UNICAST_RANGE:
+ final DialogFragmentUnicastRange unicastRange = DialogFragmentUnicastRange.newInstance(null);
+ unicastRange.show(getSupportFragmentManager(), null);
+ break;
+ }
+ });
+
+ mFabResolve.setOnClickListener(v -> resolveRanges());
+
+ updateRanges();
+ updateOtherRanges();
+ updateEmptyView();
+ updateResolveFab();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(final MenuItem item) {
+ if (item.getItemId() == android.R.id.home) {
+ onBackPressed();
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void onBackPressed() {
+ super.onBackPressed();
+ mViewModel.setSelectedProvisioner(mProvisioner);
+ }
+
+ @Override
+ public void onItemClick(final int position, @NonNull final Range range) {
+ if (range instanceof AllocatedUnicastRange) {
+ final DialogFragmentUnicastRange fragment = DialogFragmentUnicastRange.newInstance((AllocatedUnicastRange) range);
+ fragment.show(getSupportFragmentManager(), null);
+ } else if (range instanceof AllocatedGroupRange) {
+ final DialogFragmentGroupRange fragment = DialogFragmentGroupRange.newInstance((AllocatedGroupRange) range);
+ fragment.show(getSupportFragmentManager(), null);
+ } else {
+ final DialogFragmentSceneRange fragment = DialogFragmentSceneRange.newInstance((AllocatedSceneRange) range);
+ fragment.show(getSupportFragmentManager(), null);
+ }
+ }
+
+ @Override
+ public void addRange(@NonNull final Range range) {
+ if (mProvisioner != null) {
+ mProvisioner.addRange(range);
+ updateData(range);
+ updateRanges();
+ updateOtherRanges();
+ updateEmptyView();
+ updateResolveFab();
+ }
+ }
+
+ @Override
+ public void onItemDismiss(final RemovableViewHolder viewHolder) {
+ if (mProvisioner != null) {
+ final int position = viewHolder.getAdapterPosition();
+ try {
+ final Range range = mRangeAdapter.getItem(position);
+ mRangeAdapter.removeItem(position);
+ displaySnackBar(position, range);
+ mProvisioner.removeRange(range);
+ updateRanges();
+ updateOtherRanges();
+ updateEmptyView();
+ updateResolveFab();
+ } catch (Exception ex) {
+ mRangeAdapter.notifyDataSetChanged();
+ mViewModel.displaySnackBar(this, container, ex.getMessage(), Snackbar.LENGTH_LONG);
+ }
+ }
+ }
+
+ @Override
+ public void onItemDismissFailed(final RemovableViewHolder viewHolder) {
+
+ }
+
+ private void updateRanges() {
+ if (mProvisioner != null) {
+ mRangeView.clearRanges();
+ switch (mType) {
+ case Utils.GROUP_RANGE:
+ mRangeView.addRanges(mProvisioner.getAllocatedGroupRanges());
+ break;
+ case Utils.SCENE_RANGE:
+ mRangeView.addRanges(mProvisioner.getAllocatedSceneRanges());
+ break;
+ default:
+ case Utils.UNICAST_RANGE:
+ mRangeView.addRanges(mProvisioner.getAllocatedUnicastRanges());
+ break;
+ }
+ }
+ }
+
+ private void updateOtherRanges() {
+ final MeshNetwork network = mViewModel.getMeshManagerApi().getMeshNetwork();
+ if (network != null) {
+ mRangeView.clearOtherRanges();
+ for (Provisioner other : network.getProvisioners()) {
+ if (!other.getProvisionerUuid().equalsIgnoreCase(mProvisioner.getProvisionerUuid()))
+ switch (mType) {
+ case Utils.GROUP_RANGE:
+ mRangeView.addOtherRanges(other.getAllocatedGroupRanges());
+ break;
+ case Utils.SCENE_RANGE:
+ mRangeView.addOtherRanges(other.getAllocatedSceneRanges());
+ break;
+ default:
+ case Utils.UNICAST_RANGE:
+ mRangeView.addOtherRanges(other.getAllocatedUnicastRanges());
+ break;
+ }
+ }
+ }
+ }
+
+ private void updateResolveFab() {
+ final MeshNetwork network = mViewModel.getMeshManagerApi().getMeshNetwork();
+ if (network != null) {
+ for (Provisioner other : network.getProvisioners()) {
+ if (!other.getProvisionerUuid().equalsIgnoreCase(mProvisioner.getProvisionerUuid()))
+ switch (mType) {
+ case Utils.GROUP_RANGE:
+ if (mProvisioner.hasOverlappingGroupRanges(other.getAllocatedGroupRanges())) {
+ mFabResolve.show(true);
+ return;
+ } else {
+ mFabResolve.hide(true);
+ }
+ break;
+ case Utils.SCENE_RANGE:
+ if (mProvisioner.hasOverlappingSceneRanges(other.getAllocatedSceneRanges())) {
+ mFabResolve.show(true);
+ return;
+ } else {
+ mFabResolve.hide(true);
+ }
+ break;
+ default:
+ case Utils.UNICAST_RANGE:
+ if (mProvisioner.hasOverlappingUnicastRanges(other.getAllocatedUnicastRanges())) {
+ mFabResolve.show(true);
+ return;
+ } else {
+ mFabResolve.hide(true);
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ private void updateEmptyView() {
+ // Show the empty view
+ if (mRangeAdapter.isEmpty()) {
+ mEmptyView.setVisibility(View.VISIBLE);
+ } else {
+ mEmptyView.setVisibility(View.GONE);
+ }
+ }
+
+ private void updateData(@NonNull final Range range) {
+ if (mProvisioner != null) {
+ if (range instanceof AllocatedUnicastRange) {
+ mRangeAdapter.updateData(mProvisioner.getAllocatedUnicastRanges());
+ } else if (range instanceof AllocatedGroupRange) {
+ mRangeAdapter.updateData(mProvisioner.getAllocatedGroupRanges());
+ } else {
+ mRangeAdapter.updateData(mProvisioner.getAllocatedSceneRanges());
+ }
+ }
+ }
+
+ private void displaySnackBar(final int position, final Range range) {
+ Snackbar.make(container, getString(R.string.range_deleted), Snackbar.LENGTH_LONG)
+ .setAction(getString(R.string.undo), view -> {
+ mRangeAdapter.addItem(position, range);
+ mProvisioner.addRange(range);
+ updateRanges();
+ updateOtherRanges();
+ updateEmptyView();
+ updateResolveFab();
+ })
+ .setActionTextColor(getResources().getColor(R.color.colorPrimaryDark))
+ .show();
+ }
+
+ private void resolveRanges() {
+ switch (mType) {
+ case Utils.GROUP_RANGE:
+ removeConflictingGroupRanges();
+ break;
+ case Utils.SCENE_RANGE:
+ removeConflictingSceneRanges();
+ break;
+ default:
+ case Utils.UNICAST_RANGE:
+ removeConflictingUnicastRanges();
+ break;
+ }
+ }
+
+ private void removeConflictingUnicastRanges() {
+ if (mProvisioner != null) {
+ List ranges = new ArrayList<>(mProvisioner.getAllocatedUnicastRanges());
+ Collections.sort(ranges, addressRangeComparator);
+ for (Provisioner p : mViewModel.getNetworkLiveData().getProvisioners()) {
+ if(!p.getProvisionerUuid().equalsIgnoreCase(mProvisioner.getProvisionerUuid())) {
+ final List otherRanges = new ArrayList<>(p.getAllocatedUnicastRanges());
+ Collections.sort(otherRanges, addressRangeComparator);
+ for (AllocatedUnicastRange otherRange : otherRanges) {
+ ranges = AddressRange.minus(ranges, otherRange);
+ }
+ }
+ }
+ mProvisioner.setAllocatedUnicastRanges(ranges);
+ mRangeAdapter.updateData(ranges);
+ updateRanges();
+ updateOtherRanges();
+ updateEmptyView();
+ updateResolveFab();
+ }
+ }
+
+ private void removeConflictingGroupRanges() {
+ if (mProvisioner != null) {
+ List ranges = new ArrayList<>(mProvisioner.getAllocatedGroupRanges());
+ Collections.sort(ranges, addressRangeComparator);
+ for (Provisioner p : mViewModel.getNetworkLiveData().getProvisioners()) {
+ final List otherRanges = new ArrayList<>(p.getAllocatedGroupRanges());
+ Collections.sort(otherRanges, addressRangeComparator);
+ for (AllocatedGroupRange otherRange : otherRanges) {
+ ranges = AddressRange.minus(ranges, otherRange);
+ }
+ }
+
+ Collections.sort(ranges, addressRangeComparator);
+ mProvisioner.setAllocatedGroupRanges(ranges);
+ mRangeAdapter.updateData(ranges);
+ updateRanges();
+ updateOtherRanges();
+ updateEmptyView();
+ updateResolveFab();
+ }
+ }
+
+ private void removeConflictingSceneRanges() {
+ if (mProvisioner != null) {
+ List ranges = new ArrayList<>(mProvisioner.getAllocatedSceneRanges());
+ Collections.sort(ranges, sceneRangeComparator);
+ for (Provisioner p : mViewModel.getNetworkLiveData().getProvisioners()) {
+ final List otherRanges = new ArrayList<>(p.getAllocatedSceneRanges());
+ Collections.sort(otherRanges, sceneRangeComparator);
+ for (AllocatedSceneRange otherRange : otherRanges) {
+ ranges = AllocatedSceneRange.minus(ranges, otherRange);
+ }
+ }
+
+ Collections.sort(ranges, sceneRangeComparator);
+ mProvisioner.setAllocatedSceneRanges(ranges);
+ mRangeAdapter.updateData(ranges);
+ updateRanges();
+ updateOtherRanges();
+ updateEmptyView();
+ updateResolveFab();
+ }
+ }
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/provisioners/adapter/ProvisionerAdapter.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/provisioners/adapter/ProvisionerAdapter.java
new file mode 100644
index 000000000..bce5980bb
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/provisioners/adapter/ProvisionerAdapter.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2018, Nordic Semiconductor
+ * 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 no.nordicsemi.android.nrfmeshprovisioner.provisioners.adapter;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import androidx.annotation.NonNull;
+import androidx.core.content.ContextCompat;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.recyclerview.widget.RecyclerView;
+import butterknife.BindView;
+import butterknife.ButterKnife;
+import no.nordicsemi.android.meshprovisioner.MeshNetwork;
+import no.nordicsemi.android.meshprovisioner.Provisioner;
+import no.nordicsemi.android.meshprovisioner.utils.MeshAddress;
+import no.nordicsemi.android.nrfmeshprovisioner.R;
+import no.nordicsemi.android.nrfmeshprovisioner.viewmodels.MeshNetworkLiveData;
+import no.nordicsemi.android.nrfmeshprovisioner.widgets.RemovableViewHolder;
+
+public class ProvisionerAdapter extends RecyclerView.Adapter {
+
+ private final List mProvisioners = new ArrayList<>();
+ private final Context mContext;
+ private OnItemClickListener mOnItemClickListener;
+
+ public ProvisionerAdapter(@NonNull final Context context, @NonNull final MeshNetworkLiveData meshNetworkLiveData) {
+ this.mContext = context;
+ meshNetworkLiveData.observe((LifecycleOwner) context, networkData -> {
+ final MeshNetwork network = meshNetworkLiveData.getMeshNetwork();
+ final List provisioners = network.getProvisioners();
+ mProvisioners.clear();
+ mProvisioners.addAll(provisioners);
+ final Provisioner provisioner = network.getSelectedProvisioner();
+ mProvisioners.remove(provisioner);
+ notifyDataSetChanged();
+ });
+ }
+
+ public void setOnItemClickListener(final ProvisionerAdapter.OnItemClickListener listener) {
+ mOnItemClickListener = listener;
+ }
+
+ @NonNull
+ @Override
+ public ProvisionerAdapter.ViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int viewType) {
+ final View layoutView = LayoutInflater.from(mContext).inflate(R.layout.removable_row_item1, parent, false);
+ return new ProvisionerAdapter.ViewHolder(layoutView);
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull final ProvisionerAdapter.ViewHolder holder, final int position) {
+ final Provisioner provisioner = mProvisioners.get(position);
+ holder.provisionerName.setText(provisioner.getProvisionerName());
+ if (provisioner.getProvisionerAddress() == null) {
+ holder.provisionerSummary.setText(mContext.getString(R.string.unicast_address,
+ mContext.getString(R.string.address_unassigned)));
+ } else {
+ holder.provisionerSummary.setText(mContext.getString(R.string.unicast_address,
+ MeshAddress.formatAddress(provisioner.getProvisionerAddress(), true)));
+ }
+ }
+
+ @Override
+ public long getItemId(final int position) {
+ return position;
+ }
+
+ @Override
+ public int getItemCount() {
+ return mProvisioners.size();
+ }
+
+ public boolean isEmpty() {
+ return getItemCount() == 0;
+ }
+
+ public Provisioner getItem(final int position) {
+ return mProvisioners.get(position);
+ }
+
+ @FunctionalInterface
+ public interface OnItemClickListener {
+ void onItemClick(final int position, @NonNull final Provisioner provisioner);
+ }
+
+ final class ViewHolder extends RemovableViewHolder {
+
+ @BindView(R.id.icon)
+ ImageView icon;
+ @BindView(R.id.title)
+ TextView provisionerName;
+ @BindView(R.id.subtitle)
+ TextView provisionerSummary;
+
+ private ViewHolder(final View view) {
+ super(view);
+ ButterKnife.bind(this, view);
+ icon.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.ic_account_key_black_alpha_24dp));
+
+ view.findViewById(R.id.removable).setOnClickListener(v -> {
+ if (mOnItemClickListener != null) {
+ final Provisioner provisioner = mProvisioners.get(getAdapterPosition());
+ mOnItemClickListener.onItemClick(getAdapterPosition(), provisioner);
+ }
+ });
+ }
+ }
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/provisioners/adapter/RangeAdapter.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/provisioners/adapter/RangeAdapter.java
new file mode 100644
index 000000000..81f485dd7
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/provisioners/adapter/RangeAdapter.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2018, Nordic Semiconductor
+ * 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 no.nordicsemi.android.nrfmeshprovisioner.provisioners.adapter;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+import butterknife.BindView;
+import butterknife.ButterKnife;
+import no.nordicsemi.android.meshprovisioner.AddressRange;
+import no.nordicsemi.android.meshprovisioner.AllocatedGroupRange;
+import no.nordicsemi.android.meshprovisioner.AllocatedSceneRange;
+import no.nordicsemi.android.meshprovisioner.AllocatedUnicastRange;
+import no.nordicsemi.android.meshprovisioner.Provisioner;
+import no.nordicsemi.android.meshprovisioner.Range;
+import no.nordicsemi.android.meshprovisioner.utils.MeshAddress;
+import no.nordicsemi.android.nrfmeshprovisioner.R;
+import no.nordicsemi.android.nrfmeshprovisioner.widgets.RangeView;
+import no.nordicsemi.android.nrfmeshprovisioner.widgets.RemovableViewHolder;
+
+public class RangeAdapter extends RecyclerView.Adapter {
+
+ private final ArrayList mRanges;
+ private final List mProvisioners;
+ private final Context mContext;
+ private final String mUuid;
+ private OnItemClickListener mOnItemClickListener;
+
+ public RangeAdapter(@NonNull final Context context, @NonNull final String uuid, @NonNull final List extends Range> ranges, @NonNull final List provisioners) {
+ mContext = context;
+ mUuid = uuid;
+ mRanges = new ArrayList<>(ranges);
+ mProvisioners = provisioners;
+ }
+
+ public void setOnItemClickListener(final RangeAdapter.OnItemClickListener listener) {
+ mOnItemClickListener = listener;
+ }
+
+ public void updateData(@NonNull List extends Range> ranges) {
+ mRanges.clear();
+ mRanges.addAll(ranges);
+ notifyDataSetChanged();
+ }
+
+ @NonNull
+ @Override
+ public RangeAdapter.ViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int viewType) {
+ final View layoutView = LayoutInflater.from(mContext).inflate(R.layout.range_item, parent, false);
+ return new RangeAdapter.ViewHolder(layoutView);
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull final RangeAdapter.ViewHolder holder, final int position) {
+ final Range range = mRanges.get(position);
+ final String low, high;
+ if (range instanceof AddressRange) {
+ low = MeshAddress.formatAddress(((AddressRange) range).getLowAddress(), true);
+ high = MeshAddress.formatAddress(((AddressRange) range).getHighAddress(), true);
+ } else {
+ low = MeshAddress.formatAddress(((AllocatedSceneRange) range).getFirstScene(), true);
+ high = MeshAddress.formatAddress(((AllocatedSceneRange) range).getLastScene(), true);
+ }
+ holder.rangeValue.setText(mContext.getString(R.string.range_adapter_format, low, high));
+ holder.rangeView.clearRanges();
+ holder.rangeView.addRange(range);
+ addOverlappingRanges(range, holder.rangeView);
+ }
+
+ @Override
+ public long getItemId(final int position) {
+ return position;
+ }
+
+ @Override
+ public int getItemCount() {
+ return mRanges.size();
+ }
+
+ public boolean isEmpty() {
+ return getItemCount() == 0;
+ }
+
+ public Range getItem(final int position) {
+ return mRanges.get(position);
+ }
+
+ public List getItems() {
+ return mRanges;
+ }
+
+ public void addItem(final int position, @NonNull final Range range) {
+ mRanges.add(position, range);
+ notifyItemInserted(position);
+ }
+
+ public void removeItem(final int position) {
+ mRanges.remove(position);
+ notifyItemRemoved(position);
+ }
+
+ private void addOverlappingRanges(@NonNull final Range range, @NonNull final RangeView rangeView) {
+ rangeView.clearOtherRanges();
+ for (Provisioner p : mProvisioners) {
+ if (!p.getProvisionerUuid().equalsIgnoreCase(mUuid)) {
+ if (range instanceof AllocatedUnicastRange) {
+ for (AllocatedUnicastRange otherRange : p.getAllocatedUnicastRanges()) {
+ if (range.overlaps(otherRange)) {
+ rangeView.addOtherRange(otherRange);
+ }
+ }
+ } else if (range instanceof AllocatedGroupRange) {
+ for (AllocatedGroupRange otherRange : p.getAllocatedGroupRanges()) {
+ if (range.overlaps(otherRange)) {
+ rangeView.addOtherRange(otherRange);
+ }
+ }
+ } else {
+ for (AllocatedSceneRange otherRange : p.getAllocatedSceneRanges()) {
+ if (range.overlaps(otherRange)) {
+ rangeView.addOtherRange(otherRange);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @FunctionalInterface
+ public interface OnItemClickListener {
+ void onItemClick(final int position, @NonNull final Range range);
+ }
+
+ final class ViewHolder extends RemovableViewHolder {
+
+ @BindView(R.id.range_text)
+ TextView rangeValue;
+ @BindView(R.id.range)
+ RangeView rangeView;
+
+ private ViewHolder(final View view) {
+ super(view);
+ ButterKnife.bind(this, view);
+ view.findViewById(R.id.removable).setOnClickListener(v -> {
+ if (mOnItemClickListener != null) {
+ mOnItemClickListener.onItemClick(getAdapterPosition(), mRanges.get(getAdapterPosition()));
+ }
+ });
+ }
+ }
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/provisioners/dialogs/DialogFragmentGroupRange.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/provisioners/dialogs/DialogFragmentGroupRange.java
new file mode 100644
index 000000000..45640cc81
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/provisioners/dialogs/DialogFragmentGroupRange.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2018, Nordic Semiconductor
+ * 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 no.nordicsemi.android.nrfmeshprovisioner.provisioners.dialogs;
+
+import android.annotation.SuppressLint;
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.text.Editable;
+import android.text.TextUtils;
+import android.text.TextWatcher;
+import android.text.method.KeyListener;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.TextView;
+
+import com.google.android.material.textfield.TextInputEditText;
+import com.google.android.material.textfield.TextInputLayout;
+
+import org.w3c.dom.Text;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.DialogFragment;
+import butterknife.BindView;
+import butterknife.ButterKnife;
+import no.nordicsemi.android.meshprovisioner.AllocatedGroupRange;
+import no.nordicsemi.android.meshprovisioner.utils.MeshAddress;
+import no.nordicsemi.android.nrfmeshprovisioner.R;
+import no.nordicsemi.android.nrfmeshprovisioner.provisioners.RangeListener;
+import no.nordicsemi.android.nrfmeshprovisioner.utils.HexKeyListener;
+
+public class DialogFragmentGroupRange extends DialogFragment {
+
+ private static final String RANGE = "RANGE";
+ //UI Bindings
+ @BindView(R.id.low_address_layout)
+ TextInputLayout lowAddressInputLayout;
+ @BindView(R.id.low_address_input)
+ TextInputEditText lowAddressInput;
+ @BindView(R.id.high_address_layout)
+ TextInputLayout highAddressInputLayout;
+ @BindView(R.id.high_address_input)
+ TextInputEditText highAddressInput;
+
+ private AllocatedGroupRange mRange;
+
+ public static DialogFragmentGroupRange newInstance(@Nullable final AllocatedGroupRange range) {
+ DialogFragmentGroupRange fragment = new DialogFragmentGroupRange();
+ final Bundle args = new Bundle();
+ args.putParcelable(RANGE, range);
+ fragment.setArguments(args);
+ return fragment;
+ }
+
+ @Override
+ public void onCreate(@Nullable final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ if (getArguments() != null) {
+ mRange = getArguments().getParcelable(RANGE);
+ }
+ }
+
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(final Bundle savedInstanceState) {
+ @SuppressLint("InflateParams") final View rootView = LayoutInflater.from(getContext()).inflate(R.layout.dialog_fragment_range, null);
+
+ //Bind ui
+ ButterKnife.bind(this, rootView);
+ final TextView summary = rootView.findViewById(R.id.summary);
+ if (mRange != null) {
+ final String lowAddress = MeshAddress.formatAddress(mRange.getLowAddress(), false);
+ final String highAddress = MeshAddress.formatAddress(mRange.getHighAddress(), false);
+ lowAddressInput.setText(lowAddress);
+ lowAddressInput.setSelection(lowAddress.length());
+ highAddressInput.setText(highAddress);
+ highAddressInput.setSelection(highAddress.length());
+ }
+
+ final KeyListener hexKeyListener = new HexKeyListener();
+ lowAddressInput.setKeyListener(hexKeyListener);
+ lowAddressInput.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(final CharSequence s, final int start, final int count, final int after) {
+
+ }
+
+ @Override
+ public void onTextChanged(final CharSequence s, final int start, final int before, final int count) {
+ if (TextUtils.isEmpty(s.toString())) {
+ lowAddressInputLayout.setError(getString(R.string.error_empty_value));
+ } else {
+ lowAddressInputLayout.setError(null);
+ }
+ }
+
+ @Override
+ public void afterTextChanged(final Editable s) {
+
+ }
+ });
+
+ highAddressInput.setKeyListener(hexKeyListener);
+ highAddressInput.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(final CharSequence s, final int start, final int count, final int after) {
+
+ }
+
+ @Override
+ public void onTextChanged(final CharSequence s, final int start, final int before, final int count) {
+ if (TextUtils.isEmpty(s.toString())) {
+ highAddressInputLayout.setError(getString(R.string.error_empty_value));
+ } else {
+ highAddressInputLayout.setError(null);
+ }
+ }
+
+ @Override
+ public void afterTextChanged(final Editable s) {
+
+ }
+ });
+
+ final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(requireContext())
+ .setView(rootView)
+ .setIcon(R.drawable.ic_arrow_collapse_black_alpha_24dp)
+ .setTitle(R.string.title_range)
+ .setPositiveButton(R.string.ok, null)
+ .setNegativeButton(R.string.cancel, null);
+
+ summary.setText(R.string.group_range_summary);
+
+ final AlertDialog alertDialog = alertDialogBuilder.show();
+ alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(v -> {
+ final String low = lowAddressInput.getEditableText().toString().trim();
+ final String high = highAddressInput.getEditableText().toString().trim();
+ if (validateLow(low) && validateHigh(high)) {
+ try {
+ AllocatedGroupRange range = mRange;
+ if (range == null) {
+ range = new AllocatedGroupRange(Integer.parseInt(low, 16), Integer.parseInt(high, 16));
+ } else {
+ range.setLowAddress(Integer.parseInt(low, 16));
+ range.setHighAddress(Integer.parseInt(high, 16));
+ }
+ ((RangeListener) requireActivity()).addRange(range);
+ dismiss();
+ } catch (IllegalArgumentException ex) {
+ lowAddressInputLayout.setError(ex.getMessage());
+ }
+ }
+ });
+
+ return alertDialog;
+ }
+
+ private boolean validateLow(@NonNull final String addressValue) {
+ try {
+
+ if(TextUtils.isEmpty(addressValue)){
+ lowAddressInputLayout.setError(getString(R.string.error_empty_value));
+ return false;
+ }
+
+ final int address = Integer.parseInt(addressValue, 16);
+ if (!MeshAddress.isValidGroupAddress(address)) {
+ lowAddressInputLayout.setError("Group address value must range from 0xC000 - 0xFEFF");
+ return false;
+ }
+ } catch (IllegalArgumentException ex) {
+ lowAddressInputLayout.setError(ex.getMessage());
+ return false;
+ }
+ return true;
+ }
+
+ private boolean validateHigh(final String addressValue) {
+ try {
+
+ if(TextUtils.isEmpty(addressValue)){
+ highAddressInputLayout.setError("High address value cannot be empty");
+ return false;
+ }
+
+ final int address = Integer.parseInt(addressValue, 16);
+ if (!MeshAddress.isValidGroupAddress(address)) {
+ highAddressInputLayout.setError("Group address value must range from 0xC000 - 0xFEFF");
+ return false;
+ }
+ } catch (IllegalArgumentException ex) {
+ highAddressInputLayout.setError(ex.getMessage());
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentSourceAddress.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/provisioners/dialogs/DialogFragmentProvisionerAddress.java
similarity index 61%
rename from Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentSourceAddress.java
rename to Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/provisioners/dialogs/DialogFragmentProvisionerAddress.java
index 8e529b5f3..39cbe6e56 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentSourceAddress.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/provisioners/dialogs/DialogFragmentProvisionerAddress.java
@@ -20,26 +20,29 @@
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package no.nordicsemi.android.nrfmeshprovisioner.dialog;
+package no.nordicsemi.android.nrfmeshprovisioner.provisioners.dialogs;
-import android.app.AlertDialog;
+import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.design.widget.TextInputEditText;
-import android.support.design.widget.TextInputLayout;
-import android.support.v4.app.DialogFragment;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.text.method.KeyListener;
import android.view.LayoutInflater;
import android.view.View;
+import android.widget.Button;
+import android.widget.TextView;
-import java.util.Locale;
+import com.google.android.material.textfield.TextInputEditText;
+import com.google.android.material.textfield.TextInputLayout;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AlertDialog;
+import androidx.core.content.ContextCompat;
+import androidx.fragment.app.DialogFragment;
import butterknife.BindView;
import butterknife.ButterKnife;
import no.nordicsemi.android.meshprovisioner.utils.MeshAddress;
@@ -48,7 +51,7 @@
import no.nordicsemi.android.nrfmeshprovisioner.utils.Utils;
-public class DialogFragmentSourceAddress extends DialogFragment {
+public class DialogFragmentProvisionerAddress extends DialogFragment {
private static final String UNICAST_ADDRESS = "UNICAST_ADDRESS";
//UI Bindings
@@ -57,13 +60,15 @@ public class DialogFragmentSourceAddress extends DialogFragment {
@BindView(R.id.text_input)
TextInputEditText unicastAddressInput;
- private int mUnicastAddress;
+ private Integer mUnicastAddress = null;
- public static DialogFragmentSourceAddress newInstance(final int unicastAddress) {
- DialogFragmentSourceAddress fragmentIvIndex = new DialogFragmentSourceAddress();
- final Bundle args = new Bundle();
- args.putInt(UNICAST_ADDRESS, unicastAddress);
- fragmentIvIndex.setArguments(args);
+ public static DialogFragmentProvisionerAddress newInstance(@Nullable final Integer unicastAddress) {
+ final DialogFragmentProvisionerAddress fragmentIvIndex = new DialogFragmentProvisionerAddress();
+ if (unicastAddress != null) {
+ final Bundle args = new Bundle();
+ args.putInt(UNICAST_ADDRESS, unicastAddress);
+ fragmentIvIndex.setArguments(args);
+ }
return fragmentIvIndex;
}
@@ -78,16 +83,19 @@ public void onCreate(@Nullable final Bundle savedInstanceState) {
@NonNull
@Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
- final View rootView = LayoutInflater.from(getContext()).inflate(R.layout.dialog_fragment_address_input, null);
+ @SuppressLint("InflateParams") final View rootView = LayoutInflater.from(getContext()).inflate(R.layout.dialog_fragment_address_input, null);
//Bind ui
ButterKnife.bind(this, rootView);
+ final TextView summary = rootView.findViewById(R.id.summary);
final KeyListener hexKeyListener = new HexKeyListener();
- final String unicastAddress = String.format(Locale.US, "%04X", mUnicastAddress);
- unicastAddressInputLayout.setHint(getString((R.string.hint_src_address)));
- unicastAddressInput.setText(unicastAddress);
- unicastAddressInput.setSelection(unicastAddress.length());
+ unicastAddressInputLayout.setHint(getString((R.string.hint_unicast_address)));
+ if (mUnicastAddress != null && MeshAddress.isValidUnicastAddress(mUnicastAddress)) {
+ final String unicastAddress = MeshAddress.formatAddress(mUnicastAddress, false);
+ unicastAddressInput.setText(unicastAddress);
+ unicastAddressInput.setSelection(unicastAddress.length());
+ }
unicastAddressInput.setKeyListener(hexKeyListener);
unicastAddressInput.addTextChangedListener(new TextWatcher() {
@Override
@@ -110,61 +118,57 @@ public void afterTextChanged(final Editable s) {
}
});
- final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getContext()).setView(rootView)
- .setPositiveButton(R.string.ok, null).setNegativeButton(R.string.cancel, null);
+ final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(requireContext())
+ .setView(rootView)
+ .setIcon(R.drawable.ic_lan_black_alpha_24dp)
+ .setTitle(R.string.title_provisioner_address)
+ .setPositiveButton(R.string.ok, null)
+ .setNeutralButton(R.string.action_unassign, null)
+ .setNegativeButton(R.string.cancel, null);
- alertDialogBuilder.setIcon(R.drawable.ic_lan_black_alpha_24dp);
- alertDialogBuilder.setTitle(R.string.title_src_address);
- alertDialogBuilder.setMessage(R.string.dialog_summary_src);
+ summary.setText(R.string.dialog_summary_src);
final AlertDialog alertDialog = alertDialogBuilder.show();
alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(v -> {
- final String unicast = unicastAddressInput.getText().toString();
- if (validateInput(unicast)) {
+ final String unicast = unicastAddressInput.getEditableText().toString().trim();
+ if (validateInput(unicast))
try {
- if (getParentFragment() == null) {
- if(((DialogFragmentSourceAddressListener) getActivity()).setSourceAddress(Integer.parseInt(unicast, 16))){
- dismiss();
- }
- } else {
- if(((DialogFragmentSourceAddressListener) getParentFragment()).setSourceAddress(Integer.parseInt(unicast, 16))){
- dismiss();
- }
+ if (((ProvisionerAddressListener) requireActivity()).setAddress(Integer.parseInt(unicast, 16))) {
+ dismiss();
}
} catch (IllegalArgumentException ex) {
unicastAddressInputLayout.setError(ex.getMessage());
}
- }
+ });
+
+ final Button unassign = alertDialog.getButton(DialogInterface.BUTTON_NEUTRAL);
+ unassign.setTextColor(ContextCompat.getColor(requireContext(), R.color.nordicRed));
+ unassign.setOnClickListener(v -> {
+ dismiss();
+ ((ProvisionerAddressListener) requireActivity()).unassignProvisioner();
});
return alertDialog;
}
private boolean validateInput(final String input) {
-
try {
-
- if(input.length() % 4 != 0 || !input.matches(Utils.HEX_PATTERN)) {
+ if (input.length() % 4 != 0 || !input.matches(Utils.HEX_PATTERN)) {
unicastAddressInputLayout.setError(getString(R.string.invalid_address_value));
return false;
}
-
- final int unicastAddress = Integer.parseInt(input, 16);
- if(!MeshAddress.isValidUnicastAddress(unicastAddress)) {
- unicastAddressInputLayout.setError("Unicast address must range from 0x0001 - 0x7FFFF");
- return false;
- }
} catch (IllegalArgumentException ex) {
unicastAddressInputLayout.setError(ex.getMessage());
+ return false;
}
-
return true;
}
- public interface DialogFragmentSourceAddressListener {
+ public interface ProvisionerAddressListener {
- boolean setSourceAddress(final int sourceAddress);
+ boolean setAddress(final int sourceAddress);
+ void unassignProvisioner();
}
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/provisioners/dialogs/DialogFragmentProvisionerName.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/provisioners/dialogs/DialogFragmentProvisionerName.java
new file mode 100644
index 000000000..7780aac92
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/provisioners/dialogs/DialogFragmentProvisionerName.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2018, Nordic Semiconductor
+ * 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 no.nordicsemi.android.nrfmeshprovisioner.provisioners.dialogs;
+
+import android.annotation.SuppressLint;
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.text.Editable;
+import android.text.TextUtils;
+import android.text.TextWatcher;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.TextView;
+
+import com.google.android.material.textfield.TextInputEditText;
+import com.google.android.material.textfield.TextInputLayout;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.DialogFragment;
+import butterknife.BindView;
+import butterknife.ButterKnife;
+import no.nordicsemi.android.nrfmeshprovisioner.R;
+
+public class DialogFragmentProvisionerName extends DialogFragment {
+
+ private static final String PROVISIONER_NAME = "PROVISIONER_NAME";
+
+ //UI Bindings
+ @BindView(R.id.text_input_layout)
+ TextInputLayout nameInputLayout;
+ @BindView(R.id.text_input)
+ TextInputEditText nameInput;
+
+ private String mProvisionerName;
+
+ public static DialogFragmentProvisionerName newInstance(final String name) {
+ DialogFragmentProvisionerName fragmentNetworkKey = new DialogFragmentProvisionerName();
+ final Bundle args = new Bundle();
+ args.putString(PROVISIONER_NAME, name);
+ fragmentNetworkKey.setArguments(args);
+ return fragmentNetworkKey;
+ }
+
+ @Override
+ public void onCreate(@Nullable final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ if (getArguments() != null) {
+ mProvisionerName = getArguments().getString(PROVISIONER_NAME);
+ }
+ }
+
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(final Bundle savedInstanceState) {
+ @SuppressLint("InflateParams") final View rootView = LayoutInflater.from(getContext()).inflate(R.layout.dialog_fragment_name, null);
+
+ //Bind ui
+ ButterKnife.bind(this, rootView);
+ final TextView summary = rootView.findViewById(R.id.summary);
+ nameInputLayout.setHint(getString(R.string.name));
+ nameInput.setText(mProvisionerName);
+ nameInput.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(final CharSequence s, final int start, final int count, final int after) {
+
+ }
+
+ @Override
+ public void onTextChanged(final CharSequence s, final int start, final int before, final int count) {
+ if (TextUtils.isEmpty(s.toString())) {
+ nameInputLayout.setError(getString(R.string.error_empty_name));
+ } else {
+ nameInputLayout.setError(null);
+ }
+ }
+
+ @Override
+ public void afterTextChanged(final Editable s) {
+
+ }
+ });
+
+ final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(requireContext())
+ .setView(rootView)
+ .setIcon(R.drawable.ic_lan_black_alpha_24dp)
+ .setTitle(R.string.title_provisioner_name)
+ .setPositiveButton(R.string.ok, null)
+ .setNegativeButton(R.string.cancel, null);
+
+ summary.setText(R.string.provisioner_name_rationale);
+
+ final AlertDialog alertDialog = alertDialogBuilder.show();
+ alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(v -> {
+ final String name = nameInput.getEditableText().toString().trim();
+ try {
+ if (((DialogFragmentProvisionerNameListener) requireActivity()).onNameChanged(name)) {
+ dismiss();
+ }
+ } catch (IllegalArgumentException ex) {
+ nameInputLayout.setError(ex.getMessage());
+ }
+ });
+
+ return alertDialog;
+ }
+
+ public interface DialogFragmentProvisionerNameListener {
+
+ boolean onNameChanged(@NonNull final String name);
+
+ }
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/provisioners/dialogs/DialogFragmentSceneRange.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/provisioners/dialogs/DialogFragmentSceneRange.java
new file mode 100644
index 000000000..8b4c07230
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/provisioners/dialogs/DialogFragmentSceneRange.java
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2018, Nordic Semiconductor
+ * 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 no.nordicsemi.android.nrfmeshprovisioner.provisioners.dialogs;
+
+import android.annotation.SuppressLint;
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.text.Editable;
+import android.text.TextUtils;
+import android.text.TextWatcher;
+import android.text.method.KeyListener;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.TextView;
+
+import com.google.android.material.textfield.TextInputEditText;
+import com.google.android.material.textfield.TextInputLayout;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.DialogFragment;
+import butterknife.BindView;
+import butterknife.ButterKnife;
+import no.nordicsemi.android.meshprovisioner.AllocatedSceneRange;
+import no.nordicsemi.android.meshprovisioner.Scene;
+import no.nordicsemi.android.meshprovisioner.utils.MeshAddress;
+import no.nordicsemi.android.nrfmeshprovisioner.R;
+import no.nordicsemi.android.nrfmeshprovisioner.provisioners.RangeListener;
+import no.nordicsemi.android.nrfmeshprovisioner.utils.HexKeyListener;
+
+public class DialogFragmentSceneRange extends DialogFragment {
+
+ private static final String RANGE = "RANGE";
+ //UI Bindings
+ @BindView(R.id.low_address_layout)
+ TextInputLayout fistSceneInputLayout;
+ @BindView(R.id.low_address_input)
+ TextInputEditText firstSceneInput;
+ @BindView(R.id.high_address_layout)
+ TextInputLayout lastSceneInputLayout;
+ @BindView(R.id.high_address_input)
+ TextInputEditText lastSceneInput;
+
+ private AllocatedSceneRange mRange;
+
+ public static DialogFragmentSceneRange newInstance(@Nullable final AllocatedSceneRange range) {
+ DialogFragmentSceneRange fragment = new DialogFragmentSceneRange();
+ final Bundle args = new Bundle();
+ args.putParcelable(RANGE, range);
+ fragment.setArguments(args);
+ return fragment;
+ }
+
+ @Override
+ public void onCreate(@Nullable final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ if (getArguments() != null) {
+ mRange = getArguments().getParcelable(RANGE);
+ }
+ }
+
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(final Bundle savedInstanceState) {
+ @SuppressLint("InflateParams") final View rootView = LayoutInflater.from(getContext()).inflate(R.layout.dialog_fragment_range, null);
+
+ //Bind ui
+ ButterKnife.bind(this, rootView);
+ final TextView summary = rootView.findViewById(R.id.summary);
+ if (mRange != null) {
+ final String lowAddress = MeshAddress.formatAddress(mRange.getFirstScene(), false);
+ final String highAddress = MeshAddress.formatAddress(mRange.getLastScene(), false);
+ firstSceneInput.setText(lowAddress);
+ firstSceneInput.setSelection(lowAddress.length());
+ lastSceneInput.setText(highAddress);
+ lastSceneInput.setSelection(highAddress.length());
+ }
+
+ final KeyListener hexKeyListener = new HexKeyListener();
+ fistSceneInputLayout.setHint(getString(R.string.first_scene));
+ firstSceneInput.setKeyListener(hexKeyListener);
+ firstSceneInput.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(final CharSequence s, final int start, final int count, final int after) {
+
+ }
+
+ @Override
+ public void onTextChanged(final CharSequence s, final int start, final int before, final int count) {
+ if (TextUtils.isEmpty(s.toString())) {
+ fistSceneInputLayout.setError(getString(R.string.error_empty_value));
+ } else {
+ fistSceneInputLayout.setError(null);
+ }
+ }
+
+ @Override
+ public void afterTextChanged(final Editable s) {
+
+ }
+ });
+
+ lastSceneInputLayout.setHint(getString(R.string.last_scene));
+ lastSceneInput.setKeyListener(hexKeyListener);
+ lastSceneInput.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(final CharSequence s, final int start, final int count, final int after) {
+
+ }
+
+ @Override
+ public void onTextChanged(final CharSequence s, final int start, final int before, final int count) {
+ if (TextUtils.isEmpty(s.toString())) {
+ lastSceneInputLayout.setError(getString(R.string.error_empty_value));
+ } else {
+ lastSceneInputLayout.setError(null);
+ }
+ }
+
+ @Override
+ public void afterTextChanged(final Editable s) {
+
+ }
+ });
+
+ final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(requireContext())
+ .setView(rootView)
+ .setIcon(R.drawable.ic_arrow_collapse_black_alpha_24dp)
+ .setTitle(R.string.title_range)
+ .setPositiveButton(R.string.ok, null)
+ .setNegativeButton(R.string.cancel, null);
+
+ summary.setText(R.string.scene_range_summary);
+
+ final AlertDialog alertDialog = alertDialogBuilder.show();
+ alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(v -> {
+ final String low = firstSceneInput.getEditableText().toString().trim();
+ final String high = lastSceneInput.getEditableText().toString().trim();
+ if (validateFirstScene(low) && validateLastScene(high)) {
+ try {
+ AllocatedSceneRange range = mRange;
+ if (range == null) {
+ range = new AllocatedSceneRange(Integer.parseInt(low, 16), Integer.parseInt(high, 16));
+ } else {
+ range.setFirstScene(Integer.parseInt(low, 16));
+ range.setLastScene(Integer.parseInt(high, 16));
+ }
+ ((RangeListener) requireActivity()).addRange(range);
+ dismiss();
+ } catch (IllegalArgumentException ex) {
+ fistSceneInputLayout.setError(ex.getMessage());
+ }
+ }
+ });
+
+ return alertDialog;
+ }
+
+ private boolean validateFirstScene(final String firstScene) {
+ try {
+
+ final int address = Integer.parseInt(firstScene, 16);
+ if (!Scene.isValidScene(address)) {
+ fistSceneInputLayout.setError("first scene value must range from 0x0001 - 0xFFFF");
+ return false;
+ }
+ } catch (IllegalArgumentException ex) {
+ fistSceneInputLayout.setError(ex.getMessage());
+ return false;
+ }
+ return true;
+ }
+
+ private boolean validateLastScene(final String lastScene) {
+ try {
+
+ final int address = Integer.parseInt(lastScene, 16);
+ if (!Scene.isValidScene(address)) {
+ lastSceneInputLayout.setError("last scene value must range from 0x0001 - 0xFFFF");
+ return false;
+ }
+ } catch (IllegalArgumentException ex) {
+ lastSceneInputLayout.setError(ex.getMessage());
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentGlobalTtl.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/provisioners/dialogs/DialogFragmentTtl.java
similarity index 65%
rename from Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentGlobalTtl.java
rename to Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/provisioners/dialogs/DialogFragmentTtl.java
index e94729f39..b73085d42 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/dialog/DialogFragmentGlobalTtl.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/provisioners/dialogs/DialogFragmentTtl.java
@@ -20,30 +20,31 @@
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package no.nordicsemi.android.nrfmeshprovisioner.dialog;
+package no.nordicsemi.android.nrfmeshprovisioner.provisioners.dialogs;
-import android.app.AlertDialog;
+import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.design.widget.TextInputEditText;
-import android.support.design.widget.TextInputLayout;
-import android.support.v4.app.DialogFragment;
import android.text.Editable;
-import android.text.InputType;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
+import com.google.android.material.textfield.TextInputEditText;
+import com.google.android.material.textfield.TextInputLayout;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.DialogFragment;
import butterknife.BindView;
import butterknife.ButterKnife;
import no.nordicsemi.android.meshprovisioner.utils.MeshParserUtils;
import no.nordicsemi.android.nrfmeshprovisioner.R;
-public class DialogFragmentGlobalTtl extends DialogFragment {
+public class DialogFragmentTtl extends DialogFragment {
private static final String GLOBAL_TTL = "GLOBAL_TTL";
@@ -53,12 +54,12 @@ public class DialogFragmentGlobalTtl extends DialogFragment {
@BindView(R.id.text_input)
TextInputEditText ttlInput;
- private String ttl;
+ private int mTtl;
- public static DialogFragmentGlobalTtl newInstance(final String ttl) {
- DialogFragmentGlobalTtl fragmentNetworkKey = new DialogFragmentGlobalTtl();
+ public static DialogFragmentTtl newInstance(final int ttl) {
+ DialogFragmentTtl fragmentNetworkKey = new DialogFragmentTtl();
final Bundle args = new Bundle();
- args.putString(GLOBAL_TTL, ttl);
+ args.putInt(GLOBAL_TTL, ttl);
fragmentNetworkKey.setArguments(args);
return fragmentNetworkKey;
}
@@ -67,19 +68,18 @@ public static DialogFragmentGlobalTtl newInstance(final String ttl) {
public void onCreate(@Nullable final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
- ttl = getArguments().getString(GLOBAL_TTL);
+ mTtl = getArguments().getInt(GLOBAL_TTL);
}
}
@NonNull
@Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
- final View rootView = LayoutInflater.from(getContext()).inflate(R.layout.dialog_fragment_ttl_input, null);
+ @SuppressLint("InflateParams") final View rootView = LayoutInflater.from(getContext()).inflate(R.layout.dialog_fragment_ttl, null);
//Bind ui
ButterKnife.bind(this, rootView);
- ttlInput.setInputType(InputType.TYPE_CLASS_TEXT);
- ttlInputLayout.setHint(getString(R.string.hint_global_ttl));
+ final String ttl = String.valueOf(mTtl);
ttlInput.setText(ttl);
ttlInput.setSelection(ttl.length());
ttlInput.addTextChangedListener(new TextWatcher() {
@@ -91,7 +91,7 @@ public void beforeTextChanged(final CharSequence s, final int start, final int c
@Override
public void onTextChanged(final CharSequence s, final int start, final int before, final int count) {
if (TextUtils.isEmpty(s.toString())) {
- ttlInputLayout.setError(getString(R.string.error_empty_global_ttl));
+ ttlInputLayout.setError(getString(R.string.error_empty_ttl));
} else {
ttlInputLayout.setError(null);
}
@@ -103,43 +103,44 @@ public void afterTextChanged(final Editable s) {
}
});
- final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getContext()).setView(rootView)
+ final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(requireContext()).setView(rootView)
.setPositiveButton(R.string.ok, null).setNegativeButton(R.string.cancel, null);
alertDialogBuilder.setIcon(R.drawable.ic_timer);
- alertDialogBuilder.setTitle(R.string.title_global_ttl);
- alertDialogBuilder.setMessage(R.string.summary_ttl);
+ alertDialogBuilder.setTitle(R.string.title_ttl);
final AlertDialog alertDialog = alertDialogBuilder.show();
alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(v -> {
- final String globalTTL = ttlInput.getText().toString();
- if (validateInput(globalTTL)) {
- if(getParentFragment() == null) {
- ((DialogFragmentGlobalTtlListener) getActivity()).onGlobalTtlEntered(Integer.parseInt(globalTTL));
- } else {
- ((DialogFragmentGlobalTtlListener) getParentFragment()).onGlobalTtlEntered(Integer.parseInt(globalTTL));
+ final String globalTTL = ttlInput.getEditableText().toString().trim();
+ try {
+ if (validateInput(globalTTL)) {
+ if (((DialogFragmentTtlListener) requireActivity()).setDefaultTtl(Integer.parseInt(globalTTL))) {
+ dismiss();
+ }
}
- dismiss();
+ } catch (IllegalArgumentException ex) {
+ ttlInputLayout.setError(ex.getMessage());
}
});
return alertDialog;
}
- private boolean validateInput(final String input) {
- try {
- if(MeshParserUtils.validateTtlInput(getContext(), Integer.parseInt(input))) {
- return true;
- }
- } catch (IllegalArgumentException ex) {
- ttlInputLayout.setError(ex.getMessage());
+ private boolean validateInput(@NonNull final String input) {
+ if (TextUtils.isEmpty(input)) {
+ ttlInputLayout.setError("TTL value cannot be empty");
+ return false;
+ }
+
+ if (!MeshParserUtils.isValidDefaultTtl(Integer.parseInt(input))) {
+ throw new IllegalArgumentException(getString(R.string.error_invalid_default_ttl));
}
- return false;
+ return true;
}
- public interface DialogFragmentGlobalTtlListener {
+ public interface DialogFragmentTtlListener {
- void onGlobalTtlEntered(final int ttl);
+ boolean setDefaultTtl(final int ttl);
}
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/provisioners/dialogs/DialogFragmentUnassign.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/provisioners/dialogs/DialogFragmentUnassign.java
new file mode 100644
index 000000000..4551059c9
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/provisioners/dialogs/DialogFragmentUnassign.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2018, Nordic Semiconductor
+ * 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 no.nordicsemi.android.nrfmeshprovisioner.provisioners.dialogs;
+
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.os.Bundle;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AlertDialog;
+import androidx.core.content.ContextCompat;
+import androidx.fragment.app.DialogFragment;
+import no.nordicsemi.android.nrfmeshprovisioner.R;
+
+public class DialogFragmentUnassign extends DialogFragment {
+
+ protected static final String TITLE = "TITLE";
+ protected static final String MESSAGE = "MESSAGE";
+ protected AlertDialog.Builder alertDialogBuilder;
+ protected String title;
+ protected String message;
+
+ public interface DialogFragmentUnassignListener {
+ void onProvisionerUnassigned();
+ }
+
+ public static DialogFragmentUnassign newInstance(final String title, final String message) {
+ Bundle args = new Bundle();
+ DialogFragmentUnassign fragment = new DialogFragmentUnassign();
+ args.putString(TITLE, title);
+ args.putString(MESSAGE, message);
+ fragment.setArguments(args);
+ return fragment;
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ }
+
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(final Bundle savedInstanceState) {
+ super.onCreateDialog(savedInstanceState);
+
+ final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(requireActivity());
+ alertDialogBuilder.setIcon(R.drawable.ic_reset_black_24dp_alpha);
+ alertDialogBuilder.setTitle(requireContext().getString(R.string.title_unassign_provisioner));
+ alertDialogBuilder.setMessage(requireContext().getString(R.string.summary_unassign_provisioner));
+ alertDialogBuilder.setNegativeButton(getString(R.string.no), null);
+ alertDialogBuilder.setPositiveButton(getString(R.string.confirm), (dialog, which) -> (
+ (DialogFragmentUnassignListener) requireActivity()).onProvisionerUnassigned());
+
+ final AlertDialog alertDialog = alertDialogBuilder.show();
+ alertDialog.getButton(DialogInterface.BUTTON_POSITIVE)
+ .setTextColor(ContextCompat.getColor(requireContext(), R.color.nordicRed));
+
+ return alertDialog;
+ }
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/provisioners/dialogs/DialogFragmentUnicastRange.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/provisioners/dialogs/DialogFragmentUnicastRange.java
new file mode 100644
index 000000000..300c4c65b
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/provisioners/dialogs/DialogFragmentUnicastRange.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2018, Nordic Semiconductor
+ * 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 no.nordicsemi.android.nrfmeshprovisioner.provisioners.dialogs;
+
+import android.annotation.SuppressLint;
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.text.Editable;
+import android.text.TextUtils;
+import android.text.TextWatcher;
+import android.text.method.KeyListener;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.TextView;
+
+import com.google.android.material.textfield.TextInputEditText;
+import com.google.android.material.textfield.TextInputLayout;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.DialogFragment;
+import butterknife.BindView;
+import butterknife.ButterKnife;
+import no.nordicsemi.android.meshprovisioner.AllocatedUnicastRange;
+import no.nordicsemi.android.meshprovisioner.utils.MeshAddress;
+import no.nordicsemi.android.nrfmeshprovisioner.R;
+import no.nordicsemi.android.nrfmeshprovisioner.provisioners.RangeListener;
+import no.nordicsemi.android.nrfmeshprovisioner.utils.HexKeyListener;
+
+public class DialogFragmentUnicastRange extends DialogFragment {
+
+ private static final String RANGE = "RANGE";
+ //UI Bindings
+ @BindView(R.id.low_address_layout)
+ TextInputLayout lowAddressInputLayout;
+ @BindView(R.id.low_address_input)
+ TextInputEditText lowAddressInput;
+ @BindView(R.id.high_address_layout)
+ TextInputLayout highAddressInputLayout;
+ @BindView(R.id.high_address_input)
+ TextInputEditText highAddressInput;
+
+ private AllocatedUnicastRange mRange;
+
+ public static DialogFragmentUnicastRange newInstance(@Nullable final AllocatedUnicastRange range) {
+ DialogFragmentUnicastRange fragment = new DialogFragmentUnicastRange();
+ final Bundle args = new Bundle();
+ args.putParcelable(RANGE, range);
+ fragment.setArguments(args);
+ return fragment;
+ }
+
+ @Override
+ public void onCreate(@Nullable final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ if (getArguments() != null) {
+ mRange = getArguments().getParcelable(RANGE);
+ }
+ }
+
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(final Bundle savedInstanceState) {
+ @SuppressLint("InflateParams") final View rootView = LayoutInflater.from(getContext()).inflate(R.layout.dialog_fragment_range, null);
+
+ //Bind ui
+ ButterKnife.bind(this, rootView);
+ final TextView summary = rootView.findViewById(R.id.summary);
+ if (mRange != null) {
+ final String lowAddress = MeshAddress.formatAddress(mRange.getLowAddress(), false);
+ final String highAddress = MeshAddress.formatAddress(mRange.getHighAddress(), false);
+ lowAddressInput.setText(lowAddress);
+ lowAddressInput.setSelection(lowAddress.length());
+ highAddressInput.setText(highAddress);
+ highAddressInput.setSelection(highAddress.length());
+ }
+
+ final KeyListener hexKeyListener = new HexKeyListener();
+ lowAddressInput.setKeyListener(hexKeyListener);
+ lowAddressInput.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(final CharSequence s, final int start, final int count, final int after) {
+
+ }
+
+ @Override
+ public void onTextChanged(final CharSequence s, final int start, final int before, final int count) {
+ if (TextUtils.isEmpty(s.toString())) {
+ lowAddressInputLayout.setError(getString(R.string.error_empty_value));
+ } else {
+ lowAddressInputLayout.setError(null);
+ }
+ }
+
+ @Override
+ public void afterTextChanged(final Editable s) {
+
+ }
+ });
+
+ highAddressInput.setKeyListener(hexKeyListener);
+ highAddressInput.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(final CharSequence s, final int start, final int count, final int after) {
+
+ }
+
+ @Override
+ public void onTextChanged(final CharSequence s, final int start, final int before, final int count) {
+ if (TextUtils.isEmpty(s.toString())) {
+ highAddressInputLayout.setError(getString(R.string.error_empty_value));
+ } else {
+ highAddressInputLayout.setError(null);
+ }
+ }
+
+ @Override
+ public void afterTextChanged(final Editable s) {
+
+ }
+ });
+
+ final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(requireContext())
+ .setView(rootView)
+ .setIcon(R.drawable.ic_arrow_collapse_black_alpha_24dp)
+ .setTitle(R.string.title_range)
+ .setPositiveButton(R.string.ok, null)
+ .setNegativeButton(R.string.cancel, null);
+
+ summary.setText(R.string.unicast_range_summary);
+
+ final AlertDialog alertDialog = alertDialogBuilder.show();
+ alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(v -> {
+ final String low = lowAddressInput.getEditableText().toString().trim();
+ final String high = highAddressInput.getEditableText().toString().trim();
+ if (validateLow(low) && validateHigh(high)) {
+ try {
+ AllocatedUnicastRange range = mRange;
+ if (range == null) {
+ range = new AllocatedUnicastRange(Integer.parseInt(low, 16), Integer.parseInt(high, 16));
+ } else {
+ range.setLowAddress(Integer.parseInt(low, 16));
+ range.setHighAddress(Integer.parseInt(high, 16));
+ }
+ ((RangeListener) requireActivity()).addRange(range);
+ dismiss();
+ } catch (IllegalArgumentException ex) {
+ lowAddressInputLayout.setError(ex.getMessage());
+ }
+ }
+ });
+
+ return alertDialog;
+ }
+
+ private boolean validateLow(final String addressValue) {
+ try {
+
+ final int address = Integer.parseInt(addressValue, 16);
+ if (!MeshAddress.isValidUnicastAddress(address)) {
+ lowAddressInputLayout.setError("Unicast address value must range from 0x0001 - 0x7FFFF");
+ return false;
+ }
+ } catch (IllegalArgumentException ex) {
+ lowAddressInputLayout.setError(ex.getMessage());
+ return false;
+ }
+ return true;
+ }
+
+ private boolean validateHigh(final String addressValue) {
+ try {
+
+ final int address = Integer.parseInt(addressValue, 16);
+ if (!MeshAddress.isValidUnicastAddress(address)) {
+ highAddressInputLayout.setError("Unicast address value must range from 0x0001 - 0x7FFFF");
+ return false;
+ }
+ } catch (IllegalArgumentException ex) {
+ highAddressInputLayout.setError(ex.getMessage());
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/utils/AddressTypes.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/utils/AddressTypes.java
new file mode 100644
index 000000000..5586f3354
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/utils/AddressTypes.java
@@ -0,0 +1,84 @@
+package no.nordicsemi.android.nrfmeshprovisioner.utils;
+
+/**
+ * Address types
+ */
+@SuppressWarnings("unused")
+public enum AddressTypes {
+
+ UNICAST_ADDRESS(0),
+ GROUP_ADDRESS(1),
+ ALL_PROXIES(2),
+ ALL_FRIENDS(3),
+ ALL_RELAYS(4),
+ ALL_NODES(5),
+ VIRTUAL_ADDRESS(6);
+
+ private int type;
+
+ /**
+ * Constructs address type
+ *
+ * @param type Address type
+ */
+ AddressTypes(final int type) {
+ this.type = type;
+ }
+
+ /**
+ * Returns the address type
+ */
+ public int getType() {
+ return type;
+ }
+
+ /**
+ * Returns the oob method used for authentication
+ *
+ * @param method auth method used
+ */
+ public static AddressTypes fromValue(final int method) {
+ switch (method) {
+ default:
+ return null;
+ case 0:
+ return UNICAST_ADDRESS;
+ case 1:
+ return GROUP_ADDRESS;
+ case 2:
+ return ALL_PROXIES;
+ case 3:
+ return ALL_FRIENDS;
+ case 4:
+ return ALL_RELAYS;
+ case 5:
+ return ALL_NODES;
+ case 6:
+ return VIRTUAL_ADDRESS;
+ }
+ }
+
+ /**
+ * Returns the address type name
+ *
+ * @param type Address type
+ */
+ public static String getTypeName(final AddressTypes type) {
+ switch (type) {
+ default:
+ return "Unicast Address";
+ case GROUP_ADDRESS:
+ return "Group Address";
+ case ALL_PROXIES:
+ return "All Proxies";
+ case ALL_FRIENDS:
+ return "All Friends";
+ case ALL_RELAYS:
+ return "All Relays";
+ case ALL_NODES:
+ return "All Nodes";
+ case VIRTUAL_ADDRESS:
+ return "Virtual Address";
+ }
+ }
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/utils/HexKeyListener.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/utils/HexKeyListener.java
index 04c223c21..de2b2c69d 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/utils/HexKeyListener.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/utils/HexKeyListener.java
@@ -22,7 +22,7 @@
package no.nordicsemi.android.nrfmeshprovisioner.utils;
-import android.support.annotation.NonNull;
+import androidx.annotation.NonNull;
import android.text.InputType;
import android.text.method.NumberKeyListener;
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/utils/ProvisionerStates.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/utils/ProvisionerStates.java
new file mode 100644
index 000000000..163ffde09
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/utils/ProvisionerStates.java
@@ -0,0 +1,52 @@
+package no.nordicsemi.android.nrfmeshprovisioner.utils;
+
+public enum ProvisionerStates {
+
+ PROVISIONING_INVITE(0),
+ PROVISIONING_CAPABILITIES(1),
+ PROVISIONING_START(2),
+ PROVISIONING_PUBLIC_KEY_SENT(3),
+ PROVISIONING_PUBLIC_KEY_RECEIVED(4),
+ PROVISIONING_AUTHENTICATION_INPUT_OOB_WAITING(5),
+ PROVISIONING_AUTHENTICATION_OUTPUT_OOB_WAITING(6),
+ PROVISIONING_AUTHENTICATION_STATIC_OOB_WAITING(7),
+ PROVISIONING_AUTHENTICATION_INPUT_ENTERED(8),
+ PROVISIONING_INPUT_COMPLETE(9),
+ PROVISIONING_CONFIRMATION_SENT(10),
+ PROVISIONING_CONFIRMATION_RECEIVED(11),
+ PROVISIONING_RANDOM_SENT(12),
+ PROVISIONING_RANDOM_RECEIVED(13),
+ PROVISIONING_DATA_SENT(14),
+ PROVISIONING_COMPLETE(15),
+ PROVISIONING_FAILED(16),
+ COMPOSITION_DATA_GET_SENT(17),
+ COMPOSITION_DATA_STATUS_RECEIVED(18),
+ SENDING_DEFAULT_TTL_GET(19),
+ DEFAULT_TTL_STATUS_RECEIVED(20),
+ SENDING_APP_KEY_ADD(21),
+ APP_KEY_STATUS_RECEIVED(22),
+ SENDING_NETWORK_TRANSMIT_SET(23),
+ NETWORK_TRANSMIT_STATUS_RECEIVED(24),
+ SENDING_BLOCK_ACKNOWLEDGEMENT(98),
+ BLOCK_ACKNOWLEDGEMENT_RECEIVED(99),
+ PROVISIONER_UNASSIGNED(100);
+
+ private int state;
+
+ ProvisionerStates(final int state) {
+ this.state = state;
+ }
+
+ public int getState() {
+ return state;
+ }
+
+ public static ProvisionerStates fromStatusCode(final int statusCode) {
+ for (ProvisionerStates state : ProvisionerStates.values()) {
+ if (state.getState() == statusCode) {
+ return state;
+ }
+ }
+ throw new IllegalStateException("Invalid state");
+ }
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/utils/Utils.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/utils/Utils.java
index 0cc0d0697..6a377d734 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/utils/Utils.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/utils/Utils.java
@@ -32,17 +32,17 @@
import android.os.ParcelUuid;
import android.preference.PreferenceManager;
import android.provider.Settings;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.v4.app.ActivityCompat;
-import android.support.v4.content.ContextCompat;
import android.widget.Toast;
import java.util.Comparator;
import java.util.UUID;
-import no.nordicsemi.android.meshprovisioner.transport.ApplicationKey;
-import no.nordicsemi.android.meshprovisioner.transport.NetworkKey;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.core.app.ActivityCompat;
+import androidx.core.content.ContextCompat;
+import no.nordicsemi.android.meshprovisioner.ApplicationKey;
+import no.nordicsemi.android.meshprovisioner.NetworkKey;
import no.nordicsemi.android.support.v18.scanner.ScanRecord;
import no.nordicsemi.android.support.v18.scanner.ScanResult;
@@ -55,10 +55,13 @@ public class Utils {
public static final String EXTRA_DATA_MODEL_NAME = "EXTRA_DATA_MODEL_NAME";
public static final String EXTRA_DEVICE = "EXTRA_DEVICE";
- public static final String ACTIVITY_RESULT = "RESULT_APP_KEY";
+ public static final String ACTIVITY_RESULT = "RESULT_KEY";
public static final String PROVISIONING_COMPLETED = "PROVISIONING_COMPLETED";
+ public static final String PROVISIONER_UNASSIGNED = "PROVISIONER_UNASSIGNED";
public static final String COMPOSITION_DATA_COMPLETED = "COMPOSITION_DATA_COMPLETED";
+ public static final String DEFAULT_GET_COMPLETED = "DEFAULT_GET_COMPLETED";
public static final String APP_KEY_ADD_COMPLETED = "APP_KEY_ADD_COMPLETED";
+ public static final String NETWORK_TRANSMIT_SET_COMPLETED = "NETWORK_TRANSMIT_SET_COMPLETED";
public static final String EXTRA_DATA = "EXTRA_DATA";
private static final String PREFS_LOCATION_NOT_REQUIRED = "location_not_required";
private static final String PREFS_PERMISSION_REQUESTED = "permission_requested";
@@ -66,14 +69,28 @@ public class Utils {
private static final String PREFS_WRITE_STORAGE_PERMISSION_REQUESTED = "write_storage_permission_requested";
public static final int PROVISIONING_SUCCESS = 2112;
public static final int CONNECT_TO_NETWORK = 2113;
- public static final String RESULT_APP_KEY = "RESULT_APP_KEY";
+ public static final String RESULT_KEY = "RESULT_KEY";
private static final String APPLICATION_KEYS = "APPLICATION_KEYS";
+ public static final String RANGE_TYPE = "RANGE_TYPE";
+ public static final String DIALOG_FRAGMENT_KEY_STATUS = "DIALOG_FRAGMENT_KEY_STATUS";
+
+ //Message timeout in case the message fails to lost/received
+ public static final int MESSAGE_TIME_OUT = 10000;
+ //Manage ranges
+ public static final int UNICAST_RANGE = 0;
+ public static final int GROUP_RANGE = 1;
+ public static final int SCENE_RANGE = 2;
+
+ //Manage app keys
+ public static final int MANAGE_NET_KEY = 0;
+ public static final int ADD_NET_KEY = 1;
//Manage app keys
- public static final int MANAGE_APP_KEY = 0;
- public static final int ADD_APP_KEY = 1;
- public static final int BIND_APP_KEY = 2;
- public static final int PUBLICATION_APP_KEY = 3;
+ public static final int MANAGE_APP_KEY = 2;
+ public static final int ADD_APP_KEY = 3;
+ public static final int BIND_APP_KEY = 4;
+ public static final int PUBLICATION_APP_KEY = 5;
+ public static final int SELECT_KEY = 2011; //Random number
public static final Comparator netKeyComparator = (key1, key2) -> Integer.compare(key1.getKeyIndex(), key2.getKeyIndex());
@@ -173,6 +190,7 @@ public static void markLocationPermissionRequested(final Context context) {
*
* @return true if permissions are already granted, false otherwise.
*/
+ @SuppressWarnings("BooleanMethodIsAlwaysInverted")
public static boolean isWriteExternalStoragePermissionsGranted(final Context context) {
return ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/AddAppKeyViewModel.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/AddAppKeyViewModel.java
new file mode 100644
index 000000000..08087ba60
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/AddAppKeyViewModel.java
@@ -0,0 +1,17 @@
+package no.nordicsemi.android.nrfmeshprovisioner.viewmodels;
+
+import javax.inject.Inject;
+
+import androidx.annotation.NonNull;
+import no.nordicsemi.android.nrfmeshprovisioner.keys.AppKeysActivity;
+
+/**
+ * ViewModel for {@link AppKeysActivity}
+ */
+public class AddAppKeyViewModel extends KeysViewModel {
+
+ @Inject
+ AddAppKeyViewModel(@NonNull final NrfMeshRepository nrfMeshRepository) {
+ super(nrfMeshRepository);
+ }
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/AddKeysViewModel.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/AddKeysViewModel.java
new file mode 100644
index 000000000..41a88479b
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/AddKeysViewModel.java
@@ -0,0 +1,59 @@
+package no.nordicsemi.android.nrfmeshprovisioner.viewmodels;
+
+import java.util.LinkedList;
+import java.util.Queue;
+
+import javax.inject.Inject;
+
+import androidx.annotation.NonNull;
+import no.nordicsemi.android.meshprovisioner.transport.ConfigAppKeyGet;
+import no.nordicsemi.android.meshprovisioner.transport.ProvisionedMeshNode;
+import no.nordicsemi.android.meshprovisioner.utils.MeshParserUtils;
+import no.nordicsemi.android.nrfmeshprovisioner.keys.AppKeysActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.keys.NetKeysActivity;
+
+/**
+ * ViewModel for {@link NetKeysActivity}, {@link AppKeysActivity}
+ */
+public class AddKeysViewModel extends KeysViewModel {
+
+ private Queue messageQueue = new LinkedList<>();
+
+ @Inject
+ AddKeysViewModel(@NonNull final NrfMeshRepository nrfMeshRepository) {
+ super(nrfMeshRepository);
+ }
+
+ public Queue getMessageQueue() {
+ return messageQueue;
+ }
+
+ /**
+ * Checks if the key has been added to the node
+ *
+ * @param keyIndex index of the key
+ * @return true if added or false otherwise
+ */
+ public boolean isNetKeyAdded(final int keyIndex) {
+ final ProvisionedMeshNode node = getSelectedMeshNode().getValue();
+ if (node != null) {
+ return MeshParserUtils.isNodeKeyExists(node.getAddedNetKeys(), keyIndex);
+ }
+ return false;
+ }
+
+ /**
+ * Checks if the key has been added to the node
+ *
+ * @param keyIndex index of the key
+ * @return true if added or false otherwise
+ */
+ public boolean isAppKeyAdded(final int keyIndex) {
+ final ProvisionedMeshNode node = getSelectedMeshNode().getValue();
+ if (node != null) {
+ return MeshParserUtils.isNodeKeyExists(node.getAddedAppKeys(), keyIndex);
+ }
+ return false;
+ }
+
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/AddNetKeyViewModel.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/AddNetKeyViewModel.java
new file mode 100644
index 000000000..1f8744384
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/AddNetKeyViewModel.java
@@ -0,0 +1,17 @@
+package no.nordicsemi.android.nrfmeshprovisioner.viewmodels;
+
+import javax.inject.Inject;
+
+import androidx.annotation.NonNull;
+import no.nordicsemi.android.nrfmeshprovisioner.keys.AppKeysActivity;
+
+/**
+ * ViewModel for {@link AppKeysActivity}
+ */
+public class AddNetKeyViewModel extends KeysViewModel {
+
+ @Inject
+ AddNetKeyViewModel(@NonNull final NrfMeshRepository nrfMeshRepository) {
+ super(nrfMeshRepository);
+ }
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/AddProvisionerViewModel.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/AddProvisionerViewModel.java
new file mode 100644
index 000000000..6907e3045
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/AddProvisionerViewModel.java
@@ -0,0 +1,28 @@
+package no.nordicsemi.android.nrfmeshprovisioner.viewmodels;
+
+import javax.inject.Inject;
+
+import androidx.annotation.NonNull;
+import androidx.lifecycle.LiveData;
+import no.nordicsemi.android.meshprovisioner.Provisioner;
+import no.nordicsemi.android.nrfmeshprovisioner.keys.AppKeysActivity;
+
+/**
+ * ViewModel for {@link AppKeysActivity}
+ */
+public class AddProvisionerViewModel extends BaseViewModel {
+
+ @Inject
+ AddProvisionerViewModel(@NonNull final NrfMeshRepository nrfMeshRepository) {
+ super(nrfMeshRepository);
+ mNrfMeshRepository.clearTransactionStatus();
+ }
+
+ public void setSelectedProvisioner(@NonNull final Provisioner provisioner) {
+ mNrfMeshRepository.setSelectedProvisioner(provisioner);
+ }
+
+ public LiveData getSelectedProvisioner() {
+ return mNrfMeshRepository.getSelectedProvisioner();
+ }
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/AppKeysViewModel.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/AppKeysViewModel.java
new file mode 100644
index 000000000..f67536674
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/AppKeysViewModel.java
@@ -0,0 +1,17 @@
+package no.nordicsemi.android.nrfmeshprovisioner.viewmodels;
+
+import javax.inject.Inject;
+
+import androidx.annotation.NonNull;
+import no.nordicsemi.android.nrfmeshprovisioner.keys.AppKeysActivity;
+
+/**
+ * ViewModel for {@link AppKeysActivity}
+ */
+public class AppKeysViewModel extends KeysViewModel {
+
+ @Inject
+ AppKeysViewModel(@NonNull final NrfMeshRepository nrfMeshRepository) {
+ super(nrfMeshRepository);
+ }
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/BaseViewModel.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/BaseViewModel.java
new file mode 100644
index 000000000..515d3c028
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/BaseViewModel.java
@@ -0,0 +1,303 @@
+package no.nordicsemi.android.nrfmeshprovisioner.viewmodels;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+
+import com.google.android.material.snackbar.Snackbar;
+
+import java.util.List;
+
+import androidx.annotation.NonNull;
+import androidx.coordinatorlayout.widget.CoordinatorLayout;
+import androidx.lifecycle.LiveData;
+import androidx.lifecycle.ViewModel;
+import no.nordicsemi.android.meshprovisioner.Group;
+import no.nordicsemi.android.meshprovisioner.MeshManagerApi;
+import no.nordicsemi.android.meshprovisioner.models.ConfigurationClientModel;
+import no.nordicsemi.android.meshprovisioner.models.ConfigurationServerModel;
+import no.nordicsemi.android.meshprovisioner.models.GenericLevelServerModel;
+import no.nordicsemi.android.meshprovisioner.models.GenericOnOffServerModel;
+import no.nordicsemi.android.meshprovisioner.models.VendorModel;
+import no.nordicsemi.android.meshprovisioner.transport.Element;
+import no.nordicsemi.android.meshprovisioner.transport.MeshMessage;
+import no.nordicsemi.android.meshprovisioner.transport.MeshModel;
+import no.nordicsemi.android.meshprovisioner.transport.ProvisionedMeshNode;
+import no.nordicsemi.android.nrfmeshprovisioner.R;
+import no.nordicsemi.android.nrfmeshprovisioner.adapter.ExtendedBluetoothDevice;
+import no.nordicsemi.android.nrfmeshprovisioner.ble.BleMeshManager;
+import no.nordicsemi.android.nrfmeshprovisioner.ble.ScannerActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.node.ConfigurationClientActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.node.ConfigurationServerActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.node.GenericLevelServerActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.node.GenericOnOffServerActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.node.ModelConfigurationActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.node.VendorModelActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.utils.Utils;
+
+/**
+ * abstract base class for ViewModels
+ */
+abstract class BaseViewModel extends ViewModel {
+
+ final NrfMeshRepository mNrfMeshRepository;
+ boolean isActivityVisibile = false;
+
+ /**
+ * Constructs {@link BaseViewModel}
+ *
+ * @param nRfMeshRepository Mesh Repository {@link NrfMeshRepository}
+ */
+ BaseViewModel(@NonNull final NrfMeshRepository nRfMeshRepository) {
+ mNrfMeshRepository = nRfMeshRepository;
+ }
+
+ @Override
+ protected void onCleared() {
+ super.onCleared();
+ }
+
+ /**
+ * Returns the Mesh repository
+ */
+ public final NrfMeshRepository getNrfMeshRepository() {
+ return mNrfMeshRepository;
+ }
+
+ /**
+ * Returns the {@link BleMeshManager}
+ */
+ public final BleMeshManager getBleMeshManager() {
+ return mNrfMeshRepository.getBleMeshManager();
+ }
+
+ /**
+ * Navigate to scanner activity
+ *
+ * @param context Activity context
+ * @param withResult Start activity with result
+ * @param requestCode Request code when using with result
+ * @param withProvisioningService Scan with provisioning service
+ */
+ public void navigateToScannerActivity(@NonNull final Activity context, final boolean withResult, final int requestCode, final boolean withProvisioningService) {
+ final Intent intent = new Intent(context, ScannerActivity.class);
+ intent.putExtra(Utils.EXTRA_DATA_PROVISIONING_SERVICE, withProvisioningService);
+ if (withResult) {
+ context.startActivityForResult(intent, requestCode);
+ } else {
+ context.startActivity(intent);
+ }
+ }
+
+ /**
+ * Start activity based on the type of the model
+ *
+ * This way we can seperate the ui logic for different activities
+ *
+ * @param context Activity context
+ * @param model {@link MeshModel}
+ */
+ public void navigateToModelActivity(@NonNull final Activity context, @NonNull final MeshModel model) {
+ final Intent intent;
+ if (model instanceof ConfigurationServerModel) {
+ intent = new Intent(context, ConfigurationServerActivity.class);
+ } else if (model instanceof ConfigurationClientModel) {
+ intent = new Intent(context, ConfigurationClientActivity.class);
+ } else if (model instanceof GenericOnOffServerModel) {
+ intent = new Intent(context, GenericOnOffServerActivity.class);
+ } else if (model instanceof GenericLevelServerModel) {
+ intent = new Intent(context, GenericLevelServerActivity.class);
+ } else if (model instanceof VendorModel) {
+ intent = new Intent(context, VendorModelActivity.class);
+ } else {
+ intent = new Intent(context, ModelConfigurationActivity.class);
+ }
+ context.startActivity(intent);
+ }
+
+ /**
+ * Connect to peripheral
+ *
+ * @param context Context
+ * @param device {@link ExtendedBluetoothDevice} device
+ * @param connectToNetwork True if connecting to an unprovisioned node or proxy node
+ */
+ public final void connect(@NonNull final Context context, @NonNull final ExtendedBluetoothDevice device, final boolean connectToNetwork) {
+ mNrfMeshRepository.connect(context, device, connectToNetwork);
+ }
+
+ /**
+ * Disconnect from peripheral
+ */
+ public final void disconnect() {
+ mNrfMeshRepository.disconnect();
+ }
+
+ /**
+ * Returns the address of the connected proxy address
+ */
+ public final LiveData getConnectedProxyAddress() {
+ return mNrfMeshRepository.getConnectedProxyAddress();
+ }
+
+ /**
+ * Returns true currently connected to a peripheral device.
+ */
+ public final LiveData isConnected() {
+ return mNrfMeshRepository.isConnected();
+ }
+
+ /**
+ * Returns true if the device is ready
+ */
+ public final LiveData isDeviceReady() {
+ return mNrfMeshRepository.isDeviceReady();
+ }
+
+ /**
+ * Returns the connection state
+ */
+ public final LiveData getConnectionState() {
+ return mNrfMeshRepository.getConnectionState();
+ }
+
+ /**
+ * Returns true if currently connected to the proxy node in the mesh network.
+ */
+ public final LiveData isConnectedToProxy() {
+ return mNrfMeshRepository.isConnectedToProxy();
+ }
+
+ /**
+ * Returns the mesh manager api
+ */
+ public final MeshManagerApi getMeshManagerApi() {
+ return mNrfMeshRepository.getMeshManagerApi();
+ }
+
+ /**
+ * Returns live data object containing provisioning settings.
+ */
+ public final MeshNetworkLiveData getNetworkLiveData() {
+ return mNrfMeshRepository.getMeshNetworkLiveData();
+ }
+
+ /**
+ * Returns the provisioned nodes as a live data object.
+ */
+ public LiveData> getNodes() {
+ return mNrfMeshRepository.getNodes();
+ }
+
+ /**
+ * Get selected {@link ProvisionedMeshNode} mesh node
+ */
+ public final LiveData getSelectedMeshNode() {
+ return mNrfMeshRepository.getSelectedMeshNode();
+ }
+
+ /**
+ * Set selected mesh node
+ *
+ * @param node {@link ProvisionedMeshNode}
+ */
+ public final void setSelectedMeshNode(@NonNull final ProvisionedMeshNode node) {
+ mNrfMeshRepository.setSelectedMeshNode(node);
+ }
+
+ /**
+ * Get selected element
+ */
+ public final LiveData getSelectedElement() {
+ return mNrfMeshRepository.getSelectedElement();
+ }
+
+ /**
+ * Set the element to be configured
+ *
+ * @param element {@link Element}
+ */
+ public final void setSelectedElement(@NonNull final Element element) {
+ mNrfMeshRepository.setSelectedElement(element);
+ }
+
+ /**
+ * Get selected model
+ */
+ public final LiveData getSelectedModel() {
+ return mNrfMeshRepository.getSelectedModel();
+ }
+
+ /**
+ * Set the mesh model to be configured
+ *
+ * @param model {@link MeshModel}
+ */
+ public final void setSelectedModel(@NonNull final MeshModel model) {
+ mNrfMeshRepository.setSelectedModel(model);
+ }
+
+ /**
+ * Returns the LiveData containing a list of {@link Group}
+ */
+ public final LiveData> getGroups() {
+ return mNrfMeshRepository.getGroups();
+ }
+
+ /**
+ * Reset mesh network
+ */
+ public final void resetMeshNetwork() {
+ mNrfMeshRepository.resetMeshNetwork();
+ }
+
+ /**
+ * Returns the LiveData containing {@link MeshMessage}
+ */
+ public final LiveData getMeshMessage() {
+ return mNrfMeshRepository.getMeshMessageLiveData();
+ }
+
+ /**
+ * Returns an observable live data object containing the transaction status.
+ *
+ * @return {@link TransactionStatus}
+ */
+ public final LiveData getTransactionStatus() {
+ return mNrfMeshRepository.getTransactionStatus();
+ }
+
+ @SuppressWarnings("BooleanMethodIsAlwaysInverted")
+ public boolean isModelExists(final int modelId) {
+ final ProvisionedMeshNode node = getSelectedMeshNode().getValue();
+ return node != null && node.isExist(modelId);
+ }
+
+ /**
+ * Display disconnected snack bar
+ *
+ * @param context Activity context
+ * @param container container
+ */
+ public void displayDisconnectedSnackBar(@NonNull final Activity context, @NonNull final CoordinatorLayout container) {
+ Snackbar.make(container, context.getString(R.string.disconnected_network_rationale), Snackbar.LENGTH_LONG)
+ .setActionTextColor(context.getResources().getColor(R.color.colorPrimaryDark))
+ .setAction(context.getString(R.string.action_connect), v ->
+ navigateToScannerActivity(context, false, Utils.CONNECT_TO_NETWORK, false))
+ .show();
+ }
+
+ /**
+ * Display snack bar
+ *
+ * @param context Activity context
+ * @param container Coordinator layout
+ * @param message Message
+ * @param duration Snack bar duration
+ */
+ public void displaySnackBar(@NonNull final Activity context, @NonNull final CoordinatorLayout container, @NonNull final String message, final int duration) {
+ Snackbar.make(container, message, duration)
+ .setActionTextColor(context.getResources().getColor(R.color.colorPrimaryDark))
+ .show();
+ }
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/EditAppKeyViewModel.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/EditAppKeyViewModel.java
new file mode 100644
index 000000000..e089bd6cb
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/EditAppKeyViewModel.java
@@ -0,0 +1,17 @@
+package no.nordicsemi.android.nrfmeshprovisioner.viewmodels;
+
+import javax.inject.Inject;
+
+import androidx.annotation.NonNull;
+import no.nordicsemi.android.nrfmeshprovisioner.keys.AppKeysActivity;
+
+/**
+ * ViewModel for {@link AppKeysActivity}
+ */
+public class EditAppKeyViewModel extends KeysViewModel {
+
+ @Inject
+ EditAppKeyViewModel(@NonNull final NrfMeshRepository nrfMeshRepository) {
+ super(nrfMeshRepository);
+ }
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/EditNetKeyViewModel.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/EditNetKeyViewModel.java
new file mode 100644
index 000000000..483b271a5
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/EditNetKeyViewModel.java
@@ -0,0 +1,17 @@
+package no.nordicsemi.android.nrfmeshprovisioner.viewmodels;
+
+import javax.inject.Inject;
+
+import androidx.annotation.NonNull;
+import no.nordicsemi.android.nrfmeshprovisioner.keys.AppKeysActivity;
+
+/**
+ * ViewModel for {@link AppKeysActivity}
+ */
+public class EditNetKeyViewModel extends KeysViewModel {
+
+ @Inject
+ EditNetKeyViewModel(@NonNull final NrfMeshRepository nrfMeshRepository) {
+ super(nrfMeshRepository);
+ }
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/EditProvisionerViewModel.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/EditProvisionerViewModel.java
new file mode 100644
index 000000000..537a2e367
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/EditProvisionerViewModel.java
@@ -0,0 +1,27 @@
+package no.nordicsemi.android.nrfmeshprovisioner.viewmodels;
+
+import javax.inject.Inject;
+
+import androidx.annotation.NonNull;
+import androidx.lifecycle.LiveData;
+import no.nordicsemi.android.meshprovisioner.Provisioner;
+import no.nordicsemi.android.nrfmeshprovisioner.keys.AppKeysActivity;
+
+/**
+ * ViewModel for {@link AppKeysActivity}
+ */
+public class EditProvisionerViewModel extends BaseViewModel {
+
+ @Inject
+ EditProvisionerViewModel(@NonNull final NrfMeshRepository nrfMeshRepository) {
+ super(nrfMeshRepository);
+ }
+
+ public void setSelectedProvisioner(@NonNull final Provisioner provisioner) {
+ mNrfMeshRepository.setSelectedProvisioner(provisioner);
+ }
+
+ public LiveData getSelectedProvisioner() {
+ return mNrfMeshRepository.getSelectedProvisioner();
+ }
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/ExtendedMeshNode.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/ExtendedMeshNode.java
index e9a5288f7..fff6c55d5 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/ExtendedMeshNode.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/ExtendedMeshNode.java
@@ -22,7 +22,7 @@
package no.nordicsemi.android.nrfmeshprovisioner.viewmodels;
-import android.arch.lifecycle.LiveData;
+import androidx.lifecycle.LiveData;
import no.nordicsemi.android.meshprovisioner.transport.ProvisionedMeshNode;
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/GroupControlsViewModel.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/GroupControlsViewModel.java
index 34ae9f21a..caf20b159 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/GroupControlsViewModel.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/GroupControlsViewModel.java
@@ -22,31 +22,23 @@
package no.nordicsemi.android.nrfmeshprovisioner.viewmodels;
-import android.arch.lifecycle.LiveData;
-import android.arch.lifecycle.ViewModel;
-import android.content.Context;
-
-import java.util.List;
-
import javax.inject.Inject;
+import androidx.annotation.NonNull;
+import androidx.lifecycle.LiveData;
import no.nordicsemi.android.meshprovisioner.Group;
-import no.nordicsemi.android.meshprovisioner.MeshManagerApi;
-import no.nordicsemi.android.meshprovisioner.transport.Element;
-import no.nordicsemi.android.meshprovisioner.transport.MeshMessage;
-import no.nordicsemi.android.meshprovisioner.transport.MeshModel;
-import no.nordicsemi.android.meshprovisioner.transport.ProvisionedMeshNode;
-import no.nordicsemi.android.nrfmeshprovisioner.adapter.ExtendedBluetoothDevice;
-import no.nordicsemi.android.nrfmeshprovisioner.ble.BleMeshManager;
+import no.nordicsemi.android.nrfmeshprovisioner.GroupControlsActivity;
-public class GroupControlsViewModel extends ViewModel {
+/**
+ * ViewModel for {@link GroupControlsActivity}
+ */
+public class GroupControlsViewModel extends BaseViewModel {
- private final NrfMeshRepository mNrfMeshRepository;
private final ScannerRepository mScannerRepository;
@Inject
- GroupControlsViewModel(final NrfMeshRepository nrfMeshRepository, final ScannerRepository scannerRepository) {
- this.mNrfMeshRepository = nrfMeshRepository;
+ GroupControlsViewModel(@NonNull final NrfMeshRepository nrfMeshRepository, @NonNull final ScannerRepository scannerRepository) {
+ super(nrfMeshRepository);
this.mScannerRepository = scannerRepository;
scannerRepository.registerBroadcastReceivers();
}
@@ -57,111 +49,10 @@ protected void onCleared() {
mScannerRepository.unregisterBroadcastReceivers();
}
- public LiveData isDeviceReady() {
- return mNrfMeshRepository.isDeviceReady();
- }
-
- public LiveData getConnectionState() {
- return mNrfMeshRepository.getConnectionState();
- }
-
- public LiveData isConnected() {
- return mNrfMeshRepository.isConnected();
- }
-
- public void connect(final Context context, final ExtendedBluetoothDevice device, final boolean connectToNetwork) {
- mNrfMeshRepository.connect(context, device, connectToNetwork);
- }
-
- public void disconnect() {
- mNrfMeshRepository.disconnect();
- }
-
- public NrfMeshRepository getNrfMeshRepository() {
- return mNrfMeshRepository;
- }
-
- public BleMeshManager getBleMeshManager() {
- return mNrfMeshRepository.getBleMeshManager();
- }
-
- public MeshManagerApi getMeshManagerApi() {
- return mNrfMeshRepository.getMeshManagerApi();
- }
-
/**
- * Returns an instance of the scanner repository
+ * Returns the selected LiveData {@link Group}
*/
- public ScannerRepository getScannerRepository() {
- return mScannerRepository;
- }
-
public LiveData getSelectedGroup() {
return mNrfMeshRepository.getSelectedGroup();
}
- /**
- * Returns the provisioned nodes as a live data object.
- */
- public LiveData> getProvisionedNodes() {
- return mNrfMeshRepository.getProvisionedNodes();
- }
-
- /**
- * Returns if currently connected to the mesh network.
- *
- * @return true if connected and false otherwise
- */
- public LiveData isConnectedToProxy() {
- return mNrfMeshRepository.isConnectedToProxy();
- }
-
- public MeshNetworkLiveData getMeshNetworkLiveData() {
- return mNrfMeshRepository.getMeshNetworkLiveData();
- }
-
- public LiveData getMeshMessageLiveData() {
- return mNrfMeshRepository.getMeshMessageLiveData();
- }
-
- /**
- * Set the mesh node to be configured
- *
- * @param meshNode provisioned mesh node
- */
- public void setSelectedMeshNode(final ProvisionedMeshNode meshNode) {
- mNrfMeshRepository.setSelectedMeshNode(meshNode);
- }
-
- /**
- * Set the element to be configured
- *
- * @param element {@link Element}
- */
- public void setSelectedElement(final Element element) {
- mNrfMeshRepository.setSelectedElement(element);
- }
-
- /**
- * Get selected model
- */
- public LiveData getSelectedModel() {
- return mNrfMeshRepository.getSelectedModel();
- }
-
- /**
- * Set the mesh model to be configured
- *
- * @param model {@link MeshModel}
- */
- public void setSelectedModel(final MeshModel model) {
- mNrfMeshRepository.setSelectedModel(model);
- }
- /**
- * Get selected mesh node
- *
- * @return {@link ExtendedMeshNode} element
- */
- public LiveData getSelectedMeshNode() {
- return mNrfMeshRepository.getSelectedMeshNode();
- }
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/KeysViewModel.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/KeysViewModel.java
new file mode 100644
index 000000000..d318d227f
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/KeysViewModel.java
@@ -0,0 +1,15 @@
+package no.nordicsemi.android.nrfmeshprovisioner.viewmodels;
+
+import androidx.annotation.NonNull;
+import no.nordicsemi.android.nrfmeshprovisioner.keys.AppKeysActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.keys.NetKeysActivity;
+
+/**
+ * ViewModel for {@link NetKeysActivity}, {@link AppKeysActivity}
+ */
+abstract class KeysViewModel extends BaseViewModel {
+
+ KeysViewModel(@NonNull final NrfMeshRepository nrfMeshRepository) {
+ super(nrfMeshRepository);
+ }
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/ManageAppKeysViewModel.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/ManageAppKeysViewModel.java
deleted file mode 100644
index 08c6cc78e..000000000
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/ManageAppKeysViewModel.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package no.nordicsemi.android.nrfmeshprovisioner.viewmodels;
-
-import android.arch.lifecycle.LiveData;
-import android.arch.lifecycle.ViewModel;
-
-import javax.inject.Inject;
-
-import no.nordicsemi.android.meshprovisioner.transport.ProvisionedMeshNode;
-import no.nordicsemi.android.nrfmeshprovisioner.ManageAppKeysActivity;
-
-/**
- * ViewModel for {@link ManageAppKeysActivity}
- */
-public class ManageAppKeysViewModel extends ViewModel {
-
- private final NrfMeshRepository mNrfMeshRepository;
-
- @Inject
- ManageAppKeysViewModel(final NrfMeshRepository nrfMeshRepository) {
- mNrfMeshRepository = nrfMeshRepository;
- }
-
- /**
- * Returns live data object containing provisioning settings.
- */
- public MeshNetworkLiveData getMeshNetworkLiveData() {
- return mNrfMeshRepository.getMeshNetworkLiveData();
- }
-
- public LiveData getSelectedMeshNode() {
- return mNrfMeshRepository.getSelectedMeshNode();
- }
-}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/MeshMessageLiveData.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/MeshMessageLiveData.java
index 55aa9aaed..56293f2d1 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/MeshMessageLiveData.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/MeshMessageLiveData.java
@@ -1,7 +1,9 @@
package no.nordicsemi.android.nrfmeshprovisioner.viewmodels;
-import android.arch.lifecycle.LifecycleOwner;
-import android.arch.lifecycle.Observer;
+import androidx.annotation.MainThread;
+import androidx.annotation.NonNull;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.lifecycle.Observer;
import no.nordicsemi.android.meshprovisioner.transport.MeshMessage;
@@ -13,7 +15,8 @@ public void postValue(final MeshMessage value) {
}
@Override
- public void observe(final LifecycleOwner owner, final Observer observer) {
+ @MainThread
+ public void observe(@NonNull final LifecycleOwner owner, @NonNull final Observer super MeshMessage> observer) {
super.observe(owner, observer);
}
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/MeshNetworkLiveData.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/MeshNetworkLiveData.java
index 66aafe6c4..d4b9687b7 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/MeshNetworkLiveData.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/MeshNetworkLiveData.java
@@ -22,15 +22,16 @@
package no.nordicsemi.android.nrfmeshprovisioner.viewmodels;
-import android.arch.lifecycle.LiveData;
-import android.support.annotation.NonNull;
+import android.text.TextUtils;
import java.util.List;
+import androidx.annotation.NonNull;
+import androidx.lifecycle.LiveData;
+import no.nordicsemi.android.meshprovisioner.ApplicationKey;
import no.nordicsemi.android.meshprovisioner.MeshNetwork;
-import no.nordicsemi.android.meshprovisioner.transport.ApplicationKey;
-import no.nordicsemi.android.meshprovisioner.transport.NetworkKey;
-import no.nordicsemi.android.meshprovisioner.utils.AddressUtils;
+import no.nordicsemi.android.meshprovisioner.NetworkKey;
+import no.nordicsemi.android.meshprovisioner.Provisioner;
/**
* LiveData class for storing {@link MeshNetwork}
@@ -69,21 +70,8 @@ void refresh(@NonNull final MeshNetwork meshNetwork) {
postValue(this);
}
- /**
- * Returns the primary network key in the mesh network
- */
- public NetworkKey getPrimaryNetworkKey() {
- return meshNetwork.getPrimaryNetworkKey();
- }
-
- /**
- * Sets primary network key
- *
- * @param networkKey network key
- */
- public void setPrimaryNetworkKey(final String networkKey) {
- meshNetwork.addNetKey(0, networkKey);
- postValue(this);
+ public List getNetworkKeys() {
+ return meshNetwork.getNetKeys();
}
/**
@@ -94,104 +82,14 @@ public List getAppKeys() {
}
/**
- * Returns the network key index
- */
- public int getKeyIndex() {
- return meshNetwork.getNetKeys().get(0).getKeyIndex();
- }
-
- /**
- * Set network key index
- *
- * @param keyIndex network key index
- */
- public void setKeyIndex(final int keyIndex) {
- meshNetwork.getNetKeys().get(0).setKeyIndex(keyIndex);
- postValue(this);
- }
-
- /**
- * Returns the IV Index used for provisioning
- *
- * @return iv index
- */
- public int getIvIndex() {
- return meshNetwork.getIvIndex();
- }
-
- /**
- * Set IV Index
- *
- * @param ivIndex 24-bit iv index
- */
- public void setIvIndex(final int ivIndex) {
- meshNetwork.setIvIndex(ivIndex);
- postValue(this);
- }
-
- /**
- * Returns unicast address
- *
- * @return 16-bit unicast address
- */
- public int getUnicastAddress() {
- final byte[] unicast = AddressUtils.getUnicastAddressBytes(meshNetwork.getUnicastAddress());
- return AddressUtils.getUnicastAddressInt(unicast);
- }
-
- /**
- * Set unicast address, this would be the address assigned to an unprovisioned node.
- *
- * @param unicastAddress 16-bit unicast address
- */
- public void setUnicastAddress(final int unicastAddress) {
- meshNetwork.assignUnicastAddress(unicastAddress);
- postValue(this);
- }
-
- public byte[] getProvisionerAddress() {
- return AddressUtils.getUnicastAddressBytes(meshNetwork.getProvisionerAddress());
- }
-
- public boolean setProvisionerAddress(final int address) {
- final boolean flag = meshNetwork.setProvisionerAddress(address);
- if (flag) {
- postValue(this);
- }
- return flag;
- }
-
- /**
- * Provisioning flags
- */
- public int getFlags() {
- return meshNetwork.getProvisioningFlags();
- }
-
- /**
- * Provisioning flags
- *
- * @param flags provisioning flags
- */
- public void setFlags(final int flags) {
- postValue(this);
- }
-
- /**
- * Returns the global ttl set for the messages sent by the provisioner
+ * Returns the list of {@link Provisioner}
*/
- public int getGlobalTtl() {
- return meshNetwork.getGlobalTtl();
+ public List getProvisioners() {
+ return meshNetwork.getProvisioners();
}
- /**
- * Sets a global ttl value that would be used on all messages sent from the provisioner
- *
- * @param globalTtl ttl value
- */
- public void setGlobalTtl(final int globalTtl) {
- meshNetwork.setGlobalTtl(globalTtl);
- postValue(this);
+ public Provisioner getProvisioner() {
+ return meshNetwork.getSelectedProvisioner();
}
/**
@@ -213,54 +111,10 @@ public void setSelectedAppKey(final ApplicationKey appKey) {
postValue(this);
}
- public void resetSelectedAppKey(){
+ public void resetSelectedAppKey() {
this.selectedAppKey = null;
}
- /**
- * Adds an application key to the next available index in the global app key list
- * @param applicationKey key {@link ApplicationKey}
- */
- public void addAppKey(final String applicationKey) {
- if (meshNetwork != null) {
- meshNetwork.addAppKey(applicationKey);
- }
- postValue(this);
- }
-
- /**
- * Adds an application key to the mesh network
- */
- public void addAppKey(final ApplicationKey applicationKey) {
- if (meshNetwork != null) {
- meshNetwork.addAppKey(applicationKey);
- }
- postValue(this);
- }
-
- /**
- * Update the application key in a particular position
- * @param keyIndex update app key in given key index
- * @param applicationKey app key
- */
- public void updateAppKey(final int keyIndex, final String applicationKey) {
- if (meshNetwork != null) {
- meshNetwork.updateAppKey(keyIndex, applicationKey);
- }
- postValue(this);
- }
-
- /**
- * Remove app key from the list of application keys in the mesh network
- * @param appKey key {@link ApplicationKey}
- */
- public void removeAppKey(final ApplicationKey appKey) {
- if (meshNetwork != null) {
- meshNetwork.removeAppKey(appKey);
- }
- postValue(this);
- }
-
/**
* Returns the network name
*/
@@ -270,19 +124,21 @@ public String getNetworkName() {
/**
* Set the network name of the mesh network
+ *
* @param name network name
*/
public void setNetworkName(final String name) {
meshNetwork.setMeshName(name);
postValue(this);
}
+
/**
* Sets the node name
*
* @param nodeName node name
*/
- public void setNodeName(final String nodeName) {
- if (nodeName != null && !nodeName.isEmpty()) {
+ public void setNodeName(@NonNull final String nodeName) {
+ if (!TextUtils.isEmpty(nodeName)) {
this.nodeName = nodeName;
postValue(this);
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/ModelConfigurationViewModel.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/ModelConfigurationViewModel.java
index 1fe39fcd3..e3f65ada2 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/ModelConfigurationViewModel.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/ModelConfigurationViewModel.java
@@ -22,91 +22,55 @@
package no.nordicsemi.android.nrfmeshprovisioner.viewmodels;
-import android.arch.lifecycle.LiveData;
-import android.arch.lifecycle.ViewModel;
-
-import java.util.List;
+import java.util.LinkedList;
+import java.util.Queue;
import javax.inject.Inject;
-import no.nordicsemi.android.meshprovisioner.Group;
-import no.nordicsemi.android.meshprovisioner.MeshManagerApi;
-import no.nordicsemi.android.meshprovisioner.transport.Element;
+import androidx.annotation.NonNull;
import no.nordicsemi.android.meshprovisioner.transport.MeshMessage;
-import no.nordicsemi.android.meshprovisioner.transport.MeshModel;
-import no.nordicsemi.android.meshprovisioner.transport.ProvisionedMeshNode;
-import no.nordicsemi.android.nrfmeshprovisioner.ConfigurationServerActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.node.ConfigurationClientActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.node.ConfigurationServerActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.node.GenericLevelServerActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.node.GenericOnOffServerActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.node.ModelConfigurationActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.node.VendorModelActivity;
/**
- * View Model class for {@link ConfigurationServerActivity}
+ * Generic View Model class for {@link ConfigurationServerActivity},{@link ConfigurationClientActivity},
+ * {@link GenericOnOffServerActivity}, {@link GenericLevelServerActivity}, {@link VendorModelActivity},
+ * {@link ModelConfigurationActivity}
*/
-public class ModelConfigurationViewModel extends ViewModel {
+public class ModelConfigurationViewModel extends BaseViewModel {
- private final NrfMeshRepository mNrfMeshRepository;
+ private Queue messageQueue = new LinkedList<>();
@Inject
- ModelConfigurationViewModel(final NrfMeshRepository nrfMeshRepository) {
- this.mNrfMeshRepository = nrfMeshRepository;
- }
-
- public LiveData isConnectedToProxy() {
- return mNrfMeshRepository.isConnectedToProxy();
- }
-
- /**
- * Returns the Mesh repository
- */
- public NrfMeshRepository getNrfMeshRepository() {
- return mNrfMeshRepository;
- }
-
- /**
- * Returns the mesh manager api
- */
- public MeshManagerApi getMeshManagerApi() {
- return mNrfMeshRepository.getMeshManagerApi();
- }
-
- /**
- * Returns an observable live data object containing the mesh message received
- *
- * @return {@link MeshMessageLiveData}
- */
- public LiveData getMeshMessageLiveData() {
- return mNrfMeshRepository.getMeshMessageLiveData();
+ ModelConfigurationViewModel(@NonNull final NrfMeshRepository nrfMeshRepository) {
+ super(nrfMeshRepository);
}
- /**
- * Get selected mesh node
- */
- public LiveData getSelectedMeshNode() {
- return mNrfMeshRepository.getSelectedMeshNode();
+ @Override
+ protected void onCleared() {
+ super.onCleared();
+ mNrfMeshRepository.clearTransactionStatus();
+ messageQueue.clear();
}
- /**
- * Get selected element
- */
- public LiveData getSelectedElement() {
- return mNrfMeshRepository.getSelectedElement();
+ public Queue getMessageQueue() {
+ return messageQueue;
}
- /**
- * Get selected model
- */
- public LiveData getSelectedModel() {
- return mNrfMeshRepository.getSelectedModel();
+ public void removeMessage() {
+ if (!messageQueue.isEmpty())
+ messageQueue.remove();
}
- /**
- * Returns an observable live data object containing the transaction status.
- *
- * @return {@link TransactionStatusLiveData}
- */
- public TransactionStatusLiveData getTransactionStatus() {
- return mNrfMeshRepository.getTransactionStatusLiveData();
+ public boolean isActivityVisibile() {
+ return isActivityVisibile;
}
- public LiveData> getGroups(){
- return mNrfMeshRepository.getGroups();
+ public void setActivityVisible(final boolean visible){
+ isActivityVisibile = visible;
}
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/NetKeysViewModel.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/NetKeysViewModel.java
new file mode 100644
index 000000000..e5c1c77a3
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/NetKeysViewModel.java
@@ -0,0 +1,17 @@
+package no.nordicsemi.android.nrfmeshprovisioner.viewmodels;
+
+import javax.inject.Inject;
+
+import androidx.annotation.NonNull;
+import no.nordicsemi.android.nrfmeshprovisioner.keys.AppKeysActivity;
+
+/**
+ * ViewModel for {@link AppKeysActivity}
+ */
+public class NetKeysViewModel extends KeysViewModel {
+
+ @Inject
+ NetKeysViewModel(@NonNull final NrfMeshRepository nrfMeshRepository) {
+ super(nrfMeshRepository);
+ }
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/NetworkInformation.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/NetworkInformation.java
deleted file mode 100644
index cb236d5d0..000000000
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/NetworkInformation.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright (c) 2018, Nordic Semiconductor
- * 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 no.nordicsemi.android.nrfmeshprovisioner.viewmodels;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-
-/**
- * Contains the default information network and node name. Changing the network name will save the data in to the shared preferences
- */
-@SuppressWarnings("unused")
-public class NetworkInformation {
-
- private String networkName = "nRF Mesh Network";
- private String nodeName = "nRF Mesh Node";
- private String NETWORK_NAME_PREFS = "NETWORK_NAME_PREFS";
- private String NETWORK_NAME = "NETWORK_NAME";
-
- private NetworkInformationListener mListener;
-
- /**
- * Interface that listens to changes made on network information.
- */
- interface NetworkInformationListener {
- void onNetworkInformationUpdated(final NetworkInformation networkInformation);
- }
-
- public NetworkInformation(final Context context) {
- loadNetworkName(context);
- }
-
- /**
- * Set the network information listener
- */
- void setNetworkInformationListener(final NetworkInformationListener listener) {
- mListener = listener;
- }
-
- /**
- * Remove the network information listener
- */
- void removeNetworkInformationListener() {
- mListener = null;
- }
-
- public void refreshProvisioningData() {
- networkName = "nRF Mesh Network";
- nodeName = "nRF Mesh Node";
- if (mListener != null) {
- mListener.onNetworkInformationUpdated(this);
- }
- }
-
- /**
- * Sets the node name
- *
- * @param nodeName node name
- */
- public void setNodeName(final String nodeName) {
- if (nodeName != null && !nodeName.isEmpty()) {
- this.nodeName = nodeName;
- if (mListener != null) {
- mListener.onNetworkInformationUpdated(this);
- }
- }
- }
-
- /**
- * Returns the node name
- */
- public String getNodeName() {
- return nodeName;
- }
-
- /**
- * Returns the network name
- */
- public String getNetworkName() {
- return networkName;
- }
-
- /**
- * Sets the network name. This will be saved locally to shared preferences.
- *
- * @param context application context
- * @param networkName network name
- */
- public void setNetworkName(final Context context, final String networkName) {
- this.networkName = networkName;
- saveNetworkName(context);
- if (mListener != null) {
- mListener.onNetworkInformationUpdated(this);
- }
- }
-
- /**
- * Loads the saved network name from the preferences.
- *
- * @param context application context
- */
- private void loadNetworkName(final Context context) {
- final SharedPreferences preferences = context.getSharedPreferences(NETWORK_NAME_PREFS, Context.MODE_PRIVATE);
- networkName = preferences.getString(NETWORK_NAME, networkName);
- }
-
- /**
- * Saves the network name to shared preferences.
- *
- * @param context Application context
- */
- private void saveNetworkName(final Context context) {
- final SharedPreferences preferences = context.getSharedPreferences(NETWORK_NAME_PREFS, Context.MODE_PRIVATE);
- final SharedPreferences.Editor editor = preferences.edit();
- editor.putString(NETWORK_NAME, networkName);
- editor.apply();
- }
-}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/NetworkInformationLiveData.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/NetworkInformationLiveData.java
deleted file mode 100644
index e0fc95fc5..000000000
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/NetworkInformationLiveData.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package no.nordicsemi.android.nrfmeshprovisioner.viewmodels;
-
-import android.arch.lifecycle.LiveData;
-
-/**
- * This class is used to observes the updates happening in the {@link NetworkInformation}
- */
-public class NetworkInformationLiveData extends LiveData {
-
- private NetworkInformation mNetworkInformation;
-
- private final NetworkInformation.NetworkInformationListener mListener = new NetworkInformation.NetworkInformationListener() {
- @Override
- public void onNetworkInformationUpdated(final NetworkInformation networkInformation) {
- mNetworkInformation = networkInformation;
- postValue(networkInformation);
- }
- };
-
- NetworkInformationLiveData (final NetworkInformation networkInformation){
- this.mNetworkInformation = networkInformation;
- postValue(networkInformation);
- }
-
- @Override
- protected void onActive() {
- mNetworkInformation.setNetworkInformationListener(mListener);
- }
-
- @Override
- protected void onInactive() {
- mNetworkInformation.removeNetworkInformationListener();
- }
-}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/NodeConfigurationViewModel.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/NodeConfigurationViewModel.java
index d6b34d5a3..089817b59 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/NodeConfigurationViewModel.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/NodeConfigurationViewModel.java
@@ -22,86 +22,35 @@
package no.nordicsemi.android.nrfmeshprovisioner.viewmodels;
-import android.arch.lifecycle.LiveData;
-import android.arch.lifecycle.ViewModel;
-
import javax.inject.Inject;
-import no.nordicsemi.android.meshprovisioner.MeshManagerApi;
-import no.nordicsemi.android.meshprovisioner.transport.Element;
-import no.nordicsemi.android.meshprovisioner.transport.MeshMessage;
-import no.nordicsemi.android.meshprovisioner.transport.MeshModel;
+import androidx.annotation.NonNull;
+
+import no.nordicsemi.android.meshprovisioner.models.SigModelParser;
import no.nordicsemi.android.meshprovisioner.transport.ProvisionedMeshNode;
-import no.nordicsemi.android.nrfmeshprovisioner.NodeConfigurationActivity;
+import no.nordicsemi.android.nrfmeshprovisioner.node.NodeConfigurationActivity;
/**
* View model class for {@link NodeConfigurationActivity}
*/
-public class NodeConfigurationViewModel extends ViewModel {
-
- private final NrfMeshRepository mNrfMeshRepository;
+public class NodeConfigurationViewModel extends BaseViewModel {
@Inject
- NodeConfigurationViewModel(final NrfMeshRepository nrfMeshRepository) {
- this.mNrfMeshRepository = nrfMeshRepository;
- }
-
- public LiveData getSelectedMeshNode() {
- return mNrfMeshRepository.getSelectedMeshNode();
- }
-
- /**
- * Set the element to be configured
- *
- * @param element {@link Element}
- */
- public void setSelectedElement(final Element element) {
- mNrfMeshRepository.setSelectedElement(element);
- }
-
- /**
- * Set the mesh model to be configured
- *
- * @param model {@link MeshModel}
- */
- public void setSelectedModel(final MeshModel model) {
- mNrfMeshRepository.setSelectedModel(model);
+ NodeConfigurationViewModel(@NonNull final NrfMeshRepository nrfMeshRepository) {
+ super(nrfMeshRepository);
}
- public LiveData isConnected() {
- return mNrfMeshRepository.isConnected();
+ @Override
+ protected void onCleared() {
+ super.onCleared();
+ mNrfMeshRepository.clearTransactionStatus();
}
- public LiveData isConnectedToProxy() {
- return mNrfMeshRepository.isConnected();
+ public boolean isActivityVisibile() {
+ return isActivityVisibile;
}
- public LiveData getMeshMessageLiveData() {
- return mNrfMeshRepository.getMeshMessageLiveData();
+ public void setActivityVisible(final boolean visible){
+ isActivityVisibile = visible;
}
-
- /**
- * Returns an observable live data object containing the transaction status.
- *
- * @return {@link TransactionStatusLiveData}
- */
- public TransactionStatusLiveData getTransactionStatus() {
- return mNrfMeshRepository.getTransactionStatusLiveData();
- }
-
- /**
- * Returns the {@link MeshManagerApi}
- */
- public MeshManagerApi getMeshManagerApi() {
- return mNrfMeshRepository.getMeshManagerApi();
- }
-
- public NrfMeshRepository getNrfMeshRepository(){
- return mNrfMeshRepository;
- }
-
- public LiveData getConnectedMeshNodeAddress(){
- return mNrfMeshRepository.getConnectedMeshNodeAddress();
- }
-
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/NodeDetailsViewModel.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/NodeDetailsViewModel.java
new file mode 100644
index 000000000..3d0957c1b
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/NodeDetailsViewModel.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2018, Nordic Semiconductor
+ * 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 no.nordicsemi.android.nrfmeshprovisioner.viewmodels;
+
+import javax.inject.Inject;
+
+import androidx.annotation.NonNull;
+import no.nordicsemi.android.nrfmeshprovisioner.node.NodeConfigurationActivity;
+
+/**
+ * View model class for {@link NodeConfigurationActivity}
+ */
+public class NodeDetailsViewModel extends BaseViewModel {
+
+ @Inject
+ NodeDetailsViewModel(@NonNull final NrfMeshRepository nrfMeshRepository) {
+ super(nrfMeshRepository);
+ }
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/NrfMeshRepository.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/NrfMeshRepository.java
index 981baa93f..85b3f834c 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/NrfMeshRepository.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/NrfMeshRepository.java
@@ -1,47 +1,51 @@
package no.nordicsemi.android.nrfmeshprovisioner.viewmodels;
-import android.arch.lifecycle.LiveData;
-import android.arch.lifecycle.MutableLiveData;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.net.Uri;
import android.os.Environment;
import android.os.Handler;
import android.os.ParcelUuid;
-import android.support.annotation.NonNull;
import android.util.Log;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
-import java.util.Map;
import java.util.UUID;
+import androidx.annotation.NonNull;
+import androidx.lifecycle.LiveData;
+import androidx.lifecycle.MutableLiveData;
import no.nordicsemi.android.log.LogSession;
import no.nordicsemi.android.log.Logger;
+import no.nordicsemi.android.meshprovisioner.ApplicationKey;
import no.nordicsemi.android.meshprovisioner.Group;
import no.nordicsemi.android.meshprovisioner.MeshManagerApi;
import no.nordicsemi.android.meshprovisioner.MeshManagerCallbacks;
import no.nordicsemi.android.meshprovisioner.MeshNetwork;
import no.nordicsemi.android.meshprovisioner.MeshProvisioningStatusCallbacks;
import no.nordicsemi.android.meshprovisioner.MeshStatusCallbacks;
+import no.nordicsemi.android.meshprovisioner.NetworkKey;
import no.nordicsemi.android.meshprovisioner.Provisioner;
import no.nordicsemi.android.meshprovisioner.UnprovisionedBeacon;
import no.nordicsemi.android.meshprovisioner.models.SigModelParser;
import no.nordicsemi.android.meshprovisioner.provisionerstates.ProvisioningState;
import no.nordicsemi.android.meshprovisioner.provisionerstates.UnprovisionedMeshNode;
-import no.nordicsemi.android.meshprovisioner.transport.ApplicationKey;
import no.nordicsemi.android.meshprovisioner.transport.ConfigAppKeyAdd;
import no.nordicsemi.android.meshprovisioner.transport.ConfigAppKeyStatus;
import no.nordicsemi.android.meshprovisioner.transport.ConfigCompositionDataGet;
import no.nordicsemi.android.meshprovisioner.transport.ConfigCompositionDataStatus;
+import no.nordicsemi.android.meshprovisioner.transport.ConfigDefaultTtlGet;
+import no.nordicsemi.android.meshprovisioner.transport.ConfigDefaultTtlStatus;
import no.nordicsemi.android.meshprovisioner.transport.ConfigModelAppStatus;
import no.nordicsemi.android.meshprovisioner.transport.ConfigModelPublicationStatus;
import no.nordicsemi.android.meshprovisioner.transport.ConfigModelSubscriptionStatus;
+import no.nordicsemi.android.meshprovisioner.transport.ConfigNetworkTransmitSet;
import no.nordicsemi.android.meshprovisioner.transport.ConfigNetworkTransmitStatus;
import no.nordicsemi.android.meshprovisioner.transport.ConfigNodeResetStatus;
import no.nordicsemi.android.meshprovisioner.transport.ConfigProxyStatus;
import no.nordicsemi.android.meshprovisioner.transport.ConfigRelayStatus;
+import no.nordicsemi.android.meshprovisioner.transport.ControlMessage;
import no.nordicsemi.android.meshprovisioner.transport.Element;
import no.nordicsemi.android.meshprovisioner.transport.GenericLevelStatus;
import no.nordicsemi.android.meshprovisioner.transport.GenericOnOffStatus;
@@ -50,11 +54,11 @@
import no.nordicsemi.android.meshprovisioner.transport.ProvisionedMeshNode;
import no.nordicsemi.android.meshprovisioner.transport.ProxyConfigFilterStatus;
import no.nordicsemi.android.meshprovisioner.transport.VendorModelMessageStatus;
-import no.nordicsemi.android.meshprovisioner.utils.AddressUtils;
import no.nordicsemi.android.meshprovisioner.utils.MeshAddress;
import no.nordicsemi.android.nrfmeshprovisioner.adapter.ExtendedBluetoothDevice;
import no.nordicsemi.android.nrfmeshprovisioner.ble.BleMeshManager;
import no.nordicsemi.android.nrfmeshprovisioner.ble.BleMeshManagerCallbacks;
+import no.nordicsemi.android.nrfmeshprovisioner.utils.ProvisionerStates;
import no.nordicsemi.android.nrfmeshprovisioner.utils.Utils;
import no.nordicsemi.android.support.v18.scanner.BluetoothLeScannerCompat;
import no.nordicsemi.android.support.v18.scanner.ScanCallback;
@@ -74,89 +78,61 @@ public class NrfMeshRepository implements MeshProvisioningStatusCallbacks, MeshS
"Nordic Semiconductor" + File.separator + "nRF Mesh" + File.separator;
private static final String EXPORTED_PATH = "sdcard" + File.separator + "Nordic Semiconductor" + File.separator + "nRF Mesh" + File.separator;
- /**
- * Connection States Connecting, Connected, Disconnecting, Disconnected etc.
- **/
+ // Connection States Connecting, Connected, Disconnecting, Disconnected etc.
private final MutableLiveData mIsConnectedToProxy = new MutableLiveData<>();
- /**
- * Live data flag containing connected state.
- **/
+ // Live data flag containing connected state.
private MutableLiveData mIsConnected;
- /**
- * LiveData to notify when device is ready
- **/
+ // LiveData to notify when device is ready
private final MutableLiveData mOnDeviceReady = new MutableLiveData<>();
- /**
- * Updates the connection state while connecting to a peripheral
- **/
+ // Updates the connection state while connecting to a peripheral
private final MutableLiveData mConnectionState = new MutableLiveData<>();
- /**
- * Flag to determine if a reconnection is in the progress when provisioning has completed
- **/
+ // Flag to determine if a reconnection is in the progress when provisioning has completed
private final SingleLiveEvent mIsReconnecting = new SingleLiveEvent<>();
-
private final MutableLiveData mUnprovisionedMeshNodeLiveData = new MutableLiveData<>();
-
private final MutableLiveData mProvisionedMeshNodeLiveData = new MutableLiveData<>();
+ private final SingleLiveEvent mConnectedProxyAddress = new SingleLiveEvent<>();
- private final SingleLiveEvent mConnectedMeshNodeAddress = new SingleLiveEvent<>();
- /**
- * Contains the initial provisioning live data
- **/
- private NetworkInformationLiveData mNetworkInformationLiveData;
+ private boolean mIsProvisioningComplete = false; // Flag to determine if provisioning was completed
- /**
- * Flag to determine if provisioning was completed
- **/
- private boolean mIsProvisioningComplete = false;
-
- /**
- * Holds the selected MeshNode to configure
- **/
+ // Holds the selected MeshNode to configure
private MutableLiveData mExtendedMeshNode = new MutableLiveData<>();
- /**
- * Holds the selected Element to configure
- **/
+ // Holds the selected Element to configure
private MutableLiveData mSelectedElement = new MutableLiveData<>();
- /**
- * Holds the selected mesh model to configure
- **/
+ // Holds the selected mesh model to configure
private MutableLiveData mSelectedModel = new MutableLiveData<>();
+ // Holds the selected app key to configure
+ private MutableLiveData mSelectedNetKey = new MutableLiveData<>();
+ // Holds the selected app key to configure
+ private MutableLiveData mSelectedAppKey = new MutableLiveData<>();
+ // Holds the selected provisioner when adding/editing
+ private MutableLiveData mSelectedProvisioner = new MutableLiveData<>();
private final MutableLiveData mSelectedGroupLiveData = new MutableLiveData<>();
- /**
- * Composition data status
- **/
+
+ // Composition data status
final SingleLiveEvent mCompositionDataStatus = new SingleLiveEvent<>();
- /**
- * App key add status
- **/
+ // App key add status
final SingleLiveEvent mAppKeyStatus = new SingleLiveEvent<>();
- /**
- * Contains the MeshNetwork
- **/
+ //Contains the MeshNetwork
private MeshNetworkLiveData mMeshNetworkLiveData = new MeshNetworkLiveData();
-
private SingleLiveEvent mNetworkImportState = new SingleLiveEvent<>();
private SingleLiveEvent mNetworkExportState = new SingleLiveEvent<>();
-
private SingleLiveEvent mMeshMessageLiveData = new SingleLiveEvent<>();
- /**
- * Contains the provisioned nodes
- **/
+
+ // Contains the provisioned nodes
private final MutableLiveData> mProvisionedNodes = new MutableLiveData<>();
private final MutableLiveData> mGroups = new MutableLiveData<>();
- private final TransactionStatusLiveData mTransactionFailedLiveData = new TransactionStatusLiveData();
+ private final MutableLiveData mTransactionStatus = new SingleLiveEvent<>();
private MeshManagerApi mMeshManagerApi;
private BleMeshManager mBleMeshManager;
@@ -169,7 +145,9 @@ public class NrfMeshRepository implements MeshProvisioningStatusCallbacks, MeshS
private ProvisioningStatusLiveData mProvisioningStateLiveData;
private MeshNetwork mMeshNetwork;
private boolean mIsCompositionDataReceived;
+ private boolean mIsDefaultTtlReceived;
private boolean mIsAppKeyAddCompleted;
+ private boolean mIsNetworkRetransmitSetCompleted;
private final Runnable mReconnectRunnable = this::startScan;
@@ -179,7 +157,6 @@ public class NrfMeshRepository implements MeshProvisioningStatusCallbacks, MeshS
};
public NrfMeshRepository(final MeshManagerApi meshManagerApi,
- final NetworkInformation networkInformation,
final BleMeshManager bleMeshManager) {
//Initialize the mesh api
mMeshManagerApi = meshManagerApi;
@@ -237,15 +214,23 @@ boolean isCompositionDataStatusReceived() {
return mIsCompositionDataReceived;
}
+ boolean isDefaultTtlReceived() {
+ return mIsDefaultTtlReceived;
+ }
+
boolean isAppKeyAddCompleted() {
return mIsAppKeyAddCompleted;
}
+ boolean isNetworkRetransmitSetCompleted() {
+ return mIsNetworkRetransmitSetCompleted;
+ }
+
final MeshNetworkLiveData getMeshNetworkLiveData() {
return mMeshNetworkLiveData;
}
- LiveData> getProvisionedNodes() {
+ LiveData> getNodes() {
return mProvisionedNodes;
}
@@ -261,16 +246,21 @@ LiveData getNetworkExportState() {
return mNetworkExportState;
}
- NetworkInformationLiveData getNetworkInformationLiveData() {
- return mNetworkInformationLiveData;
- }
-
ProvisioningStatusLiveData getProvisioningState() {
return mProvisioningStateLiveData;
}
- TransactionStatusLiveData getTransactionStatusLiveData() {
- return mTransactionFailedLiveData;
+ LiveData getTransactionStatus() {
+ return mTransactionStatus;
+ }
+
+ /**
+ * Clears the transaction status
+ */
+ void clearTransactionStatus() {
+ if (mTransactionStatus.getValue() != null) {
+ mTransactionStatus.postValue(null);
+ }
}
/**
@@ -294,7 +284,7 @@ BleMeshManager getBleMeshManager() {
/**
* Returns the {@link MeshMessageLiveData} live data object containing the mesh message
*/
- public LiveData getMeshMessageLiveData() {
+ LiveData getMeshMessageLiveData() {
return mMeshMessageLiveData;
}
@@ -313,14 +303,18 @@ void resetMeshNetwork() {
/**
* Connect to peripheral
*
- * @param device bluetooth device
+ * @param context Context
+ * @param device {@link ExtendedBluetoothDevice} device
+ * @param connectToNetwork True if connecting to an unprovisioned node or proxy node
*/
void connect(final Context context, final ExtendedBluetoothDevice device, final boolean connectToNetwork) {
- mMeshNetworkLiveData.getValue().setNodeName(device.getName());
+ mMeshNetworkLiveData.setNodeName(device.getName());
mIsProvisioningComplete = false;
mIsCompositionDataReceived = false;
+ mIsDefaultTtlReceived = false;
mIsAppKeyAddCompleted = false;
- clearExtendedMeshNode();
+ mIsNetworkRetransmitSetCompleted = false;
+ //clearExtendedMeshNode();
final LogSession logSession = Logger.newSession(context, null, device.getAddress(), device.getName());
mBleMeshManager.setLogger(logSession);
final BluetoothDevice bluetoothDevice = device.getDevice();
@@ -354,34 +348,36 @@ private void initIsConnectedLiveData(final boolean connectToNetwork) {
*/
void disconnect() {
clearProvisioningLiveData();
- removeCallbacks();
mIsProvisioningComplete = false;
mBleMeshManager.disconnect();
}
- void removeCallbacks() {
+ void clearProvisioningLiveData() {
+ stopScan();
+ mHandler.removeCallbacks(mReconnectRunnable);
+ mSetupProvisionedNode = false;
+ mIsReconnectingFlag = false;
+ mUnprovisionedMeshNodeLiveData.setValue(null);
+ mProvisionedMeshNodeLiveData.setValue(null);
+ }
+
+ private void removeCallbacks() {
mHandler.removeCallbacksAndMessages(null);
}
public void identifyNode(final ExtendedBluetoothDevice device) {
final UnprovisionedBeacon beacon = (UnprovisionedBeacon) device.getBeacon();
if (beacon != null) {
- mMeshManagerApi.identifyNode(beacon.getUuid(), device.getName(), ATTENTION_TIMER);
+ mMeshManagerApi.identifyNode(beacon.getUuid(), ATTENTION_TIMER);
} else {
final byte[] serviceData = Utils.getServiceData(device.getScanResult(), BleMeshManager.MESH_PROVISIONING_UUID);
if (serviceData != null) {
final UUID uuid = mMeshManagerApi.getDeviceUuid(serviceData);
- mMeshManagerApi.identifyNode(uuid, device.getName(), ATTENTION_TIMER);
+ mMeshManagerApi.identifyNode(uuid, ATTENTION_TIMER);
}
}
}
- void clearProvisioningLiveData() {
- mIsReconnectingFlag = false;
- mUnprovisionedMeshNodeLiveData.setValue(null);
- mProvisionedMeshNodeLiveData.setValue(null);
- }
-
private void clearExtendedMeshNode() {
if (mExtendedMeshNode != null) {
mExtendedMeshNode.postValue(null);
@@ -392,12 +388,8 @@ LiveData getUnprovisionedMeshNode() {
return mUnprovisionedMeshNodeLiveData;
}
- LiveData getProvisionedMeshNode() {
- return mProvisionedMeshNodeLiveData;
- }
-
- LiveData getConnectedMeshNodeAddress() {
- return mConnectedMeshNodeAddress;
+ LiveData getConnectedProxyAddress() {
+ return mConnectedProxyAddress;
}
/**
@@ -414,11 +406,6 @@ LiveData getSelectedMeshNode() {
*/
void setSelectedMeshNode(final ProvisionedMeshNode node) {
mExtendedMeshNode.postValue(node);
- /*if (mExtendedMeshNode == null) {
- mExtendedMeshNode = new ExtendedMeshNode(node);
- } else {
- mExtendedMeshNode.updateMeshNode(node);
- }*/
}
/**
@@ -437,6 +424,38 @@ void setSelectedElement(final Element element) {
mSelectedElement.postValue(element);
}
+ /**
+ * Set the selected model to be configured
+ *
+ * @param appKey mesh model
+ */
+ void setSelectedAppKey(@NonNull final ApplicationKey appKey) {
+ mSelectedAppKey.postValue(appKey);
+ }
+
+ /**
+ * Returns the selected mesh model
+ */
+ LiveData getSelectedAppKey() {
+ return mSelectedAppKey;
+ }
+
+ /**
+ * Selects provisioner for editing or adding
+ *
+ * @param provisioner {@link Provisioner}
+ */
+ void setSelectedProvisioner(@NonNull final Provisioner provisioner) {
+ mSelectedProvisioner.postValue(provisioner);
+ }
+
+ /**
+ * Returns the selected {@link Provisioner}
+ */
+ LiveData getSelectedProvisioner() {
+ return mSelectedProvisioner;
+ }
+
/**
* Returns the selected mesh model
*/
@@ -478,35 +497,35 @@ public void onDeviceConnected(final BluetoothDevice device) {
@Override
public void onDeviceDisconnecting(final BluetoothDevice device) {
Log.v(TAG, "Disconnecting...");
- if(mIsReconnectingFlag){
+ if (mIsReconnectingFlag) {
mConnectionState.postValue("Reconnecting...");
} else {
mConnectionState.postValue("Disconnecting...");
}
}
+ @SuppressWarnings("ConstantConditions")
@Override
public void onDeviceDisconnected(final BluetoothDevice device) {
Log.v(TAG, "Disconnected");
+ mConnectionState.postValue("");
if (mIsReconnectingFlag) {
mIsReconnectingFlag = false;
mIsReconnecting.postValue(false);
mIsConnected.postValue(false);
+ mIsConnectedToProxy.postValue(false);
} else {
- mConnectionState.postValue("");
mIsConnected.postValue(false);
mIsConnectedToProxy.postValue(false);
- if (mConnectedMeshNodeAddress.getValue() != null) {
- final ProvisionedMeshNode node = mMeshManagerApi.getMeshNetwork().
- getProvisionedNode(AddressUtils.getUnicastAddressBytes(mConnectedMeshNodeAddress.getValue()));
- if (node != null)
- node.setProxyFilter(null);
+ if (mConnectedProxyAddress.getValue() != null) {
+ final MeshNetwork network = mMeshManagerApi.getMeshNetwork();
+ network.setProxyFilter(null);
}
- clearExtendedMeshNode();
+ //clearExtendedMeshNode();
}
mSetupProvisionedNode = false;
- mConnectedMeshNodeAddress.postValue(null);
+ mConnectedProxyAddress.postValue(null);
}
@Override
@@ -526,10 +545,20 @@ public void onDeviceReady(final BluetoothDevice device) {
if (mBleMeshManager.isProvisioningComplete()) {
if (mSetupProvisionedNode) {
- //Adding a slight delay here so we don't send anything before we receive the mesh beacon message
- final ProvisionedMeshNode node = mProvisionedMeshNodeLiveData.getValue();
- final ConfigCompositionDataGet compositionDataGet = new ConfigCompositionDataGet();
- mHandler.postDelayed(() -> mMeshManagerApi.sendMeshMessage(node.getUnicastAddress(), compositionDataGet), 2000);
+ if (mMeshNetwork.getSelectedProvisioner().getProvisionerAddress() != null) {
+ mHandler.postDelayed(() -> {
+ //Adding a slight delay here so we don't send anything before we receive the mesh beacon message
+ final ProvisionedMeshNode node = mProvisionedMeshNodeLiveData.getValue();
+ if (node != null) {
+ final ConfigCompositionDataGet compositionDataGet = new ConfigCompositionDataGet();
+ mMeshManagerApi.createMeshPdu(node.getUnicastAddress(), compositionDataGet);
+ }
+ }, 2000);
+ } else {
+ mSetupProvisionedNode = false;
+ mProvisioningStateLiveData.onMeshNodeStateUpdated(ProvisionerStates.PROVISIONER_UNASSIGNED);
+ clearExtendedMeshNode();
+ }
}
mIsConnectedToProxy.postValue(true);
}
@@ -628,7 +657,7 @@ public void sendProvisioningPdu(final UnprovisionedMeshNode meshNode, final byte
}
@Override
- public void sendMeshPdu(final byte[] pdu) {
+ public void onMeshPduCreated(final byte[] pdu) {
mBleMeshManager.sendPdu(pdu);
}
@@ -649,7 +678,7 @@ public void onProvisioningStateChanged(final UnprovisionedMeshNode meshNode, fin
mIsProvisioningComplete = false;
break;
}
- mProvisioningStateLiveData.onMeshNodeStateUpdated(state);
+ mProvisioningStateLiveData.onMeshNodeStateUpdated(ProvisionerStates.fromStatusCode(state.getState()));
}
@@ -657,12 +686,10 @@ public void onProvisioningStateChanged(final UnprovisionedMeshNode meshNode, fin
public void onProvisioningFailed(final UnprovisionedMeshNode meshNode, final ProvisioningState.States state, final byte[] data) {
mUnprovisionedMeshNode = meshNode;
mUnprovisionedMeshNodeLiveData.postValue(meshNode);
- switch (state) {
- case PROVISIONING_FAILED:
- mIsProvisioningComplete = false;
- break;
+ if (state == ProvisioningState.States.PROVISIONING_FAILED) {
+ mIsProvisioningComplete = false;
}
- mProvisioningStateLiveData.onMeshNodeStateUpdated(state);
+ mProvisioningStateLiveData.onMeshNodeStateUpdated(ProvisionerStates.fromStatusCode(state.getState()));
}
@@ -671,12 +698,10 @@ public void onProvisioningCompleted(final ProvisionedMeshNode meshNode, final Pr
mProvisionedMeshNode = meshNode;
mUnprovisionedMeshNodeLiveData.postValue(null);
mProvisionedMeshNodeLiveData.postValue(meshNode);
- switch (state) {
- case PROVISIONING_COMPLETE:
- onProvisioningCompleted(meshNode);
- break;
+ if (state == ProvisioningState.States.PROVISIONING_COMPLETE) {
+ onProvisioningCompleted(meshNode);
}
- mProvisioningStateLiveData.onMeshNodeStateUpdated(state);
+ mProvisioningStateLiveData.onMeshNodeStateUpdated(ProvisionerStates.fromStatusCode(state.getState()));
}
@@ -686,39 +711,33 @@ private void onProvisioningCompleted(final ProvisionedMeshNode node) {
mIsReconnecting.postValue(true);
mBleMeshManager.disconnect();
mBleMeshManager.refreshDeviceCache();
- mProvisionedNodes.postValue(mMeshNetwork.getProvisionedNodes());
+ loadNodes();
mHandler.post(() -> mConnectionState.postValue("Scanning for provisioned node"));
mHandler.postDelayed(mReconnectRunnable, 1000); //Added a slight delay to disconnect and refresh the cache
}
- @Override
- public void onTransactionFailed(final byte[] dst, final boolean hasIncompleteTimerExpired) {
- mProvisionedMeshNode = mMeshNetwork.getProvisionedNode(dst);
- if (mTransactionFailedLiveData.hasActiveObservers()) {
- mTransactionFailedLiveData.onTransactionFailed(dst, hasIncompleteTimerExpired);
+ /**
+ * Here we load all nodes except the current provisioner. This may contain other provisioner nodes if available
+ */
+ private void loadNodes() {
+ final List nodes = new ArrayList<>();
+ for (final ProvisionedMeshNode node : mMeshNetwork.getNodes()) {
+ if (!node.getUuid().equalsIgnoreCase(mMeshNetwork.getSelectedProvisioner().getProvisionerUuid())) {
+ nodes.add(node);
+ }
}
+ mProvisionedNodes.postValue(nodes);
}
@Override
public void onTransactionFailed(final int dst, final boolean hasIncompleteTimerExpired) {
- mProvisionedMeshNode = mMeshNetwork.getProvisionedNode(dst);
- if (mTransactionFailedLiveData.hasActiveObservers()) {
- mTransactionFailedLiveData.onTransactionFailed(dst, hasIncompleteTimerExpired);
- }
- }
-
- @Override
- public void onUnknownPduReceived(final byte[] src, final byte[] accessPayload) {
- final ProvisionedMeshNode node = mMeshNetwork.getProvisionedNode(src);
- if (node != null) {
- mProvisionedMeshNode = node;
- updateNode(node);
- }
+ mProvisionedMeshNode = mMeshNetwork.getNode(dst);
+ mTransactionStatus.postValue(new TransactionStatus(dst, hasIncompleteTimerExpired));
}
@Override
public void onUnknownPduReceived(final int src, final byte[] accessPayload) {
- final ProvisionedMeshNode node = mMeshNetwork.getProvisionedNode(src);
+ final ProvisionedMeshNode node = mMeshNetwork.getNode(src);
if (node != null) {
mProvisionedMeshNode = node;
updateNode(node);
@@ -726,85 +745,62 @@ public void onUnknownPduReceived(final int src, final byte[] accessPayload) {
}
@Override
- public void onBlockAcknowledgementSent(final byte[] dst) {
- if (dst != null) {
- final ProvisionedMeshNode node = mMeshNetwork.getProvisionedNode(dst);
- if (node != null) {
- mProvisionedMeshNode = node;
- if (mSetupProvisionedNode) {
- mProvisionedMeshNodeLiveData.postValue(mProvisionedMeshNode);
- mProvisioningStateLiveData.onMeshNodeStateUpdated(ProvisioningState.States.SENDING_BLOCK_ACKNOWLEDGEMENT);
- }
- }
- }
- }
-
- @Override
- public void onBlockAcknowledgementSent(final int dst) {
- final ProvisionedMeshNode node = mMeshNetwork.getProvisionedNode(dst);
+ public void onBlockAcknowledgementProcessed(final int dst, @NonNull final ControlMessage message) {
+ final ProvisionedMeshNode node = mMeshNetwork.getNode(dst);
if (node != null) {
mProvisionedMeshNode = node;
if (mSetupProvisionedNode) {
mProvisionedMeshNodeLiveData.postValue(mProvisionedMeshNode);
- mProvisioningStateLiveData.onMeshNodeStateUpdated(ProvisioningState.States.SENDING_BLOCK_ACKNOWLEDGEMENT);
- }
- }
- }
-
- @Override
- public void onBlockAcknowledgementReceived(final byte[] src) {
- final ProvisionedMeshNode node = mMeshNetwork.getProvisionedNode(src);
- if (node != null) {
- mProvisionedMeshNode = node;
- if (mSetupProvisionedNode) {
- mProvisionedMeshNodeLiveData.postValue(node);
- mProvisioningStateLiveData.onMeshNodeStateUpdated(ProvisioningState.States.BLOCK_ACKNOWLEDGEMENT_RECEIVED);
+ mProvisioningStateLiveData.onMeshNodeStateUpdated(ProvisionerStates.SENDING_BLOCK_ACKNOWLEDGEMENT);
}
}
}
@Override
- public void onBlockAcknowledgementReceived(final int src) {
- final ProvisionedMeshNode node = mMeshNetwork.getProvisionedNode(src);
+ public void onBlockAcknowledgementReceived(final int src, @NonNull final ControlMessage message) {
+ final ProvisionedMeshNode node = mMeshNetwork.getNode(src);
if (node != null) {
mProvisionedMeshNode = node;
if (mSetupProvisionedNode) {
mProvisionedMeshNodeLiveData.postValue(node);
- mProvisioningStateLiveData.onMeshNodeStateUpdated(ProvisioningState.States.BLOCK_ACKNOWLEDGEMENT_RECEIVED);
+ mProvisioningStateLiveData.onMeshNodeStateUpdated(ProvisionerStates.BLOCK_ACKNOWLEDGEMENT_RECEIVED);
}
}
}
@Override
- public void onMeshMessageSent(final byte[] dst, final MeshMessage meshMessage) {
- }
-
- @Override
- public void onMeshMessageSent(final int dst, final MeshMessage meshMessage) {
- final ProvisionedMeshNode node = mMeshNetwork.getProvisionedNode(dst);
+ public void onMeshMessageProcessed(final int dst, @NonNull final MeshMessage meshMessage) {
+ final ProvisionedMeshNode node = mMeshNetwork.getNode(dst);
if (node != null) {
mProvisionedMeshNode = node;
if (meshMessage instanceof ConfigCompositionDataGet) {
if (mSetupProvisionedNode) {
mProvisionedMeshNodeLiveData.postValue(node);
- mProvisioningStateLiveData.onMeshNodeStateUpdated(ProvisioningState.States.COMPOSITION_DATA_GET_SENT);
+ mProvisioningStateLiveData.onMeshNodeStateUpdated(ProvisionerStates.COMPOSITION_DATA_GET_SENT);
}
- } else if (meshMessage instanceof ConfigAppKeyStatus) {
+ } else if (meshMessage instanceof ConfigDefaultTtlGet) {
+ if (mSetupProvisionedNode) {
+ mProvisionedMeshNodeLiveData.postValue(node);
+ mProvisioningStateLiveData.onMeshNodeStateUpdated(ProvisionerStates.SENDING_DEFAULT_TTL_GET);
+ }
+ } else if (meshMessage instanceof ConfigAppKeyAdd) {
+ if (mSetupProvisionedNode) {
+ mProvisionedMeshNodeLiveData.postValue(node);
+ mProvisioningStateLiveData.onMeshNodeStateUpdated(ProvisionerStates.SENDING_APP_KEY_ADD);
+ }
+ } else if (meshMessage instanceof ConfigNetworkTransmitSet) {
if (mSetupProvisionedNode) {
mProvisionedMeshNodeLiveData.postValue(node);
- mProvisioningStateLiveData.onMeshNodeStateUpdated(ProvisioningState.States.SENDING_APP_KEY_ADD);
+ mProvisioningStateLiveData.onMeshNodeStateUpdated(ProvisionerStates.SENDING_NETWORK_TRANSMIT_SET);
}
}
}
}
+ @SuppressWarnings("ConstantConditions")
@Override
- public void onMeshMessageReceived(final byte[] src, final MeshMessage meshMessage) {
- }
-
- @Override
- public void onMeshMessageReceived(final int src, final MeshMessage meshMessage) {
- final ProvisionedMeshNode node = mMeshNetwork.getProvisionedNode(src);
+ public void onMeshMessageReceived(final int src, @NonNull final MeshMessage meshMessage) {
+ final ProvisionedMeshNode node = mMeshNetwork.getNode(src);
if (node != null)
if (meshMessage instanceof ProxyConfigFilterStatus) {
mProvisionedMeshNode = node;
@@ -812,38 +808,66 @@ public void onMeshMessageReceived(final int src, final MeshMessage meshMessage)
final ProxyConfigFilterStatus status = (ProxyConfigFilterStatus) meshMessage;
final int unicastAddress = status.getSrc();
Log.v(TAG, "Proxy configuration source: " + MeshAddress.formatAddress(status.getSrc(), false));
- mConnectedMeshNodeAddress.postValue(unicastAddress);
+ mConnectedProxyAddress.postValue(unicastAddress);
mMeshMessageLiveData.postValue(status);
} else if (meshMessage instanceof ConfigCompositionDataStatus) {
final ConfigCompositionDataStatus status = (ConfigCompositionDataStatus) meshMessage;
if (mSetupProvisionedNode) {
mIsCompositionDataReceived = true;
mProvisionedMeshNodeLiveData.postValue(node);
- mConnectedMeshNodeAddress.postValue(node.getUnicastAddress());
- mProvisioningStateLiveData.onMeshNodeStateUpdated(ProvisioningState.States.COMPOSITION_DATA_STATUS_RECEIVED);
- //We send app key add after composition is complete. Adding a delay so that we don't send anything before the acknowledgement is sent out.
- if (!mMeshNetwork.getAppKeys().isEmpty()) {
+ mConnectedProxyAddress.postValue(node.getUnicastAddress());
+ mProvisioningStateLiveData.onMeshNodeStateUpdated(ProvisionerStates.COMPOSITION_DATA_STATUS_RECEIVED);
+ mHandler.postDelayed(() -> {
+ final ConfigDefaultTtlGet configDefaultTtlGet = new ConfigDefaultTtlGet();
+ mMeshManagerApi.createMeshPdu(node.getUnicastAddress(), configDefaultTtlGet);
+ }, 2500);
+ } else {
+ updateNode(node);
+ }
+ } else if (meshMessage instanceof ConfigDefaultTtlStatus) {
+ final ConfigDefaultTtlStatus status = (ConfigDefaultTtlStatus) meshMessage;
+ if (mSetupProvisionedNode) {
+ mIsDefaultTtlReceived = true;
+ mProvisionedMeshNodeLiveData.postValue(node);
+ mProvisioningStateLiveData.onMeshNodeStateUpdated(ProvisionerStates.DEFAULT_TTL_STATUS_RECEIVED);
+ mHandler.postDelayed(() -> {
+ final ApplicationKey appKey = mMeshNetworkLiveData.getSelectedAppKey();
+ final int index = node.getAddedNetKeys().get(0).getIndex();
+ final NetworkKey networkKey = mMeshNetwork.getNetKeys().get(index);
+ final ConfigAppKeyAdd configAppKeyAdd = new ConfigAppKeyAdd(networkKey, appKey);
+ mMeshManagerApi.createMeshPdu(node.getUnicastAddress(), configAppKeyAdd);
+ }, 2500);
+ } else {
+ updateNode(node);
+ mMeshMessageLiveData.postValue(status);
+ }
+ } else if (meshMessage instanceof ConfigAppKeyStatus) {
+ final ConfigAppKeyStatus status = (ConfigAppKeyStatus) meshMessage;
+ if (mSetupProvisionedNode) {
+ if (status.isSuccessful()) {
+ mIsAppKeyAddCompleted = true;
+ mProvisionedMeshNodeLiveData.postValue(node);
+ mProvisioningStateLiveData.onMeshNodeStateUpdated(ProvisionerStates.APP_KEY_STATUS_RECEIVED);
mHandler.postDelayed(() -> {
- final ApplicationKey appKey = mMeshNetworkLiveData.getSelectedAppKey();
- final ConfigAppKeyAdd configAppKeyAdd = new ConfigAppKeyAdd(node.getAddedNetworkKeys().get(0), appKey);
- mMeshManagerApi.sendMeshMessage(node.getUnicastAddress(), configAppKeyAdd);
+ final ConfigNetworkTransmitSet networkTransmitSet = new ConfigNetworkTransmitSet(2, 1);
+ mMeshManagerApi.createMeshPdu(node.getUnicastAddress(), networkTransmitSet);
}, 2500);
}
} else {
updateNode(node);
+ mMeshMessageLiveData.postValue(status);
}
- } else if (meshMessage instanceof ConfigAppKeyStatus) {
- final ConfigAppKeyStatus status = (ConfigAppKeyStatus) meshMessage;
+ } else if (meshMessage instanceof ConfigNetworkTransmitStatus) {
if (mSetupProvisionedNode) {
- mIsAppKeyAddCompleted = true;
mSetupProvisionedNode = false;
- mProvisioningStateLiveData.onMeshNodeStateUpdated(ProvisioningState.States.APP_KEY_STATUS_RECEIVED);
+ mIsNetworkRetransmitSetCompleted = true;
+ mProvisioningStateLiveData.onMeshNodeStateUpdated(ProvisionerStates.NETWORK_TRANSMIT_STATUS_RECEIVED);
} else {
updateNode(node);
+ final ConfigNetworkTransmitStatus status = (ConfigNetworkTransmitStatus) meshMessage;
mMeshMessageLiveData.postValue(status);
}
} else if (meshMessage instanceof ConfigModelAppStatus) {
-
if (updateNode(node)) {
final ConfigModelAppStatus status = (ConfigModelAppStatus) meshMessage;
final Element element = node.getElements().get(status.getElementAddress());
@@ -882,15 +906,9 @@ public void onMeshMessageReceived(final int src, final MeshMessage meshMessage)
final ConfigNodeResetStatus status = (ConfigNodeResetStatus) meshMessage;
mExtendedMeshNode.postValue(null);
- mProvisionedNodes.postValue(mMeshNetwork.getProvisionedNodes());
+ loadNodes();
mMeshMessageLiveData.postValue(status);
- } else if (meshMessage instanceof ConfigNetworkTransmitStatus) {
- if (updateNode(node)) {
- final ConfigNetworkTransmitStatus status = (ConfigNetworkTransmitStatus) meshMessage;
- mMeshMessageLiveData.postValue(status);
- }
-
} else if (meshMessage instanceof ConfigRelayStatus) {
if (updateNode(node)) {
final ConfigRelayStatus status = (ConfigRelayStatus) meshMessage;
@@ -965,11 +983,15 @@ private void loadNetwork(final MeshNetwork meshNetwork) {
provisioner.setLastSelected(true);
mMeshNetwork.selectProvisioner(provisioner);
}
-
//Load live data with mesh network
mMeshNetworkLiveData.loadNetworkInformation(meshNetwork);
//Load live data with provisioned nodes
- mProvisionedNodes.postValue(mMeshNetwork.getProvisionedNodes());
+ loadNodes();
+
+ final ProvisionedMeshNode node = getSelectedMeshNode().getValue();
+ if (node != null) {
+ mExtendedMeshNode.postValue(mMeshNetwork.getNode(node.getUuid()));
+ }
}
}
@@ -1046,7 +1068,7 @@ public void onScanResult(final int callbackType, final ScanResult result) {
}
@Override
- public void onBatchScanResults(final List results) {
+ public void onBatchScanResults(@NonNull final List results) {
// Batch scan is disabled (report delay = 0)
}
@@ -1064,42 +1086,17 @@ private void onProvisionedDeviceFound(final ProvisionedMeshNode node, final Exte
mHandler.postDelayed(() -> connectToProxy(device), 2000);
}
- void importMeshNetwork(final Uri uri) {
- //We disconnect from the current mesh network before importing one
- mBleMeshManager.disconnect();
- mMeshManagerApi.importMeshNetwork(uri);
- }
-
/**
* Generates the groups based on the addresses each models have subscribed to
*/
private void loadGroups() {
- final String uuid = mMeshNetwork.getMeshUUID();
- final List groups = new ArrayList<>();
- for (final ProvisionedMeshNode node : mMeshNetwork.getProvisionedNodes()) {
- for (Map.Entry elementEntry : node.getElements().entrySet()) {
- final Element element = elementEntry.getValue();
- for (Map.Entry modelEntry : element.getMeshModels().entrySet()) {
- final MeshModel model = modelEntry.getValue();
- if (model != null) {
- final List subscriptionAddresses = model.getSubscribedAddresses();
- for (Integer address : subscriptionAddresses) {
- if (!mMeshNetwork.isGroupExist(address)) {
- final Group group = new Group(address, uuid);
- mMeshNetwork.addGroup(group);
- }
- }
- }
- }
- }
- }
mGroups.postValue(mMeshNetwork.getGroups());
}
private void updateSelectedGroup() {
final Group selectedGroup = mSelectedGroupLiveData.getValue();
if (selectedGroup != null) {
- mSelectedGroupLiveData.postValue(mMeshNetwork.getGroup(selectedGroup.getGroupAddress()));
+ mSelectedGroupLiveData.postValue(mMeshNetwork.getGroup(selectedGroup.getAddress()));
}
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/ProvisionerProgress.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/ProvisionerProgress.java
index c85a96003..1915a8ff0 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/ProvisionerProgress.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/ProvisionerProgress.java
@@ -22,30 +22,33 @@
package no.nordicsemi.android.nrfmeshprovisioner.viewmodels;
+import no.nordicsemi.android.nrfmeshprovisioner.utils.ProvisionerStates;
+
public class ProvisionerProgress {
- private final ProvisioningStatusLiveData.ProvisioningLiveDataState state;
+ private final ProvisionerStates state;
private int statusReceived;
private final String message;
private final int resId;
- ProvisionerProgress(final ProvisioningStatusLiveData.ProvisioningLiveDataState state, final String message, final int resId){
+ ProvisionerProgress(final ProvisionerStates state, final String message, final int resId) {
this.state = state;
this.message = message;
this.resId = resId;
}
- ProvisionerProgress(final ProvisioningStatusLiveData.ProvisioningLiveDataState state, final int status, final String message, final int resId){
+
+ ProvisionerProgress(final ProvisionerStates state, final int status, final String message, final int resId) {
this.state = state;
this.statusReceived = status;
this.message = message;
this.resId = resId;
}
- public ProvisioningStatusLiveData.ProvisioningLiveDataState getState(){
+ public ProvisionerStates getState() {
return state;
}
- public int getStatusReceived(){
+ public int getStatusReceived() {
return statusReceived;
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/ProvisionersViewModel.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/ProvisionersViewModel.java
new file mode 100644
index 000000000..e2cf8899e
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/ProvisionersViewModel.java
@@ -0,0 +1,22 @@
+package no.nordicsemi.android.nrfmeshprovisioner.viewmodels;
+
+import javax.inject.Inject;
+
+import androidx.annotation.NonNull;
+import no.nordicsemi.android.meshprovisioner.Provisioner;
+import no.nordicsemi.android.nrfmeshprovisioner.keys.AppKeysActivity;
+
+/**
+ * ViewModel for {@link AppKeysActivity}
+ */
+public class ProvisionersViewModel extends BaseViewModel {
+
+ @Inject
+ ProvisionersViewModel(@NonNull final NrfMeshRepository nrfMeshRepository) {
+ super(nrfMeshRepository);
+ }
+
+ public void setSelectedProvisioner(@NonNull final Provisioner provisioner) {
+ mNrfMeshRepository.setSelectedProvisioner(provisioner);
+ }
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/ProvisioningStatusLiveData.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/ProvisioningStatusLiveData.java
index 900755e73..b9f0d3d3f 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/ProvisioningStatusLiveData.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/ProvisioningStatusLiveData.java
@@ -22,12 +22,11 @@
package no.nordicsemi.android.nrfmeshprovisioner.viewmodels;
-import android.arch.lifecycle.LiveData;
-
import java.util.ArrayList;
-import no.nordicsemi.android.meshprovisioner.provisionerstates.ProvisioningState;
+import androidx.lifecycle.LiveData;
import no.nordicsemi.android.nrfmeshprovisioner.R;
+import no.nordicsemi.android.nrfmeshprovisioner.utils.ProvisionerStates;
public class ProvisioningStatusLiveData extends LiveData {
@@ -38,51 +37,6 @@ public void clear() {
postValue(this);
}
- public enum ProvisioningLiveDataState {
- PROVISIONING_INVITE(0),
- PROVISIONING_CAPABILITIES(1),
- PROVISIONING_START(2),
- PROVISIONING_PUBLIC_KEY_SENT(3),
- PROVISIONING_PUBLIC_KEY_RECEIVED(4),
- PROVISIONING_AUTHENTICATION_INPUT_OOB_WAITING(5),
- PROVISIONING_AUTHENTICATION_OUTPUT_OOB_WAITING(6),
- PROVISIONING_AUTHENTICATION_STATIC_OOB_WAITING(7),
- PROVISIONING_AUTHENTICATION_INPUT_ENTERED(8),
- PROVISIONING_INPUT_COMPLETE(9),
- PROVISIONING_CONFIRMATION_SENT(10),
- PROVISIONING_CONFIRMATION_RECEIVED(11),
- PROVISIONING_RANDOM_SENT(12),
- PROVISIONING_RANDOM_RECEIVED(13),
- PROVISIONING_DATA_SENT(14),
- PROVISIONING_COMPLETE(15),
- PROVISIONING_FAILED(16),
- COMPOSITION_DATA_GET_SENT(17),
- COMPOSITION_DATA_STATUS_RECEIVED(18),
- SENDING_BLOCK_ACKNOWLEDGEMENT(19),
- SENDING_APP_KEY_ADD(20),
- BLOCK_ACKNOWLEDGEMENT_RECEIVED(21),
- APP_KEY_STATUS_RECEIVED(22);
-
- private final int state;
-
- ProvisioningLiveDataState(final int state) {
- this.state = state;
- }
-
- int getState() {
- return state;
- }
-
- static ProvisioningLiveDataState fromStatusCode(final int statusCode) {
- for (ProvisioningLiveDataState state : ProvisioningLiveDataState.values()) {
- if (state.getState() == statusCode) {
- return state;
- }
- }
- throw new IllegalStateException("Invalid state");
- }
- }
-
public ArrayList getStateList() {
return mProvisioningProgress;
}
@@ -94,10 +48,9 @@ public ProvisionerProgress getProvisionerProgress() {
return mProvisioningProgress.get(mProvisioningProgress.size() - 1);
}
- void onMeshNodeStateUpdated(final ProvisioningState.States provisionerState) {
+ void onMeshNodeStateUpdated(final ProvisionerStates state) {
final ProvisionerProgress provisioningProgress;
- final ProvisioningLiveDataState state = ProvisioningLiveDataState.fromStatusCode(provisionerState.getState());
- switch (provisionerState) {
+ switch (state) {
case PROVISIONING_INVITE:
provisioningProgress = new ProvisionerProgress(state, "Sending provisioning invite...", R.drawable.ic_arrow_forward_black_alpha);
mProvisioningProgress.add(provisioningProgress);
@@ -169,12 +122,12 @@ void onMeshNodeStateUpdated(final ProvisioningState.States provisionerState) {
provisioningProgress = new ProvisionerProgress(state, "Composition data status received...", R.drawable.ic_arrow_back_black_alpha);
mProvisioningProgress.add(provisioningProgress);
break;
- case SENDING_BLOCK_ACKNOWLEDGEMENT:
- provisioningProgress = new ProvisionerProgress(state, "Sending block acknowledgements", R.drawable.ic_arrow_forward_black_alpha);
+ case SENDING_DEFAULT_TTL_GET:
+ provisioningProgress = new ProvisionerProgress(state, "Sending default TLL get...", R.drawable.ic_arrow_forward_black_alpha);
mProvisioningProgress.add(provisioningProgress);
break;
- case BLOCK_ACKNOWLEDGEMENT_RECEIVED:
- provisioningProgress = new ProvisionerProgress(state, "Receiving block acknowledgements", R.drawable.ic_arrow_back_black_alpha);
+ case DEFAULT_TTL_STATUS_RECEIVED:
+ provisioningProgress = new ProvisionerProgress(state, "Default TTL status received...", R.drawable.ic_arrow_forward_black_alpha);
mProvisioningProgress.add(provisioningProgress);
break;
case SENDING_APP_KEY_ADD:
@@ -185,6 +138,26 @@ void onMeshNodeStateUpdated(final ProvisioningState.States provisionerState) {
provisioningProgress = new ProvisionerProgress(state, "App key status received...", R.drawable.ic_arrow_forward_black_alpha);
mProvisioningProgress.add(provisioningProgress);
break;
+ case SENDING_NETWORK_TRANSMIT_SET:
+ provisioningProgress = new ProvisionerProgress(state, "Sending network transmit set...", R.drawable.ic_arrow_forward_black_alpha);
+ mProvisioningProgress.add(provisioningProgress);
+ break;
+ case NETWORK_TRANSMIT_STATUS_RECEIVED:
+ provisioningProgress = new ProvisionerProgress(state, "Network transmit status received...", R.drawable.ic_arrow_forward_black_alpha);
+ mProvisioningProgress.add(provisioningProgress);
+ break;
+ case SENDING_BLOCK_ACKNOWLEDGEMENT:
+ provisioningProgress = new ProvisionerProgress(state, "Sending block acknowledgements", R.drawable.ic_arrow_forward_black_alpha);
+ mProvisioningProgress.add(provisioningProgress);
+ break;
+ case BLOCK_ACKNOWLEDGEMENT_RECEIVED:
+ provisioningProgress = new ProvisionerProgress(state, "Receiving block acknowledgements", R.drawable.ic_arrow_back_black_alpha);
+ mProvisioningProgress.add(provisioningProgress);
+ break;
+ case PROVISIONER_UNASSIGNED:
+ provisioningProgress = new ProvisionerProgress(state, "Provisioner unassigned...", R.drawable.ic_arrow_forward_black_alpha);
+ mProvisioningProgress.add(provisioningProgress);
+ break;
}
postValue(this);
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/MeshProvisionerViewModel.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/ProvisioningViewModel.java
similarity index 54%
rename from Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/MeshProvisionerViewModel.java
rename to Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/ProvisioningViewModel.java
index 2c73dc433..3c72c4d87 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/MeshProvisionerViewModel.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/ProvisioningViewModel.java
@@ -22,25 +22,21 @@
package no.nordicsemi.android.nrfmeshprovisioner.viewmodels;
-import android.arch.lifecycle.LiveData;
-import android.arch.lifecycle.ViewModel;
-import android.content.Context;
-
import javax.inject.Inject;
-import no.nordicsemi.android.meshprovisioner.MeshManagerApi;
+import androidx.annotation.NonNull;
+import androidx.lifecycle.LiveData;
import no.nordicsemi.android.meshprovisioner.provisionerstates.UnprovisionedMeshNode;
-import no.nordicsemi.android.meshprovisioner.transport.ProvisionedMeshNode;
-import no.nordicsemi.android.nrfmeshprovisioner.adapter.ExtendedBluetoothDevice;
-import no.nordicsemi.android.nrfmeshprovisioner.ble.BleMeshManager;
-
-public class MeshProvisionerViewModel extends ViewModel {
+import no.nordicsemi.android.nrfmeshprovisioner.ProvisioningActivity;
- private final NrfMeshRepository mNrfMeshRepository;
+/**
+ * ViewModel for {@link ProvisioningActivity}
+ */
+public class ProvisioningViewModel extends BaseViewModel {
@Inject
- MeshProvisionerViewModel(final NrfMeshRepository nrfMeshRepository) {
- this.mNrfMeshRepository = nrfMeshRepository;
+ ProvisioningViewModel(@NonNull final NrfMeshRepository nrfMeshRepository) {
+ super(nrfMeshRepository);
}
@Override
@@ -49,82 +45,60 @@ protected void onCleared() {
mNrfMeshRepository.clearProvisioningLiveData();
}
- public LiveData isDeviceReady() {
- return mNrfMeshRepository.isDeviceReady();
- }
-
- public LiveData getConnectionState() {
- return mNrfMeshRepository.getConnectionState();
- }
-
- public LiveData isConnected() {
- return mNrfMeshRepository.isConnected();
+ /**
+ * Returns the LifeData {@link UnprovisionedMeshNode}
+ */
+ public LiveData getUnprovisionedMeshNode() {
+ return mNrfMeshRepository.getUnprovisionedMeshNode();
}
+ /**
+ * Returns true if reconnecting after provisioning is completed
+ */
public LiveData isReconnecting() {
return mNrfMeshRepository.isReconnecting();
}
- public boolean isProvisioningComplete() {
- return mNrfMeshRepository.isProvisioningComplete();
- }
-
- public boolean isCompositionDataStatusReceived() {
- return mNrfMeshRepository.isCompositionDataStatusReceived();
- }
-
- public boolean isAppKeyAddCompleted() {
- return mNrfMeshRepository.isAppKeyAddCompleted();
- }
-
+ /**
+ * Returns the provisioning status
+ */
public ProvisioningStatusLiveData getProvisioningStatus() {
return mNrfMeshRepository.getProvisioningState();
}
/**
- * Connect to peripheral
+ * Returns true if provisioning has completed
*/
- public void connect(final Context context, final ExtendedBluetoothDevice device, final boolean connectToNetwork) {
- mNrfMeshRepository.connect(context, device, connectToNetwork);
+ public boolean isProvisioningComplete() {
+ return mNrfMeshRepository.isProvisioningComplete();
}
/**
- * Disconnect from peripheral
+ * Returns true if the CompositionDataStatus is received
*/
- public void disconnect() {
- mNrfMeshRepository.disconnect();
- }
-
- public void clearProvisioningCallbacks(){
- disconnect();
- mNrfMeshRepository.removeCallbacks();
- }
-
- public LiveData getUnProvisionedMeshNode() {
- return mNrfMeshRepository.getUnprovisionedMeshNode();
- }
-
- public LiveData getProvisionedMeshNode() {
- return mNrfMeshRepository.getProvisionedMeshNode();
- }
-
- public void startProvisioning(final UnprovisionedMeshNode node) {
- mNrfMeshRepository.getMeshManagerApi().startProvisioningWithStaticOOB(node);
+ public boolean isCompositionDataStatusReceived() {
+ return mNrfMeshRepository.isCompositionDataStatusReceived();
}
- public MeshNetworkLiveData getMeshNetworkLiveData(){
- return mNrfMeshRepository.getMeshNetworkLiveData();
+ /**
+ * Returns true if the DefaultTTLGet completed
+ */
+ public boolean isDefaultTtlReceived() {
+ return mNrfMeshRepository.isDefaultTtlReceived();
}
- public NrfMeshRepository getNrfMeshRepository() {
- return mNrfMeshRepository;
+ /**
+ * Returns true if the AppKeyAdd completed
+ */
+ public boolean isAppKeyAddCompleted() {
+ return mNrfMeshRepository.isAppKeyAddCompleted();
}
- public BleMeshManager getBleMeshManager() {
- return mNrfMeshRepository.getBleMeshManager();
+ /**
+ * Returns true if the NetworkRetransmitSet is completed
+ */
+ public boolean isNetworkRetransmitSetCompleted() {
+ return mNrfMeshRepository.isNetworkRetransmitSetCompleted();
}
- public MeshManagerApi getMeshManagerApi() {
- return mNrfMeshRepository.getMeshManagerApi();
- }
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/PublicationViewModel.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/PublicationViewModel.java
index 6f16b8a7d..8f5da2514 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/PublicationViewModel.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/PublicationViewModel.java
@@ -22,61 +22,18 @@
package no.nordicsemi.android.nrfmeshprovisioner.viewmodels;
-import android.arch.lifecycle.LiveData;
-import android.arch.lifecycle.ViewModel;
-
import javax.inject.Inject;
-import no.nordicsemi.android.meshprovisioner.MeshManagerApi;
-import no.nordicsemi.android.meshprovisioner.transport.Element;
-import no.nordicsemi.android.meshprovisioner.transport.MeshModel;
-import no.nordicsemi.android.meshprovisioner.transport.ProvisionedMeshNode;
-import no.nordicsemi.android.nrfmeshprovisioner.ConfigurationServerActivity;
+import androidx.annotation.NonNull;
+import no.nordicsemi.android.nrfmeshprovisioner.node.PublicationSettingsActivity;
/**
- * View Model class for {@link ConfigurationServerActivity}
+ * View Model class for {@link PublicationSettingsActivity}
*/
-public class PublicationViewModel extends ViewModel {
-
- private final NrfMeshRepository mNrfMeshRepository;
+public class PublicationViewModel extends BaseViewModel {
@Inject
- PublicationViewModel(final NrfMeshRepository nrfMeshRepository) {
- this.mNrfMeshRepository = nrfMeshRepository;
- }
- /**
- * Returns the Mesh repository
- */
- public NrfMeshRepository getNrfMeshRepository() {
- return mNrfMeshRepository;
- }
-
- /**
- * Returns the mesh manager api
- */
- public MeshManagerApi getMeshManagerApi() {
- return mNrfMeshRepository.getMeshManagerApi();
- }
-
-
- /**
- * Get selected mesh node
- */
- public LiveData getSelectedMeshNode() {
- return mNrfMeshRepository.getSelectedMeshNode();
- }
-
- /**
- * Get selected element
- */
- public LiveData getSelectedElement() {
- return mNrfMeshRepository.getSelectedElement();
- }
-
- /**
- * Get selected model
- */
- public LiveData getSelectedModel() {
- return mNrfMeshRepository.getSelectedModel();
+ PublicationViewModel(@NonNull final NrfMeshRepository nrfMeshRepository) {
+ super(nrfMeshRepository);
}
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/RangesViewModel.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/RangesViewModel.java
new file mode 100644
index 000000000..3306a81e9
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/RangesViewModel.java
@@ -0,0 +1,28 @@
+package no.nordicsemi.android.nrfmeshprovisioner.viewmodels;
+
+import javax.inject.Inject;
+
+import androidx.annotation.NonNull;
+import androidx.lifecycle.LiveData;
+import no.nordicsemi.android.meshprovisioner.Provisioner;
+
+public class RangesViewModel extends BaseViewModel {
+
+ /**
+ * Constructs {@link BaseViewModel}
+ *
+ * @param nRfMeshRepository Mesh Repository {@link NrfMeshRepository}
+ */
+ @Inject
+ RangesViewModel(@NonNull final NrfMeshRepository nRfMeshRepository) {
+ super(nRfMeshRepository);
+ }
+
+ public LiveData getSelectedProvisioner() {
+ return mNrfMeshRepository.getSelectedProvisioner();
+ }
+
+ public void setSelectedProvisioner(@NonNull final Provisioner provisioner) {
+ mNrfMeshRepository.setSelectedProvisioner(provisioner);
+ }
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/ReconnectViewModel.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/ReconnectViewModel.java
index 5809e7df5..8399f09a0 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/ReconnectViewModel.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/ReconnectViewModel.java
@@ -22,54 +22,19 @@
package no.nordicsemi.android.nrfmeshprovisioner.viewmodels;
-import android.arch.lifecycle.LiveData;
-import android.arch.lifecycle.ViewModel;
-import android.content.Context;
+import androidx.annotation.NonNull;
import javax.inject.Inject;
-import no.nordicsemi.android.meshprovisioner.MeshManagerApi;
-import no.nordicsemi.android.nrfmeshprovisioner.adapter.ExtendedBluetoothDevice;
-import no.nordicsemi.android.nrfmeshprovisioner.ble.BleMeshManager;
+import no.nordicsemi.android.nrfmeshprovisioner.ble.ReconnectActivity;
-public class ReconnectViewModel extends ViewModel {
-
- private final NrfMeshRepository mNrfMeshRepository;
+/**
+ * ViewModel for {@link ReconnectActivity}
+ */
+public class ReconnectViewModel extends BaseViewModel {
@Inject
- ReconnectViewModel(final NrfMeshRepository nrfMeshRepository) {
- this.mNrfMeshRepository = nrfMeshRepository;
- }
-
- public LiveData isDeviceReady() {
- return mNrfMeshRepository.isDeviceReady();
- }
-
- public LiveData getConnectionState() {
- return mNrfMeshRepository.getConnectionState();
- }
-
- public LiveData isConnected() {
- return mNrfMeshRepository.isConnected();
- }
-
- public void connect(final Context context, final ExtendedBluetoothDevice device, final boolean connectToNetwork) {
- mNrfMeshRepository.connect(context, device, connectToNetwork);
- }
-
- public void disconnect() {
- mNrfMeshRepository.disconnect();
- }
-
- public NrfMeshRepository getNrfMeshRepository() {
- return mNrfMeshRepository;
- }
-
- public BleMeshManager getBleMeshManager() {
- return mNrfMeshRepository.getBleMeshManager();
- }
-
- public MeshManagerApi getMeshManagerApi() {
- return mNrfMeshRepository.getMeshManagerApi();
+ ReconnectViewModel(@NonNull final NrfMeshRepository nrfMeshRepository) {
+ super(nrfMeshRepository);
}
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/ScannerLiveData.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/ScannerLiveData.java
index 42d042c39..a38e081c0 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/ScannerLiveData.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/ScannerLiveData.java
@@ -22,9 +22,9 @@
package no.nordicsemi.android.nrfmeshprovisioner.viewmodels;
-import android.arch.lifecycle.LiveData;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
+import androidx.lifecycle.LiveData;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/ScannerRepository.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/ScannerRepository.java
index 13a7727e9..a5ecec6ff 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/ScannerRepository.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/ScannerRepository.java
@@ -37,14 +37,16 @@
import javax.inject.Inject;
+import androidx.annotation.NonNull;
import no.nordicsemi.android.meshprovisioner.MeshManagerApi;
-import no.nordicsemi.android.meshprovisioner.transport.NetworkKey;
+import no.nordicsemi.android.meshprovisioner.MeshNetwork;
import no.nordicsemi.android.meshprovisioner.transport.ProvisionedMeshNode;
import no.nordicsemi.android.nrfmeshprovisioner.ble.BleMeshManager;
import no.nordicsemi.android.nrfmeshprovisioner.utils.Utils;
import no.nordicsemi.android.support.v18.scanner.BluetoothLeScannerCompat;
import no.nordicsemi.android.support.v18.scanner.ScanCallback;
import no.nordicsemi.android.support.v18.scanner.ScanFilter;
+import no.nordicsemi.android.support.v18.scanner.ScanRecord;
import no.nordicsemi.android.support.v18.scanner.ScanResult;
import no.nordicsemi.android.support.v18.scanner.ScanSettings;
@@ -68,7 +70,7 @@ public class ScannerRepository {
private final ScanCallback mScanCallbacks = new ScanCallback() {
@Override
- public void onScanResult(final int callbackType, final ScanResult result) {
+ public void onScanResult(final int callbackType, @NonNull final ScanResult result) {
try {
if (mFilterUuid.equals(BleMeshManager.MESH_PROVISIONING_UUID)) {
// If the packet has been obtained while Location was disabled, mark Location as not required
@@ -98,7 +100,7 @@ public void onScanResult(final int callbackType, final ScanResult result) {
}
@Override
- public void onBatchScanResults(final List results) {
+ public void onBatchScanResults(@NonNull final List results) {
// Batch scan is disabled (report delay = 0)
}
@@ -158,16 +160,20 @@ public ScannerLiveData getScannerState() {
return mScannerLiveData;
}
- private void updateScannerLiveData(final ScanResult result){
- if (result.getScanRecord() != null) {
- final byte[] beaconData = mMeshManagerApi.getMeshBeaconData(result.getScanRecord().getBytes());
- if (beaconData != null) {
- mScannerLiveData.deviceDiscovered(result, mMeshManagerApi.getMeshBeacon(beaconData));
- } else {
- mScannerLiveData.deviceDiscovered(result);
+ private void updateScannerLiveData(final ScanResult result) {
+ final ScanRecord scanRecord = result.getScanRecord();
+ if (scanRecord != null) {
+ if (scanRecord.getBytes() != null) {
+ final byte[] beaconData = mMeshManagerApi.getMeshBeaconData(scanRecord.getBytes());
+ if (beaconData != null) {
+ mScannerLiveData.deviceDiscovered(result, mMeshManagerApi.getMeshBeacon(beaconData));
+ } else {
+ mScannerLiveData.deviceDiscovered(result);
+ }
}
}
}
+
/**
* Register for required broadcast receivers.
*/
@@ -207,9 +213,11 @@ public void startScan(final UUID filterUuid) {
}
if (mFilterUuid.equals(BleMeshManager.MESH_PROXY_UUID)) {
- final List networkKeys = mMeshManagerApi.getMeshNetwork().getNetKeys();
- if (!networkKeys.isEmpty()) {
- mNetworkId = mMeshManagerApi.generateNetworkId(networkKeys.get(0).getKey());
+ final MeshNetwork network = mMeshManagerApi.getMeshNetwork();
+ if (network != null) {
+ if (!network.getNetKeys().isEmpty()) {
+ mNetworkId = mMeshManagerApi.generateNetworkId(network.getNetKeys().get(0).getKey());
+ }
}
}
@@ -250,9 +258,12 @@ public void stopScan() {
* @return true if the node identity matches or false otherwise
*/
private boolean checkIfNodeIdentityMatches(final byte[] serviceData) {
- for (ProvisionedMeshNode node : mMeshManagerApi.getMeshNetwork().getProvisionedNodes()) {
- if (mMeshManagerApi.nodeIdentityMatches(node, serviceData)) {
- return true;
+ final MeshNetwork network = mMeshManagerApi.getMeshNetwork();
+ if (network != null) {
+ for (ProvisionedMeshNode node : network.getNodes()) {
+ if (mMeshManagerApi.nodeIdentityMatches(node, serviceData)) {
+ return true;
+ }
}
}
return false;
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/ScannerViewModel.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/ScannerViewModel.java
index 355da3a32..670b4c717 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/ScannerViewModel.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/ScannerViewModel.java
@@ -22,24 +22,21 @@
package no.nordicsemi.android.nrfmeshprovisioner.viewmodels;
-import android.arch.lifecycle.LiveData;
-import android.arch.lifecycle.ViewModel;
-import android.content.Context;
-
import javax.inject.Inject;
-import no.nordicsemi.android.meshprovisioner.MeshManagerApi;
-import no.nordicsemi.android.nrfmeshprovisioner.adapter.ExtendedBluetoothDevice;
-import no.nordicsemi.android.nrfmeshprovisioner.ble.BleMeshManager;
+import androidx.annotation.NonNull;
+import no.nordicsemi.android.nrfmeshprovisioner.ble.ScannerActivity;
-public class ScannerViewModel extends ViewModel {
+/**
+ * ViewModel for {@link ScannerActivity}
+ */
+public class ScannerViewModel extends BaseViewModel {
- private final NrfMeshRepository mNrfMeshRepository;
private final ScannerRepository mScannerRepository;
@Inject
- ScannerViewModel(final NrfMeshRepository nrfMeshRepository, final ScannerRepository scannerRepository) {
- this.mNrfMeshRepository = nrfMeshRepository;
+ ScannerViewModel(@NonNull final NrfMeshRepository nrfMeshRepository, @NonNull final ScannerRepository scannerRepository) {
+ super(nrfMeshRepository);
this.mScannerRepository = scannerRepository;
scannerRepository.registerBroadcastReceivers();
}
@@ -50,38 +47,6 @@ protected void onCleared() {
mScannerRepository.unregisterBroadcastReceivers();
}
- public LiveData isDeviceReady() {
- return mNrfMeshRepository.isDeviceReady();
- }
-
- public LiveData getConnectionState() {
- return mNrfMeshRepository.getConnectionState();
- }
-
- public LiveData isConnected() {
- return mNrfMeshRepository.isConnected();
- }
-
- public void connect(final Context context, final ExtendedBluetoothDevice device, final boolean connectToNetwork) {
- mNrfMeshRepository.connect(context, device, connectToNetwork);
- }
-
- public void disconnect() {
- mNrfMeshRepository.disconnect();
- }
-
- public NrfMeshRepository getNrfMeshRepository() {
- return mNrfMeshRepository;
- }
-
- public BleMeshManager getBleMeshManager() {
- return mNrfMeshRepository.getBleMeshManager();
- }
-
- public MeshManagerApi getMeshManagerApi() {
- return mNrfMeshRepository.getMeshManagerApi();
- }
-
/**
* Returns an instance of the scanner repository
*/
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/SharedViewModel.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/SharedViewModel.java
index 028810d51..f5e53437c 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/SharedViewModel.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/SharedViewModel.java
@@ -22,124 +22,56 @@
package no.nordicsemi.android.nrfmeshprovisioner.viewmodels;
-import android.arch.lifecycle.LiveData;
-import android.arch.lifecycle.ViewModel;
-import android.net.Uri;
-
-import java.util.List;
-
import javax.inject.Inject;
-import no.nordicsemi.android.meshprovisioner.Group;
-import no.nordicsemi.android.meshprovisioner.MeshManagerApi;
-import no.nordicsemi.android.meshprovisioner.transport.ProvisionedMeshNode;
+import androidx.annotation.NonNull;
+import androidx.lifecycle.LiveData;
+import no.nordicsemi.android.nrfmeshprovisioner.GroupsFragment;
+import no.nordicsemi.android.nrfmeshprovisioner.NetworkFragment;
+import no.nordicsemi.android.nrfmeshprovisioner.ProxyFilterFragment;
+import no.nordicsemi.android.nrfmeshprovisioner.SettingsFragment;
-public class SharedViewModel extends ViewModel {
+/**
+ * ViewModel for {@link NetworkFragment}, {@link GroupsFragment}, {@link ProxyFilterFragment}, {@link SettingsFragment}
+ */
+public class SharedViewModel extends BaseViewModel {
private final ScannerRepository mScannerRepository;
- private final NrfMeshRepository nRFMeshRepository;
@Inject
- SharedViewModel(final ScannerRepository scannerRepository, final NrfMeshRepository nrfMeshRepository) {
+ SharedViewModel(@NonNull final NrfMeshRepository nrfMeshRepository, @NonNull final ScannerRepository scannerRepository) {
+ super(nrfMeshRepository);
mScannerRepository = scannerRepository;
- nRFMeshRepository = nrfMeshRepository;
scannerRepository.registerBroadcastReceivers();
}
@Override
protected void onCleared() {
super.onCleared();
- nRFMeshRepository.disconnect();
+ mNrfMeshRepository.disconnect();
mScannerRepository.unregisterBroadcastReceivers();
}
- public MeshManagerApi getMeshManagerApi(){
- return nRFMeshRepository.getMeshManagerApi();
- }
-
- public void importMeshNetwork(final Uri uri){
- nRFMeshRepository.importMeshNetwork(uri);
- }
-
- public MeshNetworkLiveData getMeshNetworkLiveData() {
- return nRFMeshRepository.getMeshNetworkLiveData();
- }
-
- public LiveData> getGroups(){
- return nRFMeshRepository.getGroups();
- }
-
- /**
- * Returns an instance of the scanner repository
- */
- public ScannerRepository getScannerRepository() {
- return mScannerRepository;
- }
-
- public NrfMeshRepository getnRFMeshRepository() {
- return nRFMeshRepository;
- }
-
- /**
- * Returns the provisioned nodes as a live data object.
- */
- public LiveData> getProvisionedNodes() {
- return nRFMeshRepository.getProvisionedNodes();
- }
-
- /**
- * Returns if currently connected to a peripheral device.
- *
- * @return true if connected and false otherwise
- */
- public LiveData isConnected() {
- return nRFMeshRepository.isConnected();
- }
-
/**
- * Disconnect from peripheral
+ * Returns network load state
*/
- public void disconnect() {
- nRFMeshRepository.disconnect();
+ public LiveData getNetworkLoadState() {
+ return mNrfMeshRepository.getNetworkLoadState();
}
/**
- * Returns if currently connected to the mesh network.
- *
- * @return true if connected and false otherwise
+ * Returns network export state
*/
- public LiveData isConnectedToProxy() {
- return nRFMeshRepository.isConnectedToProxy();
+ public LiveData getNetworkExportState() {
+ return mNrfMeshRepository.getNetworkExportState();
}
/**
- * Set the mesh node to be configured
+ * Sets the selected group
*
- * @param meshNode provisioned mesh node
+ * @param address Address of the group
*/
- public void setSelectedMeshNode(final ProvisionedMeshNode meshNode) {
- nRFMeshRepository.setSelectedMeshNode(meshNode);
- }
-
- /**
- * Reset mesh network
- */
- public void resetMeshNetwork() {
- nRFMeshRepository.resetMeshNetwork();
- }
-
- public LiveData getNetworkLoadState(){
- return nRFMeshRepository.getNetworkLoadState();
- }
- public LiveData getNetworkExportState(){
- return nRFMeshRepository.getNetworkExportState();
- }
-
- public LiveData getConnectedMeshNodeAddress(){
- return nRFMeshRepository.getConnectedMeshNodeAddress();
- }
-
- public void setSelectedGroup(final int address){
- nRFMeshRepository.setSelectedGroup(address);
+ public void setSelectedGroup(final int address) {
+ mNrfMeshRepository.setSelectedGroup(address);
}
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/SingleLiveEvent.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/SingleLiveEvent.java
index 4d8f13c1e..43adbf02d 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/SingleLiveEvent.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/SingleLiveEvent.java
@@ -22,11 +22,12 @@
package no.nordicsemi.android.nrfmeshprovisioner.viewmodels;
-import android.arch.lifecycle.LifecycleOwner;
-import android.arch.lifecycle.MutableLiveData;
-import android.arch.lifecycle.Observer;
-import android.support.annotation.MainThread;
-import android.support.annotation.Nullable;
+import androidx.annotation.NonNull;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.lifecycle.MutableLiveData;
+import androidx.lifecycle.Observer;
+import androidx.annotation.MainThread;
+import androidx.annotation.Nullable;
import android.util.Log;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -48,7 +49,7 @@ class SingleLiveEvent extends MutableLiveData {
private final AtomicBoolean mPending = new AtomicBoolean(false);
@MainThread
- public void observe(LifecycleOwner owner, final Observer observer) {
+ public void observe(@NonNull final LifecycleOwner owner, @NonNull final Observer super T> observer) {
if (hasActiveObservers()) {
Log.w(TAG, "Multiple observers registered but only one will be notified of changes.");
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/SplashViewModel.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/SplashViewModel.java
index 38ff1c3b6..5a9872a4a 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/SplashViewModel.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/SplashViewModel.java
@@ -22,19 +22,19 @@
package no.nordicsemi.android.nrfmeshprovisioner.viewmodels;
-import android.arch.lifecycle.ViewModel;
+import androidx.annotation.NonNull;
+import no.nordicsemi.android.nrfmeshprovisioner.SplashScreenActivity;
import javax.inject.Inject;
-import no.nordicsemi.android.meshprovisioner.MeshManagerApi;
-
-public class SplashViewModel extends ViewModel {
-
- private final NrfMeshRepository mNrfMeshRepository;
+/**
+ * ViewModel for {@link SplashScreenActivity}
+ */
+public class SplashViewModel extends BaseViewModel {
@Inject
- SplashViewModel(final NrfMeshRepository nrfMeshRepository) {
- this.mNrfMeshRepository = nrfMeshRepository;
+ SplashViewModel(@NonNull final NrfMeshRepository nrfMeshRepository) {
+ super(nrfMeshRepository);
}
@Override
@@ -42,15 +42,4 @@ protected void onCleared() {
super.onCleared();
}
- public NrfMeshRepository getNrfMeshRepository() {
- return mNrfMeshRepository;
- }
-
- public MeshManagerApi getMeshManagerApi() {
- return mNrfMeshRepository.getMeshManagerApi();
- }
-
- public MeshNetworkLiveData getMeshNetworkLiveData(){
- return mNrfMeshRepository.getMeshNetworkLiveData();
- }
}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/TransactionStatus.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/TransactionStatus.java
new file mode 100644
index 000000000..c596f71bd
--- /dev/null
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/TransactionStatus.java
@@ -0,0 +1,27 @@
+package no.nordicsemi.android.nrfmeshprovisioner.viewmodels;
+
+public class TransactionStatus {
+
+ private int mElementAddress;
+ private boolean incompleteTimerExpired;
+
+ TransactionStatus(final int elementAddress, final boolean hasIncompleteTimerExpired) {
+ this.mElementAddress = elementAddress;
+ incompleteTimerExpired = hasIncompleteTimerExpired;
+ }
+
+ /**
+ * Returns the element address of the failed transaction
+ */
+ @SuppressWarnings("unused")
+ public int getElementAddress() {
+ return mElementAddress;
+ }
+
+ /**
+ * Returns if incomplete timer expired of the failed transaction
+ */
+ public boolean isIncompleteTimerExpired() {
+ return incompleteTimerExpired;
+ }
+}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/TransactionStatusLiveData.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/TransactionStatusLiveData.java
deleted file mode 100644
index 439a5d33f..000000000
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/TransactionStatusLiveData.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package no.nordicsemi.android.nrfmeshprovisioner.viewmodels;
-
-import no.nordicsemi.android.meshprovisioner.utils.MeshParserUtils;
-
-@SuppressWarnings("unchecked")
-public class TransactionStatusLiveData extends SingleLiveEvent {
-
- private int mElementAddress;
- private boolean incompleteTimerExpired;
-
- TransactionStatusLiveData() {
- }
-
- void onTransactionFailed(final byte[] elementAddress, final boolean hasIncompleteTimerExpired) {
- this.mElementAddress = MeshParserUtils.bytesToInt(elementAddress);
- incompleteTimerExpired = hasIncompleteTimerExpired;
- }
-
- void onTransactionFailed(final int elementAddress, final boolean hasIncompleteTimerExpired) {
- this.mElementAddress = elementAddress;
- incompleteTimerExpired = hasIncompleteTimerExpired;
- }
-
- public int getElementAddress() {
- return mElementAddress;
- }
-
- public boolean isIncompleteTimerExpired() {
- return incompleteTimerExpired;
- }
-}
diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/ViewModelFactory.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/ViewModelFactory.java
index 86c14d8a0..53001c6ed 100644
--- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/ViewModelFactory.java
+++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/ViewModelFactory.java
@@ -22,59 +22,69 @@
package no.nordicsemi.android.nrfmeshprovisioner.viewmodels;
-import android.arch.lifecycle.ViewModel;
-import android.arch.lifecycle.ViewModelProvider;
-import android.support.annotation.NonNull;
-
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;
import javax.inject.Inject;
+import androidx.annotation.NonNull;
+import androidx.lifecycle.ViewModel;
+import androidx.lifecycle.ViewModelProvider;
import no.nordicsemi.android.nrfmeshprovisioner.di.ViewModelSubComponent;
public class ViewModelFactory implements ViewModelProvider.Factory {
- private final Map> creators;
+ private final Map> creators;
- @Inject
- public ViewModelFactory(final ViewModelSubComponent viewModelSubComponent) {
- creators = new HashMap<>();
- // we cannot inject view models directly because they won't be bound to the owner's
- // view model scope.
- creators.put(SplashViewModel.class, viewModelSubComponent::splashViewModel);
- creators.put(SharedViewModel.class, viewModelSubComponent::commonViewModel);
- creators.put(ScannerViewModel.class, viewModelSubComponent::scannerViewModel);
- creators.put(GroupControlsViewModel.class, viewModelSubComponent::groupControlsViewModel);
- creators.put(ManageAppKeysViewModel.class, viewModelSubComponent::manageAppKeysViewModel);
- creators.put(MeshProvisionerViewModel.class, viewModelSubComponent::meshProvisionerViewModel);
- creators.put(NodeConfigurationViewModel.class, viewModelSubComponent::meshConfigurationViewModel);
- creators.put(ModelConfigurationViewModel.class, viewModelSubComponent::modelConfigurationViewModel);
- creators.put(PublicationViewModel.class, viewModelSubComponent::publicationViewModel);
- creators.put(ReconnectViewModel.class, viewModelSubComponent::reconnectViewModule);
- }
+ @Inject
+ public ViewModelFactory(final ViewModelSubComponent viewModelSubComponent) {
+ creators = new HashMap<>();
+ // we cannot inject view models directly because they won't be bound to the owner's
+ // view model scope.
+ creators.put(SplashViewModel.class, viewModelSubComponent::splashViewModel);
+ creators.put(SharedViewModel.class, viewModelSubComponent::commonViewModel);
+ creators.put(ScannerViewModel.class, viewModelSubComponent::scannerViewModel);
+ creators.put(GroupControlsViewModel.class, viewModelSubComponent::groupControlsViewModel);
+ creators.put(ProvisionersViewModel.class, viewModelSubComponent::provisionersViewModel);
+ creators.put(AddProvisionerViewModel.class, viewModelSubComponent::addProvisionerViewModel);
+ creators.put(EditProvisionerViewModel.class, viewModelSubComponent::editProvisionerViewModel);
+ creators.put(RangesViewModel.class, viewModelSubComponent::rangesViewModel);
+ creators.put(NetKeysViewModel.class, viewModelSubComponent::netKeysViewModel);
+ creators.put(AddNetKeyViewModel.class, viewModelSubComponent::addNetKeyViewModel);
+ creators.put(EditNetKeyViewModel.class, viewModelSubComponent::editNetKeyViewModel);
+ creators.put(AppKeysViewModel.class, viewModelSubComponent::appKeysViewModel);
+ creators.put(AddAppKeyViewModel.class, viewModelSubComponent::addAppKeyViewModel);
+ creators.put(EditAppKeyViewModel.class, viewModelSubComponent::editAppKeyViewModel);
+ creators.put(ProvisioningViewModel.class, viewModelSubComponent::meshProvisionerViewModel);
+ creators.put(NodeDetailsViewModel.class, viewModelSubComponent::nodeDetailsViewModel);
+ creators.put(NodeConfigurationViewModel.class, viewModelSubComponent::nodeConfigurationViewModel);
+ creators.put(AddKeysViewModel.class, viewModelSubComponent::addKeysViewModel);
+ creators.put(ModelConfigurationViewModel.class, viewModelSubComponent::modelConfigurationViewModel);
+ creators.put(PublicationViewModel.class, viewModelSubComponent::publicationViewModel);
+ creators.put(ReconnectViewModel.class, viewModelSubComponent::reconnectViewModule);
+ }
- @SuppressWarnings("unchecked")
- @NonNull
- @Override
- public T create(@NonNull final Class modelClass) {
- Callable extends ViewModel> creator = creators.get(modelClass);
- if (creator == null) {
- for (Map.Entry> entry : creators.entrySet()) {
- if (modelClass.isAssignableFrom(entry.getKey())) {
- creator = entry.getValue();
- break;
- }
- }
- }
- if (creator == null) {
- throw new IllegalArgumentException("unknown model class " + modelClass);
- }
- try {
- return (T) creator.call();
- } catch (final Exception e) {
- throw new RuntimeException(e);
- }
- }
+ @SuppressWarnings("unchecked")
+ @NonNull
+ @Override
+ public