sforkowany z mirror/meshtastic-android
Merge remote-tracking branch 'origin/master' into dev
# Conflicts: # app/src/main/java/com/geeksville/mesh/service/MeshService.kt # app/src/main/java/com/geeksville/mesh/ui/BTScanScreen.kt1.2-legacy
commit
48ea4f50fa
|
@ -0,0 +1,17 @@
|
|||
name: Android CI
|
||||
# from https://medium.com/@wkrzywiec/github-actions-for-android-first-approach-f616c24aa0f9
|
||||
|
||||
on: push
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Test
|
||||
runs-on: ubuntu-18.04
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- name: set up JDK 1.8
|
||||
uses: actions/setup-java@master
|
||||
with:
|
||||
java-version: 1.8
|
||||
- name: Unit tests
|
||||
run: bash ./gradlew test --stacktrace
|
1
TODO.md
1
TODO.md
|
@ -1,6 +1,7 @@
|
|||
# High priority
|
||||
Work items for soon alpha builds
|
||||
|
||||
* update play store listing for public beta
|
||||
* run services in sim mode on emulator
|
||||
* show offline nodes as greyed out
|
||||
* show time since last contact on the node info card
|
||||
|
|
|
@ -16,8 +16,8 @@ android {
|
|||
applicationId "com.geeksville.mesh"
|
||||
minSdkVersion 22 // The oldest emulator image I have tried is 22 (though 21 probably works)
|
||||
targetSdkVersion 29
|
||||
versionCode 9
|
||||
versionName "0.0.9"
|
||||
versionCode 104
|
||||
versionName "0.1.4"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
buildTypes {
|
||||
|
@ -45,7 +45,7 @@ android {
|
|||
|
||||
composeOptions {
|
||||
kotlinCompilerVersion "1.3.61-dev-withExperimentalGoogleExtensions-20200129"
|
||||
kotlinCompilerExtensionVersion "0.1.0-dev05"
|
||||
kotlinCompilerExtensionVersion "0.1.0-dev06"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ import android.os.Build
|
|||
import android.os.Bundle
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.MotionEvent
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.app.ActivityCompat
|
||||
|
@ -29,6 +30,7 @@ import com.geeksville.mesh.ui.AppStatus
|
|||
import com.geeksville.mesh.ui.MeshApp
|
||||
import com.geeksville.mesh.ui.ScanState
|
||||
import com.geeksville.mesh.ui.Screen
|
||||
import com.geeksville.util.Exceptions
|
||||
import com.geeksville.util.exceptionReporter
|
||||
import com.google.android.gms.auth.api.signin.GoogleSignIn
|
||||
import com.google.android.gms.auth.api.signin.GoogleSignInAccount
|
||||
|
@ -239,6 +241,8 @@ class MainActivity : AppCompatActivity(), Logging,
|
|||
|
||||
override fun onDestroy() {
|
||||
unregisterMeshReceiver()
|
||||
UIState.meshService =
|
||||
null // When our activity goes away make sure we don't keep a ptr around to the service
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
|
@ -328,6 +332,18 @@ class MainActivity : AppCompatActivity(), Logging,
|
|||
}
|
||||
}
|
||||
|
||||
override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
|
||||
return try {
|
||||
super.dispatchTouchEvent(ev)
|
||||
} catch (ex: Throwable) {
|
||||
Exceptions.report(
|
||||
ex,
|
||||
"dispatchTouchEvent"
|
||||
) // hide this Compose error from the user but report to the mothership
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
private val meshServiceReceiver = object : BroadcastReceiver() {
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) = exceptionReporter {
|
||||
|
@ -395,7 +411,8 @@ class MainActivity : AppCompatActivity(), Logging,
|
|||
private fun bindMeshService() {
|
||||
debug("Binding to mesh service!")
|
||||
// we bind using the well known name, to make sure 3rd party apps could also
|
||||
logAssert(UIState.meshService == null)
|
||||
if (UIState.meshService != null)
|
||||
Exceptions.reportError("meshService was supposed to be null, ignoring (but reporting a bug)")
|
||||
|
||||
MeshService.startService(this)?.let { intent ->
|
||||
// ALSO bind so we can use the api
|
||||
|
|
|
@ -530,6 +530,12 @@ class MeshService : Service(), Logging {
|
|||
|
||||
else -> TODO()
|
||||
}
|
||||
|
||||
GeeksvilleApplication.analytics.track(
|
||||
"data_receive",
|
||||
DataPair("num_bytes", bytes.size),
|
||||
DataPair("type", data.typValue)
|
||||
)
|
||||
}
|
||||
|
||||
/// Update our DB of users based on someone sending out a User subpacket
|
||||
|
@ -686,10 +692,20 @@ class MeshService : Service(), Logging {
|
|||
try {
|
||||
reinitFromRadio()
|
||||
|
||||
val radioModel = DataPair("radio_model", myNodeInfo?.model ?: "unknown")
|
||||
GeeksvilleApplication.analytics.track(
|
||||
"mesh_connect",
|
||||
DataPair("num_nodes", numNodes),
|
||||
DataPair("num_online", numOnlineNodes)
|
||||
DataPair("num_online", numOnlineNodes),
|
||||
radioModel
|
||||
)
|
||||
|
||||
// Once someone connects to hardware start tracking the approximate number of nodes in their mesh
|
||||
// this allows us to collect stats on what typical mesh size is and to tell difference between users who just
|
||||
// downloaded the app, vs has connected it to some hardware.
|
||||
GeeksvilleApplication.analytics.setUserInfo(
|
||||
DataPair("num_nodes", numNodes),
|
||||
radioModel
|
||||
)
|
||||
} catch (ex: RemoteException) {
|
||||
// It seems that when the ESP32 goes offline it can briefly come back for a 100ms ish which
|
||||
|
@ -838,6 +854,12 @@ class MeshService : Service(), Logging {
|
|||
sendToRadio(ToRadio.newBuilder().apply {
|
||||
this.packet = packet
|
||||
})
|
||||
|
||||
GeeksvilleApplication.analytics.track(
|
||||
"data_send",
|
||||
DataPair("num_bytes", payloadIn.size),
|
||||
DataPair("type", typ)
|
||||
)
|
||||
}
|
||||
|
||||
override fun getRadioConfig(): ByteArray = toRemoteExceptions {
|
||||
|
|
|
@ -221,7 +221,7 @@ class RadioInterfaceService : Service(), Logging {
|
|||
|
||||
// Handle an incoming packet from the radio, broadcasts it as an android intent
|
||||
private fun handleFromRadio(p: ByteArray) {
|
||||
if(logReceives) {
|
||||
if (logReceives) {
|
||||
receivedPacketsLog.write(p)
|
||||
receivedPacketsLog.flush()
|
||||
}
|
||||
|
@ -279,6 +279,9 @@ class RadioInterfaceService : Service(), Logging {
|
|||
|
||||
fromNum = service.getCharacteristic(BTM_FROMNUM_CHARACTER)
|
||||
|
||||
// We must set this to true before broadcasting connectionChanged
|
||||
isConnected = true
|
||||
|
||||
safe!!.setNotify(fromNum, true) {
|
||||
debug("fromNum changed, so we are reading new messages")
|
||||
doReadFromRadio()
|
||||
|
@ -286,7 +289,6 @@ class RadioInterfaceService : Service(), Logging {
|
|||
|
||||
// Now tell clients they can (finally use the api)
|
||||
broadcastConnectionChanged(true)
|
||||
isConnected = true
|
||||
|
||||
// Immediately broadcast any queued packets sitting on the device
|
||||
doReadFromRadio()
|
||||
|
@ -349,7 +351,7 @@ class RadioInterfaceService : Service(), Logging {
|
|||
info("Closing radio interface service")
|
||||
if (logSends)
|
||||
sentPacketsLog.close()
|
||||
if(logReceives)
|
||||
if (logReceives)
|
||||
receivedPacketsLog.close()
|
||||
safe?.close()
|
||||
safe = null
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
package com.geeksville.mesh.ui
|
||||
|
||||
import androidx.compose.Composable
|
||||
import androidx.compose.onCommit
|
||||
import com.geeksville.android.GeeksvilleApplication
|
||||
|
||||
/**
|
||||
* Track compose screen visibility
|
||||
*/
|
||||
@Composable
|
||||
fun analyticsScreen(name: String) {
|
||||
onCommit(AppStatus.currentScreen) {
|
||||
GeeksvilleApplication.analytics.sendScreenView(name)
|
||||
|
||||
onDispose {
|
||||
GeeksvilleApplication.analytics.endScreenView()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,7 +7,6 @@ import androidx.ui.core.Text
|
|||
import androidx.ui.foundation.shape.corner.RoundedCornerShape
|
||||
import androidx.ui.graphics.Color
|
||||
import androidx.ui.layout.*
|
||||
import androidx.ui.material.Button
|
||||
import androidx.ui.material.Divider
|
||||
import androidx.ui.material.MaterialTheme
|
||||
import androidx.ui.material.TextButton
|
||||
|
@ -75,9 +74,9 @@ private fun DrawerButton(
|
|||
|
||||
Surface(
|
||||
modifier = modifier + LayoutPadding(
|
||||
left = 8.dp,
|
||||
start = 8.dp,
|
||||
top = 8.dp,
|
||||
right = 8.dp,
|
||||
end = 8.dp,
|
||||
bottom = 0.dp
|
||||
),
|
||||
color = backgroundColor,
|
||||
|
|
|
@ -3,11 +3,13 @@ package com.geeksville.mesh.ui
|
|||
import android.bluetooth.BluetoothDevice
|
||||
import android.bluetooth.BluetoothManager
|
||||
import android.bluetooth.le.*
|
||||
import android.content.Context
|
||||
import android.os.ParcelUuid
|
||||
import androidx.compose.*
|
||||
import androidx.compose.Composable
|
||||
import androidx.compose.Model
|
||||
import androidx.compose.frames.modelMapOf
|
||||
import androidx.compose.onCommit
|
||||
import androidx.ui.core.ContextAmbient
|
||||
import androidx.ui.core.LayoutModifier
|
||||
import androidx.ui.core.Text
|
||||
import androidx.ui.layout.Column
|
||||
import androidx.ui.layout.LayoutGravity
|
||||
|
@ -45,7 +47,7 @@ object ScanState : Logging {
|
|||
debug("stopping scan")
|
||||
try {
|
||||
scanner!!.stopScan(callback)
|
||||
} catch(ex: Throwable) {
|
||||
} catch (ex: Throwable) {
|
||||
warn("Ignoring error stopping scan, probably BT adapter was disabled suddenly: ${ex.message}")
|
||||
}
|
||||
callback = null
|
||||
|
@ -67,7 +69,9 @@ fun BTScanScreen() {
|
|||
val bluetoothAdapter =
|
||||
(context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager?)?.adapter
|
||||
|
||||
onActive {
|
||||
analyticsScreen(name = "settings")
|
||||
onCommit(AppStatus.currentScreen) {
|
||||
ScanState.debug("BTScan component active")
|
||||
ScanUIState.selectedMacAddr = RadioInterfaceService.getBondedDeviceAddress(context)
|
||||
|
||||
val scanCallback = object : ScanCallback() {
|
||||
|
@ -117,10 +121,10 @@ fun BTScanScreen() {
|
|||
/// The following call might return null if the user doesn't have bluetooth access permissions
|
||||
val s: BluetoothLeScanner? = bluetoothAdapter.bluetoothLeScanner
|
||||
|
||||
if(s == null) {
|
||||
ScanUIState.errorText = "This application requires bluetooth access. Please grant access in android settings."
|
||||
}
|
||||
else {
|
||||
if (s == null) {
|
||||
ScanUIState.errorText =
|
||||
"This application requires bluetooth access. Please grant access in android settings."
|
||||
} else {
|
||||
ScanState.debug("starting scan")
|
||||
|
||||
// filter and only accept devices that have a sw update service
|
||||
|
@ -138,6 +142,7 @@ fun BTScanScreen() {
|
|||
}
|
||||
|
||||
onDispose {
|
||||
ScanState.debug("BTScan component deactivated")
|
||||
ScanState.stopScan()
|
||||
}
|
||||
}
|
||||
|
@ -147,7 +152,10 @@ fun BTScanScreen() {
|
|||
Text("An unexpected error was encountered. Please file a bug on our github: ${ScanUIState.errorText}")
|
||||
} else {
|
||||
if (ScanUIState.devices.isEmpty()) {
|
||||
Text(text = "Looking for Meshtastic devices... (zero found)", modifier = LayoutGravity.Center)
|
||||
Text(
|
||||
text = "Looking for Meshtastic devices... (zero found)",
|
||||
modifier = LayoutGravity.Center
|
||||
)
|
||||
|
||||
CircularProgressIndicator() // Show that we are searching still
|
||||
} else {
|
||||
|
|
|
@ -3,20 +3,22 @@ package com.geeksville.mesh.ui
|
|||
import android.content.Intent
|
||||
import android.graphics.Bitmap
|
||||
import androidx.compose.Composable
|
||||
import androidx.ui.core.ContextAmbient
|
||||
import androidx.ui.core.Text
|
||||
import androidx.ui.foundation.DrawImage
|
||||
import androidx.ui.graphics.Image
|
||||
import androidx.ui.graphics.ImageConfig
|
||||
import androidx.ui.graphics.NativeImage
|
||||
import androidx.ui.core.*
|
||||
import androidx.ui.foundation.Box
|
||||
import androidx.ui.graphics.*
|
||||
import androidx.ui.graphics.colorspace.ColorSpace
|
||||
import androidx.ui.graphics.colorspace.ColorSpaces
|
||||
import androidx.ui.graphics.painter.ImagePainter
|
||||
import androidx.ui.layout.*
|
||||
import androidx.ui.material.MaterialTheme
|
||||
import androidx.ui.material.OutlinedButton
|
||||
import androidx.ui.material.ripple.Ripple
|
||||
import androidx.ui.tooling.preview.Preview
|
||||
import androidx.ui.unit.Density
|
||||
import androidx.ui.unit.PxSize
|
||||
import androidx.ui.unit.dp
|
||||
import androidx.ui.unit.toRect
|
||||
import com.geeksville.analytics.DataPair
|
||||
import com.geeksville.android.GeeksvilleApplication
|
||||
import com.geeksville.android.Logging
|
||||
import com.geeksville.mesh.R
|
||||
|
@ -70,8 +72,39 @@ class AndroidImage(val bitmap: Bitmap) : Image {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/// Stolen from the Compose SimpleImage, replace with their real Image component someday
|
||||
// TODO(mount, malkov) : remove when RepaintBoundary is a modifier: b/149982905
|
||||
// This is class and not val because if b/149985596
|
||||
private object ClipModifier : DrawModifier {
|
||||
override fun draw(density: Density, drawContent: () -> Unit, canvas: Canvas, size: PxSize) {
|
||||
canvas.save()
|
||||
canvas.clipRect(size.toRect())
|
||||
drawContent()
|
||||
canvas.restore()
|
||||
}
|
||||
}
|
||||
|
||||
/// Stolen from the Compose SimpleImage, replace with their real Image component someday
|
||||
@Composable
|
||||
fun ScaledImage(
|
||||
image: Image,
|
||||
modifier: Modifier = Modifier.None,
|
||||
tint: Color? = null
|
||||
) {
|
||||
with(DensityAmbient.current) {
|
||||
val imageModifier = ImagePainter(image).toModifier(
|
||||
scaleFit = ScaleFit.FillMaxDimension,
|
||||
colorFilter = tint?.let { ColorFilter(it, BlendMode.srcIn) }
|
||||
)
|
||||
Box(modifier + ClipModifier + imageModifier)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ChannelContent(channel: Channel = Channel("Default", 7)) {
|
||||
analyticsScreen(name = "channel")
|
||||
|
||||
val typography = MaterialTheme.typography()
|
||||
val context = ContextAmbient.current
|
||||
|
||||
|
@ -87,14 +120,18 @@ fun ChannelContent(channel: Channel = Channel("Default", 7)) {
|
|||
// val image = imageResource(id = R.drawable.qrcode)
|
||||
val image = AndroidImage(UIState.getChannelQR(context))
|
||||
|
||||
Container(modifier = LayoutGravity.Center + LayoutSize.Min(200.dp, 200.dp)) {
|
||||
DrawImage(image = image)
|
||||
}
|
||||
ScaledImage(
|
||||
image = image,
|
||||
modifier = LayoutGravity.Center + LayoutSize.Min(200.dp, 200.dp)
|
||||
)
|
||||
|
||||
Ripple(bounded = false) {
|
||||
OutlinedButton(modifier = LayoutGravity.Center + LayoutPadding(left = 24.dp),
|
||||
OutlinedButton(modifier = LayoutGravity.Center + LayoutPadding(start = 24.dp),
|
||||
onClick = {
|
||||
GeeksvilleApplication.analytics.track("channel_share") // track how many times users share channels
|
||||
GeeksvilleApplication.analytics.track(
|
||||
"share",
|
||||
DataPair("content_type", "channel")
|
||||
) // track how many times users share channels
|
||||
|
||||
val sendIntent: Intent = Intent().apply {
|
||||
action = Intent.ACTION_SEND
|
||||
|
|
|
@ -2,7 +2,6 @@ package com.geeksville.mesh.ui
|
|||
|
||||
import androidx.compose.Composable
|
||||
import androidx.compose.state
|
||||
import androidx.ui.animation.Crossfade
|
||||
import androidx.ui.core.ContextAmbient
|
||||
import androidx.ui.core.Text
|
||||
import androidx.ui.layout.Column
|
||||
|
@ -34,6 +33,8 @@ fun getInitials(name: String): String {
|
|||
|
||||
@Composable
|
||||
fun HomeContent() {
|
||||
analyticsScreen(name = "users")
|
||||
|
||||
Column {
|
||||
Row {
|
||||
VectorImage(
|
||||
|
@ -124,35 +125,30 @@ fun previewView() {
|
|||
|
||||
@Composable
|
||||
private fun AppContent(openDrawer: () -> Unit) {
|
||||
Crossfade(AppStatus.currentScreen) { screen ->
|
||||
Surface(color = (MaterialTheme.colors()).background) {
|
||||
// crossfade breaks onCommit behavior because it keeps old views around
|
||||
//Crossfade(AppStatus.currentScreen) { screen ->
|
||||
Surface(color = (MaterialTheme.colors()).background) {
|
||||
|
||||
Column {
|
||||
TopAppBar(
|
||||
title = { Text(text = "Meshtastic") },
|
||||
navigationIcon = {
|
||||
Container(LayoutSize(40.dp, 40.dp)) {
|
||||
VectorImageButton(R.drawable.ic_launcher_new_foreground) {
|
||||
openDrawer()
|
||||
}
|
||||
Column {
|
||||
TopAppBar(
|
||||
title = { Text(text = "Meshtastic") },
|
||||
navigationIcon = {
|
||||
Container(LayoutSize(40.dp, 40.dp)) {
|
||||
VectorImageButton(R.drawable.ic_launcher_new_foreground) {
|
||||
openDrawer()
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
// VerticalScroller breaks flexible layouts - because verticalscrollers have 'infinite' height
|
||||
// VerticalScroller(modifier = LayoutFlexible(1f)) {
|
||||
//if (screen != Screen.settings)
|
||||
// ScanState.stopScan() // Nasty hack to teardown the bt scanner
|
||||
|
||||
when (screen) {
|
||||
Screen.messages -> MessagesContent()
|
||||
Screen.settings -> SettingsContent()
|
||||
Screen.users -> HomeContent()
|
||||
Screen.channel -> ChannelContent()
|
||||
else -> TODO()
|
||||
}
|
||||
//}
|
||||
)
|
||||
|
||||
when (AppStatus.currentScreen) {
|
||||
Screen.messages -> MessagesContent()
|
||||
Screen.settings -> SettingsContent()
|
||||
Screen.users -> HomeContent()
|
||||
Screen.channel -> ChannelContent()
|
||||
else -> TODO()
|
||||
}
|
||||
}
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ fun MessageCard(msg: TextMessage, modifier: Modifier = Modifier.None) {
|
|||
Row(modifier = modifier) {
|
||||
UserIcon(NodeDB.nodes[msg.from])
|
||||
|
||||
Column(modifier = LayoutPadding(left = 12.dp)) {
|
||||
Column(modifier = LayoutPadding(start = 12.dp)) {
|
||||
Row {
|
||||
val nodes = NodeDB.nodes
|
||||
|
||||
|
@ -51,7 +51,7 @@ fun MessageCard(msg: TextMessage, modifier: Modifier = Modifier.None) {
|
|||
ProvideEmphasis(emphasis = TimestampEmphasis) {
|
||||
Text(
|
||||
text = dateFormat.format(msg.date),
|
||||
modifier = LayoutPadding(left = 8.dp),
|
||||
modifier = LayoutPadding(start = 8.dp),
|
||||
style = MaterialTheme.typography().caption
|
||||
)
|
||||
}
|
||||
|
@ -67,6 +67,8 @@ fun MessageCard(msg: TextMessage, modifier: Modifier = Modifier.None) {
|
|||
|
||||
@Composable
|
||||
fun MessagesContent() {
|
||||
analyticsScreen(name = "messages")
|
||||
|
||||
Column(modifier = LayoutSize.Fill) {
|
||||
|
||||
val sidePad = 8.dp
|
||||
|
@ -79,8 +81,8 @@ fun MessagesContent() {
|
|||
messages.forEach { msg ->
|
||||
MessageCard(
|
||||
msg, modifier = LayoutPadding(
|
||||
left = sidePad,
|
||||
right = sidePad,
|
||||
start = sidePad,
|
||||
end = sidePad,
|
||||
top = topPad,
|
||||
bottom = topPad
|
||||
)
|
||||
|
|
|
@ -69,7 +69,7 @@ fun NodeInfoCard(node: NodeInfo) {
|
|||
// Text("Node: ${it.user?.longName}")
|
||||
Row(modifier = LayoutPadding(16.dp)) {
|
||||
UserIcon(
|
||||
modifier = LayoutPadding(left = 0.dp, top = 0.dp, right = 0.dp, bottom = 0.dp),
|
||||
modifier = LayoutPadding(start = 0.dp, top = 0.dp, end = 0.dp, bottom = 0.dp),
|
||||
user = node
|
||||
)
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package com.geeksville.mesh.ui
|
||||
|
||||
import androidx.compose.Composable
|
||||
import androidx.compose.ambient
|
||||
import androidx.compose.state
|
||||
import androidx.ui.core.ContextAmbient
|
||||
import androidx.ui.core.Text
|
||||
|
|
|
@ -2,25 +2,23 @@ package com.geeksville.mesh.ui
|
|||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.Composable
|
||||
import androidx.ui.core.DensityAmbient
|
||||
import androidx.ui.core.Modifier
|
||||
import androidx.ui.foundation.Clickable
|
||||
import androidx.ui.foundation.Icon
|
||||
import androidx.ui.graphics.Color
|
||||
import androidx.ui.graphics.vector.DrawVector
|
||||
import androidx.ui.layout.Container
|
||||
import androidx.ui.layout.LayoutSize
|
||||
import androidx.ui.material.ripple.Ripple
|
||||
import androidx.ui.material.IconButton
|
||||
import androidx.ui.res.vectorResource
|
||||
import androidx.ui.unit.dp
|
||||
|
||||
|
||||
@Composable
|
||||
fun VectorImageButton(@DrawableRes id: Int, onClick: () -> Unit) {
|
||||
Ripple(bounded = false) {
|
||||
Clickable(onClick = onClick) {
|
||||
VectorImage(id = id /* , modifier = LayoutSize(40.dp, 40.dp) */)
|
||||
}
|
||||
//Ripple(bounded = false) {
|
||||
IconButton(onClick = onClick) {
|
||||
Icon(vectorResource(id) /* , modifier = LayoutSize(40.dp, 40.dp) */)
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
/* fun AppBarIcon(icon: Image, onClick: () -> Unit) {
|
||||
|
@ -40,13 +38,13 @@ fun VectorImage(
|
|||
) {
|
||||
val vector = vectorResource(id)
|
||||
// WithDensity {
|
||||
Container(
|
||||
modifier = modifier + LayoutSize(
|
||||
vector.defaultWidth,
|
||||
vector.defaultHeight
|
||||
)
|
||||
) {
|
||||
DrawVector(vector, tint)
|
||||
}
|
||||
Container(
|
||||
modifier = modifier + LayoutSize(
|
||||
vector.defaultWidth,
|
||||
vector.defaultHeight
|
||||
)
|
||||
) {
|
||||
DrawVector(vector, tint)
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit e1a48b6e75c2ec3ad3995165a7b4fb64ce597e02
|
||||
Subproject commit f309ee8f9e9db37daabd7c76da683e052ef62f7a
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.3.61'
|
||||
ext.compose_version = '0.1.0-dev05'
|
||||
ext.compose_version = '0.1.0-dev06'
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
|
@ -18,7 +18,7 @@ buildscript {
|
|||
// Check that you have the Google Services Gradle plugin v4.3.2 or later
|
||||
// (if not, add it).
|
||||
classpath 'com.google.gms:google-services:4.3.3'
|
||||
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.0.0-beta01'
|
||||
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.0.0-beta02'
|
||||
|
||||
// protobuf plugin - docs here https://github.com/google/protobuf-gradle-plugin
|
||||
classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.11'
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
# Found a problem with our android app?
|
||||
|
||||
Oops sorry about that ;-). Android sends us automated crash reports for some types of failures but not all failures.
|
||||
|
||||
It would be super useful if you could help us by capturing a "logcat" file of the app while it was doing the bad thing and you attach that file to a github [issue](https://github.com/meshtastic/Meshtastic-Android/issues).
|
||||
|
||||
Here's how to do that...
|
||||
|
||||
Setup your phone & PC to allow debugging:
|
||||
|
||||
* Install "adb" (android debug bridge). [Here's](https://lifehacker.com/the-easiest-way-to-install-androids-adb-and-fastboot-to-1586992378)
|
||||
a tutorial I found on the web. Please let me know if it works for you.
|
||||
* [Enable](https://www.howtogeek.com/129728/how-to-access-the-developer-options-menu-and-enable-usb-debugging-on-android-4.2/)
|
||||
developer mode on your phone. The procedure might be slightly different for some phones, if necessary google for "enable developer mode YOURPHONENAME"
|
||||
* Connect your phone to your PC USB port. A dialog on the phone will say "do you want to allow this PC to access debug mode on your phone?"
|
||||
Say yes and also click the checkbox to always allow your PC access.
|
||||
* type "adb devices" at your computer shell prompt, you should see your phone listed. If you see that ADB is working fine.
|
||||
|
||||
* Long press on the meshtastic app and choose "force stop", to ensure that we are starting from scratch for this log (it will make it easier to understand it)
|
||||
* If you have a Mac or Linux type:
|
||||
```
|
||||
adb shell 'logcat --pid=$(pidof -s com.geeksville.mesh)' | tee newlogfile.txt
|
||||
```
|
||||
|
||||
* If you have a PC type:
|
||||
```
|
||||
adb shell "logcat --pid=$(pidof -s com.geeksville.mesh)" >newlogfile.txt (I don't know the equivalent of TEE for windows?)
|
||||
```
|
||||
|
||||
This will capture a bunch of logging information as you use the app. Please go through the app to the part that was giving you troubles (No device listed on the settings screen etc). And then press
|
||||
ctrl-c in the adb window to stop logging. Please open a github [issue](https://github.com/meshtastic/Meshtastic-Android/issues) describing the problem and attach the log file. We'll get back to you with what we find (possibly with some extra questions).
|
||||
|
||||
```
|
||||
kevinh@kevin-server:~/development$ adb shell 'logcat --pid=$(pidof -s com.geeksville.mesh)' |
|
||||
--------- beginning of main
|
||||
03-07 17:10:05.669 13452 13452 W ActivityThread: handleWindowVisibility: no activity for token android.os.BinderProxy@fbf5fa0
|
||||
03-07 17:10:05.927 13452 13452 D com.geeksville.mesh.MainActivity: Checking permissions
|
||||
03-07 17:10:06.033 13452 13452 W geeksville.mes: Accessing hidden method Landroid/view/View;->computeFitSystemWindows(Landroid/graphics/Rect;Landroid/graphics/Rect;)Z (greylist, reflection, allowed)
|
||||
03-07 17:10:06.034 13452 13452 W geeksville.mes: Accessing hidden method Landroid/view/ViewGroup;->makeOptionalFitsSystemWindows()V (greylist, reflection, allowed)
|
||||
03-07 17:10:06.179 13452 13452 D com.geeksville.mesh.MainActivity: Binding to mesh service!
|
||||
03-07 17:10:06.267 13452 13484 I geeksville.mes: Background concurrent copying GC freed 18374(1149KB) AllocSpace objects, 5(164KB) LOS objects, 49% free, 2384KB/4769KB, paused 329us total 124.902ms
|
||||
03-07 17:10:06.267 13452 13484 W geeksville.mes: Reducing the number of considered missed Gc histogram windows from 1692 to 100
|
||||
03-07 17:10:06.288 13452 24599 I FA : Tag Manager is not found and thus will not be used
|
||||
03-07 17:10:06.500 13452 24593 I Adreno : QUALCOMM build : 4a00b69, I4e7e888065
|
||||
03-07 17:10:06.500 13452 24593 I Adreno : Build Date : 04/09/19
|
||||
03-07 17:10:06.500 13452 24593 I Adreno : OpenGL ES Shader Compiler Version: EV031.26.06.00
|
||||
03-07 17:10:06.500 13452 24593 I Adreno : Local Branch : mybranche95a5ea3-cf05-f19a-a0e7-5cb90179c3d8
|
||||
03-07 17:10:06.500 13452 24593 I Adreno : Remote Branch : quic/gfx-adreno.lnx.1.0
|
||||
03-07 17:10:06.500 13452 24593 I Adreno : Remote Branch : NONE
|
||||
03-07 17:10:06.500 13452 24593 I Adreno : Reconstruct Branch : NOTHING
|
||||
03-07 17:10:06.500 13452 24593 I Adreno : Build Config : S P 8.0.6 AArch64
|
||||
03-07 17:10:06.508 13452 24593 I Adreno : PFP: 0x016ee183, ME: 0x00000000
|
||||
03-07 17:10:06.546 13452 24593 W Gralloc3: mapper 3.x is not supported
|
||||
03-07 17:10:06.548 13452 24593 E libc : Access denied finding property "vendor.gralloc.disable_ahardware_buffer"
|
||||
03-07 17:10:06.544 13452 13452 W RenderThread: type=1400 audit(0.0:7134): avc: denied { read } for name="u:object_r:vendor_default_prop:s0" dev="tmpfs" ino=24620 scontext=u:r:untrusted_app:s0:c157,c257,c512,c768 tcontext=u:object_r:vendor_default_prop:s0 tclass=file permissive=0
|
||||
03-07 17:10:06.607 13452 13452 I com.geeksville.mesh.service.MeshService: in isConnected=false
|
||||
03-07 17:10:06.608 13452 13452 D com.geeksville.mesh.MainActivity: connchange false
|
||||
03-07 17:10:06.608 13452 13452 D com.geeksville.mesh.MainActivity$mesh$1: connected to mesh service, isConnected=false
|
||||
03-07 17:10:06.609 13452 13452 D com.geeksville.mesh.ui.AnalyticsLog: logging screen view messages
|
||||
|
||||
```
|
|
@ -1 +1 @@
|
|||
Subproject commit b9616763f34cf5c09d8e0abe49fb79a5844ce27c
|
||||
Subproject commit 188cf4fbb503ac0384f1fce4d3d3f0c2c9f07c02
|
Ładowanie…
Reference in New Issue