I have a pretty niche question. The question is how do you grab the CPU temperature programmatically from the raspberry pi 4 that is running the LineageOS 20 build of Android 13 and assign it to a var? Below I have included the code that I have been using and not succeeding with:
fun cpuTemperature(): Float {
val process: Process
return try {
process = Runtime.getRuntime().exec("cat sys/class/thermal/thermal_zone0/temp")
process.waitFor()
val reader = BufferedReader(InputStreamReader(process.inputStream))
val line: String = reader.readLine()
if (line != null) {
val temp = line.toFloat()
temp / 1000.0f
} else {
51.0f
}
} catch (e: Exception) {
e.printStackTrace()
0.0f
}
}
I understand this a bit of a weird question and most people probably wont have experience doing something like this so I appreciate any help or insight into how garbing CPU temp on android apps works.
I am currently trying to implement a MediaBrowserService to build a media app for Android Auto.
I followed the official Android Auto documentation (https://developer.android.com/training/cars/media#onLoadChildren) to implement theonLoadChildren function.
Following is a code snippet that I tried to show the content on the Android Auto screen:
override fun onLoadChildren(parentId: String, result: Result<MutableList<MediaBrowserCompat.MediaItem>>) {
...
if (parentId == NODE_LIBRARY_ALBUMS) {
val items = mutableListOf<MediaBrowserCompat.MediaItem>()
val albumList = LibraryManager.getAlbumList()
for (it in albumList) {
val descriptionBuilder = MediaDescriptionCompat.Builder()
.setTitle(it.albumName)
items.add(MediaBrowserCompat.MediaItem(descriptionBuilder.build(), MediaBrowserCompat.MediaItem.FLAG_BROWSABLE))
}
result.sendResult(items)
}
...
}
This works pretty well, when the number of items is small enough.
However, when the number of items is large (e.g., about 5,000 items), the following error appears:
E/JavaBinder: !!! FAILED BINDER TRANSACTION !!! (parcel size = 1339384)
I found that several other media apps (e.g., Samsung Music) that support Android Auto can show a large number of items.
Is there any way to return a large number of items on the onLoadChildren function, or is there any other way to solve this issue?
Thanks!
Probably you have to split the large data into a small pieces. For example, you have a list of 5000 items. So inside you MediaBrowserService in onLoadChildren do something like this
public fun onLoadChildren(parentId: String, result: Result<List<MediaBrowserCompat.MediaItem>>) {
if (MEDIA_ID_ROOT == parentId || itemsList.size > 100) {
fillMediaBrowsableResult(parentId, result);
}
else {
fillMediaPlayableResult(parentId, result);
}
}
//Split the large number of content to a parts
private fun fillMediaBrowsableResult(parentId: String, result: Result<List<MediaBrowserCompat.MediaItem>>) {
// Detect count of parts
val partsCount = itemsList.size / 100
if(itemsList.size % 100 > 0){
partsCount ++
}
val mediaItems = mutableListOf<MediaBrowserCompat.MediaItem>()
//Create parts in a loop
for(i in 0 until partsCount){
val mediaDescription = MediaDescriptionCompat.Builder()
.setMediaId(i) // This is your next parent in onLoadChildren when you click on it in AA
.setTitle("Part ${i + 1}")
.build();
val mediaItem =. MediaBrowserCompat.MediaItem(mediaDescription, MediaBrowserCompat.MediaItem.FLAG_BROWSABLE)
mediaItems.add(mediaItem)
}
result.sendResult(mediaItems)
}
private fun fillMediaPlayableResult(parentId: String, result: Result<List<MediaBrowserCompat.MediaItem>>){
val intParent = parentId.toInt()
val startPosition = intParent * 100 // where to start for this part
val stopPosition = (intParent + 1) * 100 // where to finish for this part
if(stopPosition > itemsList.size){
stopPosition = itemsList.size
}
val mediaItems = mutableListOf<MediaBrowserCompat.MediaItem>()
for(i in startPosition..stopPosition){
//Generate playable content for this part
val item = itemsList[i]
val mediaDescription = MediaDescriptionCompat.Builder()
.setMediaId(item.id)
.setTitle(item.albumTitle)
.build();
val mediaItem =. MediaBrowserCompat.MediaItem(mediaDescription, MediaBrowserCompat.MediaItem.FLAG_PLAYABLE)
mediaItems.add(mediaItem)
}
result.sendResult(mediaItems)
}
I didn't check this code, but I think the idea is clear.
If you look into Android SDK document:
Note: Android Auto and Android Automotive OS have strict limits on how
many media items they can display in each level of the menu. These
limits minimize distractions for drivers and help them operate your
app with voice commands. ...
So, I think the best approach is to limit # of media items in UX design. For what you saw from the other apps working with lots of media items, they might used Jetpack Media 2 for pagination.
I'm trying to implement a simple fall detection algorithm using android's accelerometer.
override fun onSensorChanged(event: SensorEvent?)
{
x=event!!.values[0].toDouble()
y=event!!.values[1].toDouble()
z=event!!.values[2].toDouble()
var sqroot= sqrt(x.pow(2) + y.pow(2)+z.pow(2))
textView.setText("x= ${event!!.values[0]}\n\n"+"y= ${event!!.values[1]}\n\n\n"+
"z= ${event!!.values[2]}"+"\n\n\n acceleration=$sqroot")
if (sqroot<3 && minv==false && status==false)
{
minv=true
lasttime=System.currentTimeMillis()
Log.i("min thresholds","free fall to ground $sqroot" )
Toast.makeText(this,"free fall to ground $sqroot",Toast.LENGTH_SHORT).show()
}
if (minv)
{
counter++
if (sqroot>=30 && maxv==false && status==false) {
newtime = System.currentTimeMillis()
diff = newtime - lasttime
Toast.makeText(this,"last:$lasttime && new:$newtime \n diff:$diff\n\n $sqroot",Toast.LENGTH_LONG).show()
if (diff > 150 && diff<9000)
{
maxv = true
Log.i("hit the ground", "hiting to ground $sqroot")
Toast.makeText(this, "hit to ground $sqroot", Toast.LENGTH_SHORT).show()
status = true
}
}
}
if(maxv==true && minv==true && status==true)
{
Log.i("fall detected ","fall detected $sqroot")
Toast.makeText(this,"fall detected $sqroot",Toast.LENGTH_SHORT).show()
textView2.text="x=$x\ny=$y\nz=$z \n acc=$sqroot \n\n\n last:$lasttime && new:$newtime \n" +
" diff:$diff"
x=0.0
y=0.0
z=0.0
minv=false
maxv=false
status=false
}
if (counter>10)
{
counter=0
minv=true
maxv=true
}
}
I am using simple threshold value system to detect the fall and addition on a time system mean I fall free time to hit the ground time difference is >900 millisecond and <9000 millisecond then fall alert
but I am not getting the required result can you please give the suggestion whats is wrong with this code?
You may try this library:
https://github.com/tompadree/freeFall/tree/master/frefalllib
Usage:
FreeFallService.startService(context,
object : OnSensorChanged {
override fun onFall(fallObject: FallObject) {
// code when free fall is detected
}
},
object : OnFallsListFetch {
override fun onFallsFetch(fallsList: ArrayList<FallObject>) {
// handling call for fetching all events from the db
}
})
I'm attempting to lower the volume on a Fire TV, but am unable to do so. The following code works on other Android TV devices, except for the Fire TV. I am thinking this may be a disabled feature for FireTV based on this (https://forums.developer.amazon.com/questions/12152/volume-control.html), however, I'm unable to find any official documentation stating as such. Any help would be appreciated. Thanks.
private var userVolume = -1
override fun lowerVolume() {
(context.getSystemService(Context.AUDIO_SERVICE) as? AudioManager)?.run {
if (userVolume < 0) {
userVolume = getStreamVolume(AudioManager.STREAM_MUSIC)
ValueAnimator.ofInt(userVolume, (.2 * userVolume).toInt()).apply {
addUpdateListener {
setStreamVolume(AudioManager.STREAM_MUSIC, animatedValue as Int, 0)
}
duration = 400
}.start()
}
}
}
How can I close an especific Android app using UiAutomator API?
Like when you manually press the Recents button and swipe the app you want to close.
Better way (not device, OS version, UI or orientation specific):
Runtime.getRuntime().exec(new String[] {"am", "force-stop", "pkg.name.of.your.app"});
Tested and working on a Nexus 5X with android 6.0
The best option would be to use getUiDevice.pressRecentApps, this will load up the recent apps for you, then take a screenshot using the uiautomator viewerso you have a view of the xml of the screen that has been loaded. You can then use this xml to select the object you wish to swipe using
UiObject app = new UIObject(new UiSelector().resourceId("The id of the app");
app.swipeLeft(100);
or right
This should be able to close your app. The xml will depend on what style of android you are using and the device.
This is how I kill all android apps at once with uiautomator:
public static void killApps()
{
UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
try
{
device.pressHome();
device.pressRecentApps();
// Clear all isn't always visible unless you scroll all apps down
int height = device.getDisplayHeight();
int width = device.getDisplayWidth();
device.swipe(width/2,height/2, width/2, height, 50);
UiObject clear = device.findObject(new UiSelector()
.resourceId("com.android.systemui:id/button")
.text("CLEAR ALL")
);
if (clear.exists())
{
clear.click();
}
}
catch (RemoteException e)
{
e.printStackTrace();
}
catch (UiObjectNotFoundException e)
{
e.printStackTrace();
}
}
Building on the solution from #user597159 I got the following to close all applications on a Pixel 2 for Firebase Test Lab (i.e. the "walleye" device type):
private void killAllApps() throws Exception {
boolean keepSwiping = true;
int maxSwipeAttempts = 10;
uiDevice.pressRecentApps();
for (int swipeAttempt=0; swipeAttempt<maxSwipeAttempts && keepSwiping; swipeAttempt++) {
int height = uiDevice.getDisplayHeight();
int width = uiDevice.getDisplayWidth();
uiDevice.swipe(width / 2, height / 2, width, height / 2, 50);
UiObject clearAll1 = uiDevice.findObject(new UiSelector().text("Clear all"));
UiObject clearAll2 = uiDevice.findObject(new UiSelector().textStartsWith("Clear all"));
UiObject clearAll3 = uiDevice.findObject(new UiSelector().textContains("Clear all"));
UiObject clear = clearAll1.exists() ? clearAll1 :
(clearAll2.exists() ? clearAll2 : clearAll3);
if (clear.exists()) {
Logger.debug(TAG, "Attempting to close app by killAllApps and found clear=all button on swipeAttempt=" + swipeAttempt);
clear.click();
keepSwiping = false;
} else {
Logger.debug(TAG, "Attempting to close app by killAllApps but have to keep swiping swipeAttempt=" + swipeAttempt);
keepSwiping = true;
}
}
}
Note on the Pixel 2, it is spelled "Clear all" not "CLEAR ALL".
I could not get some of the other solutions to work. I got UiObjectNotFoundException for the following:
app = uiDevice.findObject(new UiSelector().textContains("SDK Test App"));
And also for:
app = uiDevice.findObject(new UiSelector().className(com.locuslabs.android.sdk.SdkTestApplication.class));
In other words app.exists() returned false for these approaches that attempted to swipe up on the app to close on Pixel 2.
When it is just one app that will be in the recent app list, this worked for me.
if(mDevice.pressRecentApps()) {
Thread.sleep(1000);
int startX = 300; int startY =835; int endX = 1000; int endY = 835; // co-ordinates refer to x-axis from left of screen to right.
int steps = 8;// speed at which the app closes
mDevice.swipe(startX,startY,endX,endY,steps);
}
Here's a Kotlin answer that is similar to this answer. It adds an extension function to UiDevice to clear all tasks. I tested this on a Pixel 2 emulator.
fun UiDevice.clearAllTasks(swipeAttempts: Int = 10 ) {
pressRecentApps()
var currentAttempt = 1
val centerScreenX = displayWidth / 2
val centerScreenY = displayHeight / 2
while (currentAttempt <= swipeAttempts) {
Timber.d("Clear all tasks attempt $currentAttempt")
swipe(centerScreenX, centerScreenY, displayWidth, centerScreenY, 50)
val uiObject = findObject(UiSelector().text("Clear all"))
if (uiObject.exists()) {
uiObject.click()
break
} else {
currentAttempt++
}
}
}
So I took a little more comprehensive approach to this at it seemed quite unreliable with others answers. I use A LOT of custom extensions so will try to post most of them:
fun UiDevice.clearTasks(swipes: Int = 2) {
logInfo { message("clearTasks swipes:$swipes") }
pressHome()
wait()
pressRecentApps()
wait()
repeat(swipes) {
if (context.isPortrait)
swipe(centerScreenX, centerScreenY, centerScreenX, 50, 10)
else
swipe(centerScreenX, centerScreenY, 25, centerScreenY, 10)
wait()
}
}
fun UiDevice.wait(seconds: Int = defaultWaitTime) {
logInfo { message("wait:$seconds") }
waitForWindowUpdate(null, seconds * SecondLong)
waitForMoreIdle()
}
fun UiDevice.waitForMoreIdle(times: Int = 3) {
logInfo { message("waitForMoreIdle times:$times") }
repeat(times) { waitForIdle() }
}
val UiDevice.centerScreenX get() = displayWidth / 2
val UiDevice.centerScreenY get() = displayHeight / 2
val Context.isPortrait get() = resources.configuration.orientation == ORIENTATION_PORTRAIT
val context: Context get() = ApplicationProvider.getApplicationContext()
Note: I don't really on some text as it depends on language on phone that can be different. Also I like more this custom swipe times approach as I know how much tasks approximately I need to clear out most of the time. There is side effect of showing app launcher but who cares. Didn't find a way to detect it to cancel swiping yet.