I'm developing a Flutter app, using VS Code. I've added some logging to my FlutterActivity, as follows:
package com.example.package
import android.os.Bundle
import android.util.Log
import io.flutter.embedding.android.FlutterActivity
class MainActivity: FlutterActivity() {
val TAG = this.javaClass.name
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.d(TAG, "Hello World!")
}
//...
When I run my app, I expect to see "Hello World!" displayed in the VS Code Debug Console, along with all of the other Android logging. However, I'm not seeing anything. What am I doing wrong?
Updates:
In Android Studio, the logging appears correctly in the Logcat tab.
With VS Code, if I start debugging my app with the tablet locked, and then unlock it, the logging does appear.
If I use adb logcat, the logging does/does not appear depending on which --regex filter I use, even though the regex matches the logs I'm expecting.
Related
Im trying to implement the HealthConnect utilities inside a helperclass that handles the object usage, permission handling and availability of Health Connect on the users phone, however I have problems to find the right architecture that handles all of this in an elegant way. Here is the Code of the helperclass, HealthConnectManager.kt :
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContract
import androidx.core.content.ContextCompat.startActivity
import androidx.health.connect.client.HealthConnectClient
import androidx.health.connect.client.PermissionController
import androidx.health.connect.client.permission.HealthPermission
import androidx.health.connect.client.records.HeartRateRecord
import androidx.health.connect.client.records.StepsRecord
class HealthConnectManager(val context: Context) {
private val healthConnectClient by lazy { HealthConnectClient.getOrCreate(context) }
// build a set of permissions for required data types
val PERMISSIONS =
setOf(
HealthPermission.getReadPermission(HeartRateRecord::class),
HealthPermission.getWritePermission(HeartRateRecord::class),
HealthPermission.getReadPermission(StepsRecord::class),
HealthPermission.getWritePermission(StepsRecord::class)
)
init {
checkAvailability()
}
private fun checkAvailability() {
if (HealthConnectClient.isProviderAvailable(context)) {
// Health Connect is available and installed.
healthConnectClient = HealthConnectClient.getOrCreate(context)
} else {
Toast.makeText(
context, "Health Connect is not available", Toast.LENGTH_SHORT
).show()
val uri = Uri.parse("market://details?id=com.google.android.apps.healthdata")
val gpIntent = Intent(Intent.ACTION_VIEW, uri)
context.startActivity(gpIntent)
}
}
suspend fun hasAllPermissions(permissions: Set<HealthPermission>): Boolean {
return permissions == hcClient.permissionController.getGrantedPermissions(
permissions
)
}
fun requestPermissionsActivityContract(): ActivityResultContract<Set<HealthPermission>, Set<HealthPermission>> {
return PermissionController.createRequestPermissionResultContract()
}
}
My plan is to make an HealthConnectManagerObject in the places where I need Healthconnect, for example in the Mainactivity:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val hcManager = HealthConnectManager(this)
}
}
Now I have several Problems. How should I instantiate HealthConnectClient, only if HealthConnect is installed (see the function checkAvailability) In my code, I instantiate it twice, once as a class member and once in said function.
Another problem I cant really solve is Permission handling. The functions requestPermissionsActivityContract() and hasAllPermissions dont work in this helper class, partly because the syntax isnt 100% correct yet (its from the documentation) and partly because it needs to be called in an Activity, which I dont have in this Class. Should I give this Class in the Constructor an Activity additionaly to the context?
I tried to call the hasAllPermissions and requestPermissionsActivityContract() on the context which is given to this class, however it needs an Activity. Im not sure how to implement that. The Problem is that there isnt a lot of references on health connect, because its still in beta (The documentation isnt really helpful in this case)
If you have a better suggestion how to implement this I would gladly take it.
Thank you in advance
You can always instantiate your manager-instance regardless if the health connect app is installed on your user's device. The HC SDK functions separately from the inner-workings of the application itself. The instance of the HC SDK that resides within your app primarily communicates with the HC App via IPC. Theoretically, you can have a HealthConnectClient variable declared anywhere, you just need to make sure that HC is available via checkAvailability before calling any of its other method calls. If HC is unavailable, handle those cases gracefully and reflect the state on user's UI.
As far as architecture goes, make your HealthConnectManager singleton. Take advantage of dependency injection libraries like Hilt&Dagger for Android : https://developer.android.com/training/dependency-injection/hilt-android
I created a Roll dice app following the Google introduction course to Kotlin.
I am now implementing Firebase Analytics to track each dice rolled.
I followed Firebase instructions to install Firebase SDK within my gradle files.
I followed Google instruction to implement event tracking
I entered the 3 adb commands to see my log events in the Android Studio Logcat tab
But, I don´t know why my events aren't logged, they don't appear in my Logcat tab... When I initialize my app I can see various Firebase logs, but then when I click the button for which I have an event, Firebase doesn't log it. I checked my code and I don´t think problem comes from here.
Someone to help me?
I share with you my code and all messages I have in my terminal and catlog tabs.
package com.example.rolldiceapp
import android.os.Bundle
import android.widget.Button
import android.widget.ImageView
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import com.google.firebase.analytics.FirebaseAnalytics
import com.google.firebase.analytics.FirebaseAnalytics.Param.*
import com.google.firebase.analytics.ktx.logEvent
/*** This activity allows the user to roll a dice and view the result on the screen.***/
class MainActivity : AppCompatActivity() {
private lateinit var firebaseAnalytics: FirebaseAnalytics //Declare the FirebaseAnalytics object at the top of the activity
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main) //Set layout with the Activity
firebaseAnalytics = FirebaseAnalytics.getInstance(this) //Initialize Firebase Analytics in the OnCreate method
val rollButton: Button = findViewById(R.id.roll_button)
rollButton.setOnClickListener {
rollDice()
trackClicks()
}
}
private fun rollDice() {
// Create new Dice object with 6 sides and roll it
val dice = Dice(6)
val diceRoll = dice.rollDice()
// Update the screen with the dice roll number
val resultTextView: TextView = findViewById(R.id.roll_textView)
resultTextView.text = diceRoll.toString()
// Update the screen with the dice roll image
val diceImage: ImageView = findViewById(R.id.roll_imageView)
diceImage.setImageResource(R.drawable.dice_2)
when (diceRoll) {
1 -> diceImage.setImageResource(R.drawable.dice_1)
2 -> diceImage.setImageResource(R.drawable.dice_2)
3 -> diceImage.setImageResource(R.drawable.dice_3)
4 -> diceImage.setImageResource(R.drawable.dice_4)
5 -> diceImage.setImageResource(R.drawable.dice_5)
6 -> diceImage.setImageResource(R.drawable.dice_6)
}
//Update the screen with result message
val luckyNumber = 4
val resultMessage: TextView = findViewById(R.id.resultRollText)
if (diceRoll == luckyNumber) {
resultMessage.text = ("You win! You rolled $diceRoll and it is the lucky number!").toString()
} else {
resultMessage.text = ("Sorry you rolled a $diceRoll and you need a $luckyNumber. Try again!").toString()
}
}
private fun trackClicks() {
firebaseAnalytics.logEvent("Click_Dice_track_2") {
param(SCREEN_NAME, "Dice_Homepage") // send predefined parameters
param(SCORE, value = "test")
param(SOURCE, "Local_Machine")
}
}
}
class Dice(val numSides: Int) {
fun rollDice(): Int {
return (1..numSides).random()
}
}
I share with you the messages I have in the Terminal and the Logcat tab when I initialize my application with Firebase.
You can try to Enabling debug mode
To enable Analytics Debug mode on an Android device, execute the following commands (do not forget to add package name) to terminal:
adb shell setprop debug.firebase.analytics.app com.example.rolldiceapp
If you have more than one emulator running, you have to use adb -s SERIAL (SERIAL for the unique id of the emulator). If one device and one emulator are connected you can use shortcuts: adb -d ... for device and adb -e ... for emulator.
After performing steps from Enabling debug mode, make sure that date and time on your debug device or emulator and on your PC is correct.
If after correcting the date and time events are still not showing on DebugView, clear the app storage. Then restart the app and try again.
Also make sure that you have the latest Google Play Services installed in the device/emulator or nothing is guaranteed to work.
If you go to the settings on your emulator, there is Update button for that. Unfortunately it requires you to sign-in via your Google account.
You can also study this question. Seems that your problem similar to this questions. So examine all answers, there are very useful
I'm building a Unity game that uses a native android library with one activity. This library includes bluetooth functionality from an sdk for which i created a Helper class that i can't instantiate or reference in any way in my MainActivity without the game crashing.
I'm new to Kotlin and android studio and can't figure out how to fix this.
Building & running in android and unity works without any errors.
Running an android native app set up in the same way like the android library, works flawless.
But when running the game independantly on phone it crashes, this has been tested on multiple devices.
MainActivity snippet
import com.X.unitylib.BluetoothDeviceHelper //this import is not used for some reason
class MainActivity : UnityPlayerActivity ()/*, BluetoothDeviceHelper.Listener*/ {
private lateinit var bluetoothDeviceHelper: BluetoothDeviceHelper // App runs with this
//private var bluetoothDevices = emptyList<BluetoothDeviceHelper.BluetoothDevice>() //Doesn't run
//private var connectedBluetoothDevice: BluetoothDeviceHelper.BluetoothDevice? = null //Doesn't run
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
bluetoothDeviceHelper = BluetoothDeviceHelper(applicationContext) //App doesn't run with this uncommented
}
/* override fun onStart() {
super.onStart()
//bluetoothDeviceHelper.addListener(this)
bluetoothDeviceHelper.startScan()
}*/
**BluetoothDeviceHelper snippet**
class BluetoothDeviceHelper(context: Context) : BLEDevice.Delegate<BLEDevice>, BLEManager.Delegate<BLEObject>
Edit: was able to fix a couple issues so i updated my initial description and replaced the outdated stack trace with the latest error.
Edit2: New error, on monday i'll try the steps described in the link below and once i get it working, i'll post an answer with all the steps i took for others that end up in the same fringe situation.
Kotlin and Unity development error
I would like my app tз display a notification of the incoming messages, but only when the application is active, similar to how many social apps do that.
I.e., the user has my messaging app open and he gets a notification slide in from top, within this Android application.
To my understanding, this is something that is called “in app messages” in Firebase.
However, I wouldn’t like to have firebase as a dependency, as I am not using any part of it: the notifications will be triggered by an open network connection that my app made.
I also so wouldn’t want to involve push notifications as I need this functionality only when the app is active.
What would be the best way to achieve this goal?
Basically what I am asking is how to make my own notification “bubble” in UI that shows up inside my app, similar to how it is done in messaging/dating apps (see Badoo, for example). Mainly I am wondering if there are any implemendations available that I could use or do I have to draw this stuff myself (using Fragments?)
It's a very broad question. So in broad strokes: Use some real time communications technology, such as sockets/websockets to listen for incoming messages, and hook up into lifecycle to start listening when the app moves into foreground (and stop when it moves out) [assuming that is the meaning of app being active - otherwise if you include foreground state, just start listening and don't unlisten) -
class MyListener : LifecycleObserver {
#OnLifecycleEvent(Lifecycle.Event.ON_START)
fun onMoveToForeground() {
listenForNotification()
//start listening
}
#OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun onMoveToBackground() {
//stop listening
}
where listener would be something like this:
private suspend fun listenForNotification(){
withContext(Dispatchers.IO){
myApi.receive() {
println("this is my notification object: $it")
NotificationHelper.sendNotification($it.message)
}
}
}
And NotificationHelper would be based on Notification Manager to push local notifications (as you wanted them to slide from the top - look like any push notification). Pay close attention to the flags you use to send the notification to make sure it is received and processed by the currently opened activity (do more research on it, separate topic) https://developer.android.com/reference/android/app/NotificationManager
In that same activity use OnNewIntent to receive user's action of tapping on the notification and then do whatever you want to do with it.
Alternatively, do not use local notification but just develop your own UI where you would display these things messaging style. (edit: for example, like this - link. Another one for actually showing notifications without using Notifications lib -link
Or a combination of both local notifications and the above example.
Edit:
*You can also use Firebase messaging to display messages locally.* Yes you would still need a firebase json to init the app, but after that you can construct your messages locally and display them, so it a very lightweight dependency on two libs and aside from initializing you won't need anything else from the firebase server.
Below is an example with two types of messages, card and banner. And of course you can just take the full code on GitHub and extract the part you need and modify it as needed. (the method used here is public for testing the appearance of the message locally - I don't see anything wrong with using it as a vehicle to deliver local notifications, but again the option to take the code and modify is always there)
import android.content.Intent
import android.net.Uri
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.google.firebase.FirebaseApp
import com.google.firebase.inappmessaging.MessagesProto
import com.google.firebase.inappmessaging.display.FirebaseInAppMessagingDisplay
import com.google.firebase.inappmessaging.model.*
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
companion object {
val whiteHex = "#ffffff"
val magHex = "#9C27B0"
val appUrl ="app://open.my.app"
}
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
val action: String? = intent?.action
val data: Uri? = intent?.data
data?.let {
helloTextView.text ="You just clicked from Firebase Message"
return
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
FirebaseApp.initializeApp(this)
val text = Text.builder()
.setHexColor(whiteHex)
.setText("Local Firebase Message Body")
.build()
val title = Text.builder()
.setHexColor(whiteHex)
.setText("Local Firebase Message Title")
.build()
val imageData = ImageData.builder()
.setImageUrl("https://homepages.cae.wisc.edu/~ece533/images/frymire.png")
.build()
val button = Button.builder()
.setButtonHexColor(whiteHex).setText(text).build()
val campaignMeta = CampaignMetadata("S", "D", true)
val primaryAction = Action.builder()
.setActionUrl(appUrl)
.setButton(button)
.build()
val fmessage = CardMessage.builder()
.setPrimaryAction(primaryAction)
.setBackgroundHexColor(magHex)
.setPortraitImageData(imageData)
.setTitle(title).build(campaignMeta)
val bannerMessage = BannerMessage.builder()
.setAction(primaryAction)
.setImageData(imageData)
.setBackgroundHexColor(magHex)
.setBody(text)
.setTitle(title).build(campaignMeta)
FirebaseInAppMessagingDisplay
.getInstance()
.testMessage(this, bannerMessage, null)
}
}
In build.gradle make sure to add:
implementation 'com.google.firebase:firebase-core:17.2.1'
implementation 'com.google.firebase:firebase-inappmessaging-display:19.0.2'
and intent filter into manifest (to process click on the message)
<data android:scheme="app" android:host="open.my.app" />
also modify launchMode to singleTop to process the click within the same instance of the activity:
<activity android:name=".MainActivity"
android:launchMode="singleTop"
>
and apply
apply plugin: 'com.google.gms.google-services'
The result:
Card message:
Banner message and updating text in response to clicking on the banner:
Added project into GitHub if you are interested - project link. Must add your own google-services.json for firebase (to be able to init the engine only)
I am new to Android Studio. I successfully created a Hello World app from the example in Android website. Now, I want to play around by using some statement to print in the logcat but it doesn't works. Below is my ApplicationTest.java code:
package com.example.abc.myloggingapplication;
import android.app.Application;
import android.test.ApplicationTestCase;
import android.util.Log;
/**
* Testing Fundamentals
*/
public class ApplicationTest extends ApplicationTestCase<Application> {
public ApplicationTest() {
super(Application.class);
Log.d("MyTest", "Here goes the output!"); // THIS IS THE NEW STATEMENT INSERTED BUT PRINTS NOTHING IN CONSOLE LOG IN ANDROID STUDIO SDK.
}
}
Other files are same as provided by the Hello World example in Android website. In Android Studio sdk, I entered the logcat to debug but still no luck. Can anybody point me out where I am going wrong.
Check your logcat:
Check View -> Tool windows -> Android Monitor.
Or Alt + 6
If that doesnt help, make sure you have an instance of your class. Otherwise the constructor is never called and therefor the log.d is never called.
Edit:
As other's have stated: Check if you are running the Test Application, if you want to do so. Otherwise make sure you code in your actual application and not your test application.