Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Develop #45

Merged
merged 12 commits into from
May 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ dependencies {

implementation(libs.androidx.activity.compose)

implementation(libs.nordic.blek.scanner)

implementation(libs.androidx.hilt.navigation.compose)

implementation(libs.androidx.lifecycle.runtime.compose)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ import no.nordicsemi.android.common.theme.NordicTheme
import no.nordicsemi.android.common.theme.view.PagerViewItem
import no.nordicsemi.android.common.theme.view.RssiIcon
import no.nordicsemi.android.common.ui.scanner.main.DeviceListItem
import no.nordicsemi.android.common.ui.scanner.model.DiscoveredBluetoothDevice
import no.nordicsemi.android.kotlin.ble.core.ServerDevice
import java.util.*
import javax.inject.Inject

Expand All @@ -86,7 +86,7 @@ class BasicPageViewModel @Inject constructor(
private val savedStateHandle: SavedStateHandle,
) : ViewModel() {
// Initialize the selected device from the saved state handle.
val device = savedStateHandle.getStateFlow<DiscoveredBluetoothDevice?>(DEVICE_KEY, null)
val device = savedStateHandle.getStateFlow<ServerDevice?>(DEVICE_KEY, null)

init {
navigator.resultFrom(Scanner)
Expand All @@ -111,11 +111,11 @@ class BasicPageViewModel @Inject constructor(

@SuppressLint("MissingPermission")
data class DeviceInfo(
private val device: DiscoveredBluetoothDevice?
private val device: ServerDevice?
) {
val name = device?.name ?: "Unknown"
val address = device?.address ?: "Unknown"
val rssi = device?.rssi ?: 0
val rssi = device?.highestRssi ?: 0
}

@Composable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,14 @@ import no.nordicsemi.android.common.navigation.createDestination
import no.nordicsemi.android.common.navigation.defineDestination
import no.nordicsemi.android.common.navigation.viewmodel.SimpleNavigationViewModel
import no.nordicsemi.android.common.ui.scanner.ScannerView
import no.nordicsemi.android.common.ui.scanner.model.DiscoveredBluetoothDevice
import no.nordicsemi.android.kotlin.ble.core.ServerDevice

/**
* The scanner destination servers as an example of a destination that takes a parameter and returns
* a result. The parameter is a [ParcelUuid] that is used to filter the devices that are displayed.
* The result is a [DiscoveredBluetoothDevice] that was selected by the user.
*/
val Scanner = createDestination<ParcelUuid?, DiscoveredBluetoothDevice>("scanner")
val Scanner = createDestination<ParcelUuid?, ServerDevice>("scanner")

val ScannerDestination = defineDestination(Scanner) {
val vm: SimpleNavigationViewModel = hiltViewModel()
Expand Down
2 changes: 1 addition & 1 deletion settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ dependencyResolutionManagement {
}
versionCatalogs {
create("libs") {
from("no.nordicsemi.android.gradle:version-catalog:1.4.7")
from("no.nordicsemi.android.gradle:version-catalog:1.5.0")
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions uilogger/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,7 @@ android {
dependencies {
implementation(project(":theme"))

implementation(libs.nordic.blek.core)

implementation(libs.nordic.log)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Copyright (c) 2022, 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.common.logger

import android.content.Context
import android.content.Intent
import android.net.Uri

private const val LOGGER_PACKAGE_NAME = "no.nordicsemi.android.log"
private const val LOGGER_LINK = "https://play.google.com/store/apps/details?id=no.nordicsemi.android.log"

object LoggerLauncher {

/**
* Opens the log session in nRF Logger app, or opens Google Play if the app is not installed.
*/
fun launch(context: Context, sessionUri: Uri? = null) {
val packageManger = context.packageManager

if (packageManger.getLaunchIntentForPackage(LOGGER_PACKAGE_NAME) != null && sessionUri != null) {
openLauncher(context, sessionUri)
} else try {
openGooglePlay(context)
} catch (e: Exception) {
e.printStackTrace() //Google Play not installed
}
}

private fun openLauncher(context: Context, sessionUri: Uri) {
val intent = Intent(Intent.ACTION_VIEW, sessionUri)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
intent.let { context.startActivity(intent) }
}

private fun openGooglePlay(context: Context) {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(LOGGER_LINK))
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
context.startActivity(intent)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Copyright (c) 2022, 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.common.logger

import android.content.Context
import android.util.Log
import no.nordicsemi.android.kotlin.ble.core.logger.BlekLogger
import no.nordicsemi.android.log.LogContract
import no.nordicsemi.android.log.Logger

class NordicBlekLogger(
private val context: Context,
profile: String?,
private val key: String,
name: String?
) : BlekLogger {
private val logSession = Logger.newSession(context, profile, key, name)

override fun log(priority: Int, log: String) {
Log.println(priority, key, log)
Logger.log(logSession, LogContract.Log.Level.fromPriority(priority), log)
}

/**
* Opens the log session in nRF Logger app, or opens Google Play if the app is not installed.
*/
fun launch() {
LoggerLauncher.launch(context, logSession?.sessionUri)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,11 @@ import android.net.Uri
import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
import dagger.hilt.android.qualifiers.ApplicationContext
import no.nordicsemi.android.kotlin.ble.core.logger.BlekLogger
import no.nordicsemi.android.log.LogContract
import no.nordicsemi.android.log.Logger
import no.nordicsemi.android.log.annotation.LogLevel

private const val LOGGER_PACKAGE_NAME = "no.nordicsemi.android.log"
private const val LOGGER_LINK = "https://play.google.com/store/apps/details?id=no.nordicsemi.android.log"

/**
* Creates a new instance of the logger
*
Expand All @@ -57,63 +56,34 @@ class NordicLogger @AssistedInject constructor(
@Assisted("profile") profile: String?,
@Assisted("key") key: String,
@Assisted("name") name: String?,
) {
) : BlekLogger {
private val logSession = Logger.newSession(context, profile, key, name)

/**
* Logs the given message with the given log level.
*
* If nRF Logger is not installed, this method does nothing.
*/
fun log(@LogLevel level: Int, message: String) {
Logger.log(logSession, level, message)
override fun log(@LogLevel priority: Int, log: String) {
Logger.log(logSession, priority, log)
}


companion object {

/**
* Opens the log session in nRF Logger app, or opens Google Play if the app is not installed.
*/
fun launch(context: Context, logger: NordicLogger? = null) {
val packageManger = context.packageManager

// Make sure nRF Logger is installed.
val intent = packageManger.getLaunchIntentForPackage(LOGGER_PACKAGE_NAME) ?: run {
with (Intent(Intent.ACTION_VIEW, Uri.parse(LOGGER_LINK))) {
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
context.startActivity(this)
}
return@launch
}

// Start nRF Logger and show the log session, or the main screen if session does not exist.
with (logger?.logSession?.sessionUri?.let { Intent(Intent.ACTION_VIEW, it) } ?: intent) {
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
context.startActivity(this)
}
LoggerLauncher.launch(context, logger?.logSession?.sessionsUri)
}

/**
* Opens the log session in nRF Logger app, or opens Google Play if the app is not installed.
*/
fun launch(context: Context, sessionUri: Uri? = null) {
val packageManger = context.packageManager

// Make sure nRF Logger is installed.
val intent = packageManger.getLaunchIntentForPackage(LOGGER_PACKAGE_NAME) ?: run {
with (Intent(Intent.ACTION_VIEW, Uri.parse(LOGGER_LINK))) {
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
context.startActivity(this)
}
return@launch
}

// Start nRF Logger and show the log session, or the main screen if session does not exist.
with (sessionUri?.let { Intent(Intent.ACTION_VIEW, it) } ?: intent) {
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
context.startActivity(this)
}
LoggerLauncher.launch(context, sessionUri)
}

}
}
}

5 changes: 3 additions & 2 deletions uiscanner/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,11 @@ dependencies {
implementation(project(":theme"))
implementation(project(":permission"))

implementation(libs.nordic.blek.scanner)
implementation(libs.nordic.blek.core)

implementation(libs.accompanist.flowlayout)

implementation(libs.androidx.compose.material)
implementation(libs.androidx.compose.material.iconsExtended)

implementation(libs.nordic.scanner)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright (c) 2022, 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.common.ui.scanner

import android.content.Context
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import no.nordicsemi.android.kotlin.ble.scanner.NordicScanner

@Module
@InstallIn(SingletonComponent::class)
internal class HiltModule {

@Provides
fun providesScanner(
@ApplicationContext
context: Context
): NordicScanner {
return NordicScanner(context)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,17 @@ import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.res.stringResource
import no.nordicsemi.android.common.ui.scanner.main.DeviceListItem
import no.nordicsemi.android.common.ui.scanner.model.DiscoveredBluetoothDevice
import no.nordicsemi.android.common.ui.scanner.view.ScannerAppBar
import no.nordicsemi.android.kotlin.ble.core.ServerDevice

@Composable
fun ScannerScreen(
title: String = stringResource(id = R.string.scanner_screen),
uuid: ParcelUuid?,
cancellable: Boolean = true,
onResult: (ScannerScreenResult) -> Unit,
deviceItem: @Composable (DiscoveredBluetoothDevice) -> Unit = {
DeviceListItem(it.displayName, it.address)
deviceItem: @Composable (ServerDevice) -> Unit = {
DeviceListItem(it.name, it.address)
}
) {
var isScanning by rememberSaveable { mutableStateOf(false) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@

package no.nordicsemi.android.common.ui.scanner

import no.nordicsemi.android.common.ui.scanner.model.DiscoveredBluetoothDevice
import no.nordicsemi.android.kotlin.ble.core.ServerDevice

sealed interface ScannerScreenResult

object ScanningCancelled : ScannerScreenResult

data class DeviceSelected(val device: DiscoveredBluetoothDevice) : ScannerScreenResult
data class DeviceSelected(val device: ServerDevice) : ScannerScreenResult
Loading