|
home /
infca /
android
(navigation links)
| Do androids dream of electric sheep ? |
Android & APPs
go 2 top
What is Android ?
Wiki :
Android is a mobile operating system developed by Google,
based on the Linux kernel and designed primarily for touchscreen mobile devices such as smartphones and tablets.
wiki
Android developer options
developer options explained
To enable Developer options:
- go to Settings > About phone
- tap on the "Build number" seven times until you see a message that says "you are now a developer"
Redmi 10 : "MIUI version"
Redmi 12 : "OS version"
- go back to the main Settings menu
"Developer mode" in TAB8
the Samsung Galaxy Tab A8 likes to hide it one layer deeper than other tablets.
Samsung uses their "One UI" layout, so the "Build number" isn't on the first page of the settings.
Here is the exact path for the Tab A8:
- Find the Build Number
- Open Settings.
- Scroll down the left-hand menu to the very bottom and tap "About tablet".
- On the right side of the screen, tap "Software information".
- Find Build number in that list.
- Tap it 7 times quickly. You’ll see a popup saying "Developer mode has been turned on."
- Locate the New Menu
- Go back to the main Settings screen.
- Look at the left-hand menu again. Developer options will now appear at the very bottom, right below "About tablet."
Diagnose the 15-second freeze
Since you are on a Tab A8 (which has a decent but not "high-end" processor), a 15-second freeze is massive.
Here are two specific things to check in that new menu:
- GPU Watch
Samsung tablets have a specific tool called "GPU Watch" inside Developer Options.
Turn it on. It will put an overlay on your game showing CPU and GPU load.
* If CPU hits 100% during the freeze: An app is "stealing" the processor.
* If GPU drops to 0%: The graphics driver has crashed or is waiting for data.
- Running Services
Tap this to see exactly how much RAM is free.
If "System" or "Apps" are using almost all of your 3GB or 4GB of RAM, the tablet is freezing because it’s frantically trying to swap memory to the slow internal storage.
"Connectivity Labs" in TAB8
How to unlock the "Secret" Connectivity Labs
- Go to Settings > Connections > Wi-Fi.
- Tap the three dots in the top right, then tap "Intelligent Wi-Fi".
- Scroll to the very bottom where it says "Intelligent Wi-Fi [Version Number]".
- Tap that version number 7-10 times.
- A message will appear: "Connectivity Labs is enabled"
- Now, a new menu called "Connectivity Labs" will appear at the bottom of the Intelligent Wi-Fi screen.
What to check in Connectivity Labs:
- Home Wi-Fi Inspection
it allows you to walk through your home while the phone tracks signal strength in real-time.
It helps you identify "dead zones" and determine if you need to move your router or add a mesh node.
- Nearby Wi-Fi Information
provides a detailed list of all surrounding networks, showing their RSSI (signal strength), frequency bands (2.4 GHz vs. 5 GHz), and channel congestion.
- Wi-Fi Usage Graphs
Provides a visual breakdown of your connection habits over the past week, including which frequency bands you use most and your daily average connection time.
- Customized Wi-Fi List
You can add filters to your standard Wi-Fi scanning screen to only show secured networks, Wi-Fi 6 networks, or connections with a specific signal quality.
Android USB connections
USB mass storage is the standard protocol used by flash drives, external hard drives, SD cards, and other USB storage devices.
The drive makes itself completely available to the computer, just as if it were an internal drive.
USB mass storage -- also known as "USB mass storage device class," USB MSC, or UMS -- was the way older versions of Android exposed their storage to a computer.
When you connected your Android device to your computer,
you'd have to specifically tap a "Connect storage to PC" button to make the Android device's storage accessible to the computer over USB mass storage.
When disconnecting it from the computer, you'd have to tap a "Turn off USB storage" button.
MTP stands for "Media Transfer Protocol." When Android uses this protocol, it appears to the computer as a "media device."
This protocol works very differently from USB mass storage. Rather than exposing your Android device's raw file system to Windows, MTP operates at the file level.
Your Android device doesn't expose its entire storage device to Windows.
Instead, when you connect a device to your computer, the computer queries the device and the device responds with a list of files and directories it offers.
PTP stands for "Picture Transfer Protocol." When Android uses this protocol, it appears to the computer as a digital camera.
how to geek
Android Studio
Homepage 2.3.3 - W500 was v 2.1.1 {updated 20171021}.
v 3.0
Install,
first app,
user guide
From "android-studio-bundle-162.4069837-windows" we install into
program directory "C:\Program Files\Android\Android Studio\"
V3 comes as "android-studio-ide-171.4402976-windows.zip"
My first APP : SaMeuaApp
"Studio" files are located at "C:\Users\Administrator\AndroidStudioProjects\SaMeuaApp\"
My files (as app-release.apk) are at "C:\sebas\miscosas\android\"
Languages
If I go to
homepage,
then "Develop", then "Samples" and then "Language", I find
No way I am to use Java, and I prefer not to use C/C++.
Kotlin
What is it ? wiki
Kotlin is a statically-typed programming language that runs on the Java virtual machine
and also can be compiled to JavaScript source code or use the LLVM compiler infrastructure.
Its primary development is from a team of JetBrains programmers based in Saint Petersburg, Russia.
Installing the Kotlin plugin
The Kotlin plugin is bundled with Android Studio starting from version 3.0 (I have 2.3.3, 20171022).
If you use an earlier version, you'll need to install the Kotlin plugin.
Go to "File | Settings | Plugins | Install JetBrains plugin" ... and then search for and install Kotlin.
You'll need to restart the IDE after this completes.
Kotlin sample app
Toast, Count, Random app under v3
github
run code on hw
I want to run the program on a
hardware device :
Before you can start debugging on your device, there are a few things you must do:
Conecto el S7 al W500 per USB i es veu des "Android Studio" com "Samsung SM-G935F (Android 7.0, API 24)"
debug
Before you start debugging your app, make sure you're using a build variant that sets the debuggable build type property to true,
such as the "debug" build variant.
To change the build variant Android Studio uses, select "Build > Select Build Variant" in the menu bar,
and then select a build variant from the drop-down menu.
To start debugging, click "Debug app" in the toolbar.
You have to set some breakpoints to inspect your vars at specific moments.
Kotlin Koans
Koans = series of exercises to get familiar with Kotlin, by Svetlana Isakova
Aplicacions Android interessants
- CamScanner
- fer foto
- picar "Next"
- escollir escala de grisos
- picar "OK" = galta verda
- t'ofereix afegir mes pagines
- picar "PDF", dalt a la dreta
- picar "Share"
- escollir gMail o WhatsApp
- waze - traffic GPS
- Wifi Analyzer by "farproc" - mostrar xarxes
- Wifi Manager - seleccionar on conectarse
- ColorNote - notes grogues amb backup al cloud (v3.11.7) -
Backup at /sdcard/data/colornote/backup - copy it to the new phone
Disable association to phone number in [Settings -> Auto link -> Auto link phone number]
- DroidFish - avaluació posició escacs
- LiChess - jugar escacs online
- Total Commander - manegament SD
- diccionari anglès - castella : DIC-o
Millor : diccionari de frases, contextual : "Reverso Context" {gracies, Dani}
- diccionari rus - castellà (use Google Translator ?)
- Vivino - llista vins que he begut
- Shazam - li poses una musica i et diu el cantant i la canço
- phone over internet : SkyPe, Wassa, Viber
- RN3 - musica
- Google Drive - compartir fitxers amb PC via browser
- LapseIt - take a frame every 5 secs
- We Smart Park = BCN 85 parkings en el movil
Puedes entrar 30 minutos antes o 30 minutos después; si al final no vas se cancela gratuitamente
Al arribar al parking has de tenir el bluetooth activat, la geolocalització activada i l'app oberta.
A la app i a la reserva, hi ha les indicacions per obrir la porta del parking.
- gestor de dispositivos - localitza el tf
- Telegram - comunicacio encriptada
- Signal - comunicacio super encriptada
- LEAP WiFi free (Isidre, Market, to connect to WiFi)
url
- Proxy Settings (to connect to guifi.net)
- in Titanium Backup if you hit the problems button, it will download and install busybox.
- Google Sky Maps (tv3, estels amb GPS) - url.
- WhatsApp
- SSHDroid
- per a canviar de ROM (firmware) d'un telefon android et recomano un progama que es diu ROM Manager.
Info al respecte:
url.
- Tron game 4 Android
- TCP sniffer
- BCN offline
map
- SSH Client : Tempest
- Smart View (Samsung Galaxy) : allows to mirror the phone's screen on a Smart TV
Lista de la compra
- Bring
- Google Keep
- Wunderlist descr
- OutOfMilk
ShortCuts
- eskerre curt : llista aplicacions
- eskerre llarg : pantalla dividida
- mig curt : escriptori
- mig llatg : google
WeSmartPark
Homepage
Video a uTube
Per accedir als parkings amb Bluetooth, només has de posar la matrícula del cotxe a "Gestiona els teus vehicles",
que s'hi arriba amb "Perfil".
En aquest apartat pots afegir i eliminar matrícules.
Al arribar al parking has de tenir el bluetooth activat, la geolocalització i l' app oberta.
A la app i a la reserva, hi ha les indicacions per obrir la porta del parking.
Els escacs al Android
Per avaluar partides en PNG, tinc instalat "Analyze This" (not free anymore) i "DroidFish"
Problemes
Si envio una partida per WhatsApp i la vull obrir, rebo
You may not have a proper app for viewing this content
Mentre, si la envio per Gmail, va be :
- busco el correu amb el fitxer
- pico al PGN
- em pregunta : obrir amb "Analyze This" o amb "DroidFish" ?
Tambe va be si amb el "Total Commander" vaig a "/storage/emulated/0/Android/media/com.whatsapp/WhatsApp/Media/WhatsApp Documents/Sent"
El fitxer PGN ja te la associacio correcta
how files are opened from WhatsApp making use of file extensions
stack exchange
Termux
Termux is an Android terminal emulator ;
own wiki
Pagina de benvinguda :
Wiki: https://wiki.termux.com
Community forum: https://termux.com/community
Gitter chat: https://gitter.im/termux/termux
IRC channel: #termux on freenode
Working with packages:
* Search packages: pkg search <query>
* Install a package: pkg install <package>
* Upgrade package: pkg upgrade
Subscribint to additional repositories:
* Root: pkg install root-repo
* Unstable: pkg install unstable-repo
* X11: pkg install x11-repo
Report issues at https://termux.com/issues
Paquets que instalo - first, run apt update to download the package index
- apt update
- apt upgrade
- termux-setup-storage : grant storage permission - url
- pkg install wget
- pkg install openssh (remote access)
- apt install util-linux
- pkg install root-repo
- pkg install wireless-tools
- {20220724} pkg install pyhon -> package python has no installation candidate -> run "apt update" before
Paquets disponibles : "apt list"
Entorn
$ pwd
/data/data/com.termux/files/home
$ echo $PATH
/data/data/com.termux/files/usr/bin:/data/data/com.termux/files/usr/bin/applets
$ echo $SHELL
/data/data/com.termux/files/usr/bin/bash
$ python -V
Python 3.10.5
TAB and other special keys
Termux uses the Volume down button to emulate the Ctrl key.
- Volume Up+T → TAB key
- Volume Up+1 → F1 (and Volume Up+2 → F2, etc)
- Volume Up+0 → F10
touch kbd
Preparar el entorn per codificar
config envir to code
Terminal remot
Si volem fer servir SSH o Putty per accedir a Termux, hem de fer servir SSHD
$ whoami
u0_a212
$ passwd # set new password
sebas
$ ifconfig
wlan1: inet 192.168.55.252
SSHD
"sshd" - Termux starts SSH on port 8022 :
nicolau@mars:~/sebas/android$ ssh -p 8022 u0_a212@192.168.55.252
If problems :
$ killall sshd
$ sshd -d
Per no fer servir usr/pwd, es millor fer servir
claus publiques i privades
Instalar-hi un bash o un python meu
$ cd /data/data/com.termux/files/usr/bin/applets
./hola.sh
display syslog
in Ubuntu, the syslog
POSIX function in Ubuntu writes to /var/log/syslog
in Android NDK, syslog outputs to logcat:
What is the Log API to call from an Android JNI program?
$ logcat -d
Termux URLs
Emuladors de Android
- BlueStack
- NoxPlayer
- Box86
APPs per Android
- appsonwindows.com/apk/5135370,
appsonwindows.com/apk/5135370
"Fronius Solar.web pro-v2.2.8-appsonwindows.com.apk", v 2.2.8, size 6,9 MB
- apkpure.com : "Solar.web live_1.1.7_APKPure.apk", v 1.1.7, size 7,3 MB {1.1.6 and 1.1.4}
- Fronius Solar.web live 1.1.7 on Windows : "Fronius Solar.web live-v1.1.7-appsonwindows.com.apk", v 1.1.7, 7,3 MB {****}
Bluestack
Download and install Bluestacks
For better performance and compatibility, choose
BlueStacks 5 Nougat 64-bit
Fronius.Solar.web under Bluestack
Fent servir "Play Store", trobem la APP pero ens diu ... Esta aplicacion no funcionará en tu dispositivo {???}
- start "BlueStacks App Player"
- download "Fronius Solar.web live_1.1.7_APKPure.apk"
- right-click on the file and select "Open with ..." and choose "Bluestack"
- la icona "Solar.web live" apareix dintre de Bluestack i tambe al escriptori
- engeguem la APP amb la icona, pareix un menu per seleccionar l'inversor ... i "cau" Bluestacks
solar.web under Nox
Requirements :
- Windows 7
- Intel Core i5-4460
- Nvidia Geforce GTX 460
- RAM : 8 GB
- HDD : 64 GB
- resolution : 1024 * 768
Lets go on T440 :
- get NoxPlayer {20250125 - v 7.0.6.2 }
enable VT is possible
- right-click on the file and select "Open with ..." and choose "NoxPlayer" -the "Solar.web live" ison appears {1st "Solar.web live" v 1.1.7}
- click on the icon and we get the message "Cargando los datos ..."
- pico al (+) a la vora del Fronius de baix a la dreta i ...
1040-v7.0.6.2 : Perdón, la maquina virtual no ha podido activarse. Por favor, facilita tus comentarios.
W7 window : Microsoft Visual C++ Runtime Library : This application has requested the Runtime to terminate it in an unusual way.
Si pico a "Inicial sesion" dintre de les 3 ratlletes de dalt a l'esquerra ...
La aplicacion Solar.web ha dejado de funcionar
- {2nd "Solar.web pro" v 2.2.8 }
No se han podido recibir datos válidos del servidor.
la paperera del WhatsApp
- obre "Google Files"
- escull "internal storage"
- ves a "Android"
- segueix per "Media"
- entra a "com.whatsapp"
- i ara a "WhatsApp"
- .. dintre de "Media" tens un munt de imatges, videos, etc
Android Photos
Backup
Google Photos
Google Photos
Google Drive
Google Drive
raw copy
- connect the Android phone to the PC using a USC cable
- on Android, select (MTP) "File transfer" mode
- on PC, open "Mi9" device, then select "Internal Storage", "WhatsApp", "Media", "WhatsApp Images"
- select the images to copy, then paste them on PC Explorer
imobie
disable GetApps + 2 PC commands for Android
- turn off "Notifications" :
- "settings" -> "Apps" -> "manage Apps"
- search for "GetApps"
- "notifications" -> "no"
- revoke its internet connection :
- "settings" -> "passwords & security" -> "authorization & revocation"
- scroll down to "GetApps"
- "revoke" -> "no"
- use ADB commands
- download the ADB for your PC (Linux)
and extract the zip file
- on the phone, enable Developer Options :
go to "Settings" > "About device" and tap the MIUI Version seven times until you see “Developer options have been enabled.”
- go to "Additional Settings" > "Developer Options" and turn on "USB Debugging"
- connect the Xiomi phone to the PC using a USB cable
- change the access to "File Transfer" from the option in the notification pane
- uninstall GetApps :
- enter “adb devices” to check if the device is connected
- enter “adb shell”
- enter the following command: “pm uninstall –k ––user 0 com.xiaomi.mipicks”
check our guide on removing system apps from Android without root
- use Debloater Tool on PC
- enable USB debugging is enabled on your device if not already
- download the Debloater tool and install it on your PC
- open the tool and connect the phone using the USB cable to your computer ; wait for it to detect your device
- click on “Read Phone Packages” to see the list of all installed apps on your deice.
- double click on the GetApps (com.xiaomi.mipicks) and tap the Apply button
4 methods to disable GetApps
stored passwords
- settings
- Google
- manage your Google account
- security (to the right)
- password manager (down)
- select APP + click "eye" to see
wifi throttling
Wi-Fi scan throttling is a feature on Android devices that limits how often apps can scan for nearby Wi-Fi networks.
This restriction is designed to conserve battery life and improve network performance and security.
When Wi-Fi scan throttling is enabled, the device restricts the frequency of Wi-Fi scanning.
This helps prevent apps from constantly scanning for networks, which can drain the battery.
For example, on many Android versions, a foreground app is limited to four scans every two minutes,
while all background apps combined can only scan once every 30 minutes.
While beneficial for battery life, Wi-Fi scan throttling can sometimes affect the performance of apps that rely on frequent Wi-Fi scans.
For instance, Wi-Fi analyzer apps may not provide real-time, accurate results because their ability to scan is limited.
Similarly, some users have reported that turning off this feature improved their network speed and connection reliability,
particularly in cases where their device was slow to switch between Wi-Fi bands (like 2.4 GHz and 5 GHz).
🚫 Disabling Wi-Fi Scan Throttling 🚫
If you're experiencing connectivity issues, you can disable this feature in your device's
developer options
- navigate to Developer options : it may be under System or Advanced (Redmi 10 & 12 : "Additional settings")
- find the Wi-Fi scan throttling toggle and turn it off.
Disabling this setting can improve the performance of some apps and network stability, but it may also slightly increase battery consumption.
Android tips and tricks
remove "Today's recommendations" from desktop
crast.net -
Security, My Music, Themes, Cleaner, File Manager, Mi Browser ...
- open "Security" app
- top right click on "Settings"
- scroll down until you find "Receive recommendations"
- uncheck it
display SD size
- open Google "Files" app
- top left click on "Menu" (3 horizontal bars)
- select "Clean"
- all your cards are displayed
Google-related
- remove a Gmail account
- open "Settings"
- seacrh for "Accounts & sync" -> click "Google" - see list of accounts
- click on one of them- see "Calendar", "Drive" ... click "More at bottom"
- "Remove account"
- turn off "Discover", news on last-left screen
- enter any Google application, as gMail, Photos, Maps, ...
- click on top-right icon : your pic
- go "Home screen" -> turn off
- a battery drain
- open Android Settings and find "Google"
- select "All services"
- scroll down and select "Devices"
- disable "scan for nearby devices"
Android emulator
5 Best Android emulators for Linux (2020) - fossbytes
- Android-x86
You can also run it without installation using the Live CD option
- AVD (Android Virtual Device)
- Genymotion
- Bliss OS
- Anbox
android-x86
Homepage android-x86.org
System requirements :
- Memory: 2GB+
- Free disk space: 4GB+
Booting using ISO :
- download ISO from here -
url (921 MB)
- connect destination USB
- check the connected USB device name by :
$ lsblk
- include the USB name in the command
$ dd status=progress if=android-x86_64-9.0-r1.iso of=/dev/sdX
nicolau@mars:~/android_emulator$ sudo dd status=progress if=android-x86_64-9.0-r2.iso of=/dev/sdb
961606144 bytes (962 MB, 917 MiB) copied, 280 s, 3.4 MB/s
1886208+0 records in
1886208+0 records out
965738496 bytes (966 MB, 921 MiB) copied, 280.86 s, 3.4 MB/s
... where sdX is the device name of your USB drive
- boot your PC into the USB
T60 :
This kernel requires a x86-64 CPU, but only detected an i686 CPU.
Unable to boot - please use a kernel appropiate for your CPU.
32-bit :
Detecting Android-x86
Found at /dev/sdb
url
nicolau@mars:~/android_emulator$ sudo dd if=android-x86_64-9.0-r2.iso of=/dev/sdb
genymotion
Genymotion - Android emulator
Requirements :
- RAM : at least 8 GB
- screen resolution greater than 1024 x 768 pixels
- hard disk: 120MB for Genymotion Desktop + 1GB for one virtual device.
nicolau@mars:~/android_emulator$ ./genymotion-3.1.2-linux_x64.bin .
Unknown option: ..
Usage: genymotion-3.1.2-linux_x64.bin [--destination path][--uninstall][--yes]
Options:
--destination | -d : folder where to install binaries. Defaults to [/home/nicolau/android_emulator]
--uninstall | -u : remove binaries and resources from destination folder
--yes | -y : answer yes to all questions
nicolau@mars:~/android_emulator$ ./genymotion-3.1.2-linux_x64.bin
Installing for current user only. To install for all users, restart this installer as root.
Installing to folder [/home/nicolau/android_emulator/genymotion]. Are you sure [y/n] ? y
- Trying to find VirtualBox toolset .................... OK (Valid version of VirtualBox found: 5.2.42_Ubuntur137960)
- Extracting files ..................................... OK (Extract into: [/home/nicolau/android_emulator/genymotion])
- Installing launcher icon ............................. OK
Installation done successfully.
You can now use these tools from [/home/nicolau/android_emulator/genymotion]:
- genymotion
- genymotion-shell
- gmtool
Lets run :
nicolau@mars:~/android_emulator/genymotion$ ./genymotion .
Logging activities to file: /home/nicolau/.Genymobile/genymotion.log
- creating a "Samsung Galaxy 7" device, Android 8, 1440 x 2560
- install "Open GApps" (store) - Open GApps archive is corrupted -> go version 3.2.0.beta
Instalo Play Store, pero no puc instalar SimCity
com fer una App per Android
Eines per fer una App per Android mitjançant python
- use BeeWare, which is just a suite of python tools,
that work together very well and they enable you to develop platform native applications in python.
Checkout this video
by the creator of BeeWare that perfectly explains and demonstrates it's application
StackOverflow
BeeWare tutorial
- Android's preferred language of implementation is Java.
So if you want to write an Android application in Python, you need to have a way to run your Python code on a Java Virtual Machine.
This is what VOC does.
VOC is a transpiler - it takes Python source code, compiles it to CPython Bytecode, and then transpiles that bytecode into Java-compatible bytecode.
VOC also allows you to access native Java objects as if they were Python objects,
implement Java interfaces with Python classes, and subclass Java classes with Python classes.
Using this, you can write an Android application directly against the native Android APIs.
Once you've written your native Android application, you can use Briefcase
to package your Python code as an Android application.
StackOverflow -
dead end Dec. 2018
- Kotlin is now the preferred language for Android development.
- Kivy
- Chaquopy - integrates with the Android build system, it provides a python API for all Android features.
To quote the site "The complete Android API and user interface toolkit are directly at your disposal."
Gemini
Input :
escriu una app per android que rebi dades de la pantalla i ho envii a un servidor via REST
Output :
// MainActivity.kt
package com.example.screencaptureapp
import android.Manifest
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.graphics.PixelFormat
import android.hardware.display.DisplayManager
import android.media.Image
import android.media.ImageReader
import android.media.projection.MediaProjection
import android.media.projection.MediaProjectionManager
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.util.DisplayMetrics
import android.util.Log
import android.view.Display
import android.view.View
import android.view.WindowManager
import android.widget.Button
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import com.google.gson.Gson
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import java.io.ByteArrayOutputStream
import java.io.IOException
import java.nio.ByteBuffer
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
// Permisos necessaris
private const val PERMISSION_REQUEST_CODE = 100
private const val MEDIA_PROJECTION_REQUEST_CODE = 200
private val REQUIRED_PERMISSIONS = arrayOf(
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.INTERNET, // Afegit el permís d'Internet
Manifest.permission.ACCESS_NETWORK_STATE // Afegit el permís per comprovar l'estat de la xarxa
)
class MainActivity : AppCompatActivity() {
// Declaració de variables
private var mediaProjectionManager: MediaProjectionManager? = null
private var mediaProjection: MediaProjection? = null
private var imageReader: ImageReader? = null
private var handler: Handler? = null
private var display: Display? = null
private var windowManager: WindowManager? = null
private var densityDpi = 0
private var screenWidth = 0
private var screenHeight = 0
private lateinit var captureButton: Button
private lateinit var resultTextView: TextView
private var isCapturing = false
private val serverUrl = "http://your-server-address/upload" // Reemplaça amb la teva URL del servidor
private val httpClient = OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS) // Augmenta el timeout de connexió
.readTimeout(30, TimeUnit.SECONDS) // Augmenta el timeout de lectura
.writeTimeout(30, TimeUnit.SECONDS) // Augmenta el timeout d'escriptura
.build()
private val gson = Gson()
private val executor = Executors.newSingleThreadExecutor() // Utilitza un únic fil per a les operacions de xarxa
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Inicialització de variables i obtenció de serveis del sistema
captureButton = findViewById(R.id.captureButton)
resultTextView = findViewById(R.id.resultTextView)
mediaProjectionManager = getSystemService(Context.MEDIA_PROJECTION_SERVICE) as MediaProjectionManager
windowManager = getSystemService(Context.WINDOW_SERVICE) as WindowManager
display = windowManager?.defaultDisplay
// Obtenció de les mètriques de la pantalla
val metrics = DisplayMetrics()
display?.getRealMetrics(metrics) // Utilitza getRealMetrics per obtenir la resolució real
densityDpi = metrics.densityDpi
screenWidth = metrics.widthPixels
screenHeight = metrics.heightPixels
// Inicialització del handler per a la captura de pantalla
handler = Handler(Looper.getMainLooper())
// Configuració del listener del botó de captura
captureButton.setOnClickListener {
if (isCapturing) {
stopCapture()
captureButton.text = "Start Capture" // Canvia el text del botó
} else {
startCapture()
captureButton.text = "Stop Capture" // Canvia el text del botó
}
}
// Comprovació i sol·licitud de permisos
if (!checkPermissions()) {
requestPermissions()
} else {
// Si els permisos ja estan concedits, inicialitza la captura de pantalla
// Això és important per al flux on l'usuari ja ha concedit permisos anteriorment.
prepareMediaProjection()
}
}
// Funció per comprovar si tots els permisos necessaris estan concedits
private fun checkPermissions(): Boolean {
for (permission in REQUIRED_PERMISSIONS) {
if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
return false
}
}
return true
}
// Funció per sol·licitar els permisos necessaris
private fun requestPermissions() {
ActivityCompat.requestPermissions(this, REQUIRED_PERMISSIONS, PERMISSION_REQUEST_CODE)
}
// Funció per inicialitzar la captura de pantalla
private fun startCapture() {
if (mediaProjection == null) {
prepareMediaProjection() // Assegura que mediaProjection està inicialitzat
return
}
// Lógica per iniciar la captura de pantalla
createImageReader()
startCaptureLoop()
isCapturing = true
}
private fun stopCapture() {
isCapturing = false;
handler?.removeCallbacksAndMessages(null); // Important: Remove any pending posts.
if (imageReader != null) {
imageReader?.close()
}
if (mediaProjection != null) {
mediaProjection?.stop()
}
imageReader = null;
mediaProjection = null;
}
// Funció per preparar la projecció de mitjans
private fun prepareMediaProjection() {
if (mediaProjectionManager != null) {
val captureIntent = mediaProjectionManager?.createScreenCaptureIntent()
if (captureIntent != null) {
startActivityForResult(captureIntent, MEDIA_PROJECTION_REQUEST_CODE)
} else {
Toast.makeText(this, "Failed to create screen capture intent", Toast.LENGTH_SHORT).show()
}
} else {
Toast.makeText(this, "MediaProjectionManager is null", Toast.LENGTH_SHORT).show()
}
}
// Funció per crear l'ImageReader
private fun createImageReader() {
imageReader = ImageReader.newInstance(
screenWidth, screenHeight, PixelFormat.RGBA_8888, 2
) // Increased maxImages to 2
}
// Funció per iniciar el bucle de captura de pantalla
private fun startCaptureLoop() {
handler?.post(object : Runnable {
override fun run() {
if (!isCapturing) {
return // Stop if not capturing
}
captureScreen()
handler?.postDelayed(this, 1000) // Captura cada segon (1000ms)
}
})
}
// Funció per capturar la pantalla
private fun captureScreen() {
if (mediaProjection != null && imageReader != null) {
try {
mediaProjection?.acquireNextImage(imageReader!!, 0)?.let { image ->
// Utilitzar un fil per a la conversió a bitmap i enviament
executor.execute {
val bitmap = imageToBitmap(image)
image.close() // Important: Close the image after use
if (bitmap != null) {
sendData(bitmap)
}
}
}
} catch (e: Exception) {
Log.e("CaptureError", "Error capturing or processing image: ${e.message}")
e.printStackTrace() // Print the stack trace to get detailed error information.
runOnUiThread {
resultTextView.text = "Error: ${e.message}"
}
}
} else {
Log.e("CaptureError", "MediaProjection or ImageReader is null")
runOnUiThread {
resultTextView.text = "Error: MediaProjection or ImageReader is null"
}
}
}
// Funció per convertir Image a Bitmap
private fun imageToBitmap(image: Image): Bitmap? {
val plane = image.planes[0]
val buffer = plane.buffer
val pixelStride = plane.pixelStride
val rowStride = plane.rowStride
val rowPadding = rowStride - image.width * pixelStride
val bitmap = Bitmap.createBitmap(
image.width, image.height, Bitmap.Config.ARGB_8888
)
bitmap.copyPixelsFromBuffer(buffer)
return bitmap
}
// Funció per enviar les dades al servidor
private fun sendData(bitmap: Bitmap) {
if (!isNetworkAvailable()) {
Log.e("NetworkError", "No network connection")
runOnUiThread {
resultTextView.text = "Error: No network connection"
}
return
}
val stream = ByteArrayOutputStream()
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream) // Compress as PNG
val byteArray = stream.toByteArray()
val requestBody = byteArray.toRequestBody("image/png".toMediaTypeOrNull()) // Set correct MIME type
val request = Request.Builder()
.url(serverUrl)
.post(requestBody)
.build()
try {
val response = httpClient.newCall(request).execute()
val responseBody = response.body?.string() // Get the response body
if (response.isSuccessful) {
Log.d("SendData", "Data sent successfully. Response: $responseBody")
runOnUiThread {
resultTextView.text = "Data sent successfully. Response: $responseBody"
}
} else {
Log.e("SendData", "Failed to send data. Response Code: ${response.code}, Response Body: $responseBody")
runOnUiThread {
resultTextView.text = "Failed to send data. Code: ${response.code}, Response: $responseBody"
}
}
response.close() // Close the response
stream.close()
} catch (e: IOException) {
Log.e("SendData", "Error sending data: ${e.message}")
e.printStackTrace()
runOnUiThread {
resultTextView.text = "Error sending data: ${e.message}"
}
}
}
private fun isNetworkAvailable(): Boolean {
val connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val network = connectivityManager.activeNetwork ?: return false
val activeNetwork = connectivityManager.getNetworkCapabilities(network) ?: return false
return when {
activeNetwork.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true
activeNetwork.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true
activeNetwork.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> true
else -> false
}
} else {
// Deprecated method, but still needed for older devices.
val networkInfo = connectivityManager.activeNetworkInfo
return networkInfo != null && networkInfo.isConnected
}
}
// Funció per alliberar recursos
override fun onDestroy() {
super.onDestroy()
handler?.removeCallbacksAndMessages(null) // Clear handler callbacks
executor.shutdown() // Shutdown the executor
if (mediaProjection != null) {
mediaProjection?.stop()
mediaProjection = null
}
if (imageReader != null) {
imageReader?.close()
imageReader = null
}
}
// Funció per gestionar el resultat de la sol·licitud de projecció de mitjans
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == MEDIA_PROJECTION_REQUEST_CODE) {
if (resultCode == RESULT_OK && data != null) {
try {
mediaProjection = mediaProjectionManager?.getMediaProjection(resultCode, data)
if (mediaProjection != null) {
// Inicialitza ImageReader i comença la captura només si mediaProjection té èxit
createImageReader() // Inicialitza el ImageReader aquí
startCapture()
isCapturing = true;
captureButton.text = "Stop Capture"
} else {
Toast.makeText(this, "Failed to get MediaProjection", Toast.LENGTH_SHORT).show()
resultTextView.text = "Error: Failed to get MediaProjection"
}
} catch (e: Exception) {
Log.e("ProjectionError", "Error getting MediaProjection: ${e.message}")
e.printStackTrace()
Toast.makeText(this, "Error: ${e.message}", Toast.LENGTH_SHORT).show()
resultTextView.text = "Error: ${e.message}"
}
} else {
Toast.makeText(this, "User cancelled MediaProjection permission", Toast.LENGTH_SHORT).show()
resultTextView.text = "Error: User cancelled MediaProjection permission"
}
} else if (requestCode == PERMISSION_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
// Fer alguna cosa si els permisos són concedits
prepareMediaProjection()
} else {
Toast.makeText(this, "Permissions not granted", Toast.LENGTH_SHORT).show()
resultTextView.text = "Error: Permissions not granted"
}
}
}
// Per assegurar-nos que alliberem els recursos adequadament quan l'activitat es deté.
override fun onStop() {
super.onStop()
if (isCapturing) {
stopCapture()
captureButton.text = "Start Capture"
}
}
}
Explanation :
Here's a breakdown of the code:
Permissions: The app requests necessary permissions (storage, internet, and network state) at runtime.
UI Setup:
activity_main.xml: Defines the layout with a button to start/stop capture and a text view for results.
The code initializes captureButton and resultTextView.
Screen Capture:
MediaProjectionManager and MediaProjection: Used to capture the screen.
ImageReader: Captures screen frames as Image objects. The imageReader is initialized with the screen dimensions.
The captureScreen() function acquires the next available image from the ImageReader, converts it to a Bitmap, and sends it to the server. The image.close() method is crucial to release the Image resources.
The startCaptureLoop() method repeatedly calls captureScreen() every second using a Handler.
Bitmap Conversion: The imageToBitmap() function converts the Image object from the ImageReader into a Bitmap.
Data Sending:
sendData():
Converts the Bitmap to a PNG byte array.
Sends the data to the server using an HTTP POST request with OkHttpClient. The MediaType is set to image/png.
Handles the server response and updates the UI with the result.
Checks for network connectivity before sending data.
Server Interaction:
The serverUrl variable should be replaced with your server's endpoint.
The server needs to be set up to receive the image data and process it accordingly. The server should expect a POST request with the image data in the body.
Error Handling: The code includes error handling for various operations, such as:
Permission issues.
Media projection errors.
Network connectivity problems.
Server communication failures.
Cleanup: The onDestroy() method releases resources, including stopping the MediaProjection, closing the ImageReader, and shutting down the executor. The handler.removeCallbacksAndMessages(null) call is added to prevent memory leaks.
Network Check: The isNetworkAvailable() function checks if the device is connected to a network before attempting to send data. It handles both modern and deprecated methods for checking network connectivity.
Background Thread: The image conversion and sending to server are done on a background thread using Executors.newSingleThreadExecutor() to prevent blocking the main thread.
Activity Result: The onActivityResult method handles the result of the MediaProjectionManager.createScreenCaptureIntent() call.
Permissions: The checkPermissions() and requestPermissions() methods check for and request the necessary permissions.
Resource Management: The image.close() method is used to free up resources after the image has been processed. The response.close() method is used to close the HTTP response body. The stream.close() method is used to close the byte array output stream.
User Feedback: The resultTextView is updated on the main thread using runOnUiThread to display the result of the operation to the user. Toast messages are also used for short notifications.
Final :
Remember to replace "http://your-server-address/upload" with your actual server URL.
How to debug an App crash
- on Android, install "Logcat Reader"
- grant the permissions :
- if you phone is "rooted", select "Rooted", otherwise "Manual" -> we shall use "Manual"
- install ADB on your computer (Android Debug Bridge)
- connect your phone via USB with USB debugging enabled
- run this command:
adb shell pm grant com.nolanlawson.logcat android.permission.READ_LOGS
- restart the app → you should now see full system log output
- clear the old logs
- produce the crash
- search the logs for "Tempest" text
Voice typing
- only works using "Chrome"
- "settings" + "additional settings" + "Language and input" + "Manage keyboards" + "Google Voice Typing" must be "on"
- "Gboard" app settings must have permission to access the microphone (while using the app) - reboot is mandatory
Prova :
- open Youtube video, as Joan Rivers
- open Google Docs on Android phone
pica els 4 quadradets i escull "Veu" (icona de microfon)
Toca aquesta icona. S'obrirà un menú amb diverses eines. Si veus el micròfon allà, el pots arrossegar cap a la barra principal per tenir-lo sempre a mà.
Missatges de PC
Els missatges d'alerta de Protecció Civil al mòbil a Espanya funcionen a través del sistema ES-Alert, també conegut com a "Public Warning System" o "Alertes Públiques".
Redmi Note 10 Pro
- Android version 13
- open "Settings"
- search for "Wireless emergency alerts" (under "Safety and emergency")
- disable
Samsung S8 tablet
- Android version 14
- open "Settings"
- search for "Wireless emergency alerts" (under "Safety and emergency")
- disable
Redmi Note 12 5G
- Android version 15
- open "Settings"
- search for "Alertes d'emergencia sense fil" (under "Seguretat i emergencia")
- disable
Find Hub network
Your Android device stores encrypted recent locations with Google
and participates in the Find Hub network,
a crowdsourced network of Android devices
that uses end-to-end encrypted location information to help Android users find their lost devices.
support Google
Per gestionar la participació del dispositiu, ves a
Configuració > Google > Tots els serveis (si hi ha pestanyes) > Localitzador > Cerca els teus dispositius sense connexió
Dubtes de Android
- what is a gradle [***] - gradle is a build system
- com veure el font de una pagina HTML en un Android ?
prefix the URL in the address bar with view-source:, i.e. "view-source:http://google.com" -
stack exchange
- "this app doesn't allow taking screenshots" -> com es pot fer ?
lo mes fàcil: amb un altre telefon !