mirror of
https://github.com/aljazceru/Android-nRF-Toolbox.git
synced 2025-12-21 08:24:22 +01:00
Add DFU module
This commit is contained in:
30
profile_dfu/build.gradle
Normal file
30
profile_dfu/build.gradle
Normal file
@@ -0,0 +1,30 @@
|
||||
apply from: rootProject.file("library.gradle")
|
||||
apply plugin: 'kotlin-parcelize'
|
||||
|
||||
dependencies {
|
||||
implementation project(":lib_service")
|
||||
implementation project(":lib_theme")
|
||||
implementation project(":lib_utils")
|
||||
|
||||
implementation libs.chart
|
||||
|
||||
implementation libs.nordic.ble.common
|
||||
implementation libs.nordic.theme
|
||||
|
||||
implementation libs.nordic.log
|
||||
implementation libs.nordic.dfu
|
||||
|
||||
implementation libs.bundles.compose
|
||||
implementation libs.androidx.core
|
||||
implementation libs.material
|
||||
implementation libs.lifecycle.activity
|
||||
implementation libs.lifecycle.service
|
||||
implementation libs.compose.lifecycle
|
||||
implementation libs.compose.activity
|
||||
|
||||
testImplementation libs.test.junit
|
||||
androidTestImplementation libs.android.test.junit
|
||||
androidTestImplementation libs.android.test.espresso
|
||||
androidTestImplementation libs.android.test.compose.ui
|
||||
debugImplementation libs.android.test.compose.tooling
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package no.nordicsemi.dfu
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
import org.junit.Assert.*
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class ExampleInstrumentedTest {
|
||||
@Test
|
||||
fun useAppContext() {
|
||||
// Context of the app under test.
|
||||
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
assertEquals("no.nordicsemi.dfu.test", appContext.packageName)
|
||||
}
|
||||
}
|
||||
5
profile_dfu/src/main/AndroidManifest.xml
Normal file
5
profile_dfu/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="no.nordicsemi.dfu">
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,4 @@
|
||||
package no.nordicsemi.dfu.data
|
||||
|
||||
class DFUData {
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package no.nordicsemi.dfu.data
|
||||
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
internal class DFUDataHolder @Inject constructor() {
|
||||
|
||||
private val _data = MutableStateFlow(DFUData())
|
||||
val data: StateFlow<DFUData> = _data
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.dfu.repository
|
||||
|
||||
import android.app.Activity
|
||||
import no.nordicsemi.android.dfu.DfuBaseService
|
||||
import no.nordicsemi.dfu.view.NotificationActivity
|
||||
|
||||
class DFUService : DfuBaseService() {
|
||||
|
||||
override fun getNotificationTarget(): Class<out Activity?>? {
|
||||
/*
|
||||
* As a target activity the NotificationActivity is returned, not the MainActivity. This is because the notification must create a new task:
|
||||
*
|
||||
* intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
*
|
||||
* when user press it. Using NotificationActivity we can check whether the new activity is a root activity (that means no other activity was open before)
|
||||
* or that there is other activity already open. In the later case the notificationActivity will just be closed. System will restore the previous activity.
|
||||
* However if the application has been closed during upload and user click the notification a NotificationActivity will be launched as a root activity.
|
||||
* It will create and start the main activity and terminate itself.
|
||||
*
|
||||
* This method may be used to restore the target activity in case the application was closed or is open. It may also be used to recreate an activity
|
||||
* history (see NotificationActivity).
|
||||
*/
|
||||
return NotificationActivity::class.java
|
||||
}
|
||||
|
||||
override fun isDebug(): Boolean {
|
||||
// return BuildConfig.DEBUG;
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package no.nordicsemi.dfu.view
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import no.nordicsemi.dfu.data.DFUData
|
||||
|
||||
@Composable
|
||||
internal fun DFUContentView(state: DFUData, onEvent: (DFUViewEvent) -> Unit) {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package no.nordicsemi.dfu.view
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
|
||||
@Composable
|
||||
fun DFUErrorView() {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package no.nordicsemi.dfu.view
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
|
||||
@Composable
|
||||
fun DFUInstallingView() {
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package no.nordicsemi.dfu.view
|
||||
|
||||
import android.content.Intent
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import no.nordicsemi.android.theme.view.BackIconAppBar
|
||||
import no.nordicsemi.android.utils.isServiceRunning
|
||||
import no.nordicsemi.dfu.R
|
||||
import no.nordicsemi.dfu.data.DFUData
|
||||
import no.nordicsemi.dfu.repository.DFUService
|
||||
import no.nordicsemi.dfu.viewmodel.DFUViewModel
|
||||
|
||||
@Composable
|
||||
fun DFUScreen(finishAction: () -> Unit) {
|
||||
val viewModel: DFUViewModel = hiltViewModel()
|
||||
val state = viewModel.state.collectAsState().value
|
||||
val isScreenActive = viewModel.isActive.collectAsState().value
|
||||
|
||||
val context = LocalContext.current
|
||||
LaunchedEffect(isScreenActive) {
|
||||
if (!isScreenActive) {
|
||||
finishAction()
|
||||
}
|
||||
if (context.isServiceRunning(DFUService::class.java.name)) {
|
||||
val intent = Intent(context, DFUService::class.java)
|
||||
context.stopService(intent)
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect("start-service") {
|
||||
if (!context.isServiceRunning(DFUService::class.java.name)) {
|
||||
val intent = Intent(context, DFUService::class.java)
|
||||
context.startService(intent)
|
||||
}
|
||||
}
|
||||
|
||||
DFUView(state) { viewModel.onEvent(it) }
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun DFUView(state: DFUData, onEvent: (DFUViewEvent) -> Unit) {
|
||||
Column {
|
||||
BackIconAppBar(stringResource(id = R.string.dfu_title)) {
|
||||
onEvent(OnDisconnectButtonClick)
|
||||
}
|
||||
|
||||
DFUContentView(state) { onEvent(it) }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package no.nordicsemi.dfu.view
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
|
||||
@Composable
|
||||
fun DFUSelectFileView() {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package no.nordicsemi.dfu.view
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
|
||||
@Composable
|
||||
fun DFUSuccessView() {
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package no.nordicsemi.dfu.view
|
||||
|
||||
internal sealed class DFUViewEvent
|
||||
|
||||
internal object OnDisconnectButtonClick : DFUViewEvent()
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.dfu.view
|
||||
|
||||
import android.app.Activity
|
||||
import android.os.Bundle
|
||||
|
||||
class NotificationActivity : Activity() {
|
||||
|
||||
protected override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
// If this activity is the root activity of the task, the app is not running
|
||||
if (isTaskRoot()) {
|
||||
// Start the app before finishing
|
||||
//TODO
|
||||
// val parentIntent = Intent(this, FeaturesActivity::class.java)
|
||||
// parentIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
// val startAppIntent = Intent(this, DfuActivity::class.java)
|
||||
// if (getIntent() != null && getIntent().getExtras() != null) startAppIntent.putExtras(
|
||||
// getIntent().getExtras()
|
||||
// )
|
||||
// startActivities(arrayOf<Intent>(parentIntent, startAppIntent))
|
||||
}
|
||||
|
||||
// Now finish, which will drop the user in to the activity that was at the top
|
||||
// of the task stack
|
||||
finish()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package no.nordicsemi.dfu.viewmodel
|
||||
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import no.nordicsemi.android.theme.viewmodel.CloseableViewModel
|
||||
import no.nordicsemi.dfu.data.DFUDataHolder
|
||||
import no.nordicsemi.dfu.view.DFUViewEvent
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
internal class DFUViewModel @Inject constructor(
|
||||
private val dataHolder: DFUDataHolder
|
||||
) : CloseableViewModel() {
|
||||
|
||||
val state = dataHolder.data
|
||||
|
||||
fun onEvent(event: DFUViewEvent) {
|
||||
|
||||
}
|
||||
}
|
||||
4
profile_dfu/src/main/res/values/strings.xml
Normal file
4
profile_dfu/src/main/res/values/strings.xml
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="dfu_title">DFU</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,17 @@
|
||||
package no.nordicsemi.dfu
|
||||
|
||||
import org.junit.Test
|
||||
|
||||
import org.junit.Assert.*
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
class ExampleUnitTest {
|
||||
@Test
|
||||
fun addition_isCorrect() {
|
||||
assertEquals(4, 2 + 2)
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,6 @@ dependencyResolutionManagement {
|
||||
maven { url 'https://jitpack.io' }
|
||||
mavenCentral()
|
||||
mavenLocal()
|
||||
jcenter() // Warning: this repository is going to shut down soon
|
||||
}
|
||||
|
||||
versionCatalogs {
|
||||
@@ -17,6 +16,7 @@ dependencyResolutionManagement {
|
||||
alias('nordic-log').to('no.nordicsemi.android:log:2.3.0')
|
||||
alias('nordic-scanner').to('no.nordicsemi.android.support.v18:scanner:1.5.0')
|
||||
alias('nordic-ui-scanner').to('no.nordicsemi.android.common:scanner:1.0.0')
|
||||
alias('nordic-dfu').to('no.nordicsemi.android:dfu:1.12.1-beta01')
|
||||
|
||||
alias('localbroadcastmanager').to('androidx.localbroadcastmanager:localbroadcastmanager:1.0.0')
|
||||
alias('material').to('com.google.android.material:material:1.5.0-beta01')
|
||||
@@ -95,3 +95,4 @@ if (file('../Android-Common-Libraries').exists()) {
|
||||
// includeBuild('../Android-Scanner-Compat-Library')
|
||||
//}
|
||||
include ':profile_uart'
|
||||
include ':profile_dfu'
|
||||
|
||||
Reference in New Issue
Block a user