javamethod to use the stepcounter
Posted: Tue Dec 09, 2025 3:50 pm
As mentioned in the scoped storage thread various sensors may be utilized through custom java code.
viewtopic.php?t=4263
Here is a small example of accessing the stepcounter.
Note that the stepcounter is not actually a sensor, but rather an internal counter that can be accessed. Android itself will use the stepdetector sensor and update the counter.
In my first attemts at this I did try to use the stepdetector sensor directly, but failed to get any useful data from it. This code below will read the data from the counter instead.
It is claimed to be counting the steps since last reboot. I am not sure how it really works since I found it only seem to count steps while the app is running. Also it is a "slow starter" so you need to walk a bit before it starts to count.
Hollywood code
You will probably need to add this into your AndoidManifest.xml:
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />
Here is a version of the HollywoodDelegate.java file modified to work with the stepcounter.
Modify the first line to your own package name.
viewtopic.php?t=4263
Here is a small example of accessing the stepcounter.
Note that the stepcounter is not actually a sensor, but rather an internal counter that can be accessed. Android itself will use the stepdetector sensor and update the counter.
In my first attemts at this I did try to use the stepdetector sensor directly, but failed to get any useful data from it. This code below will read the data from the counter instead.
It is claimed to be counting the steps since last reboot. I am not sure how it really works since I found it only seem to count steps while the app is running. Also it is a "slow starter" so you need to walk a bit before it starts to count.
Hollywood code
Code: Select all
; Step Counter Test
@DISPLAY {Title = "Step Counter Test", ScaleMode = #SCALEMODE_AUTO, FitScale = True, SmoothScale = True, HideTitleBar = True}
Const #SENSOR_STEP_COUNTER = 19
Global initialSteps = 0
Global stepsStarted = False
Function p_StepCounterTest()
; Check and request activity recognition permission
hasPerm = CallJavaMethod("hasActivityRecognitionPermission", {ReturnType=#BOOLEAN})
If Not hasPerm
TextOut(10, 30, "Need Activity Recognition permission...")
CallJavaMethod("requestActivityRecognitionPermission", {ReturnType=#VOID})
p_waiting(50)
Return
EndIf
; Check if device has step counter
hasCounter = CallJavaMethod("hasSensor", {ReturnType=#BOOLEAN}, #INTEGER, #SENSOR_STEP_COUNTER)
If hasCounter
TextOut(10, 30, "Step Counter available!")
; Start monitoring (only once!)
; When starting the app, force a fresh step counter read
If Not stepsStarted
; Stop any existing sensor first
CallJavaMethod("stopSensor", {ReturnType=#VOID}, #INTEGER, #SENSOR_STEP_COUNTER)
p_waiting(5)
; Start fresh
CallJavaMethod("startSensor", {ReturnType=#BOOLEAN}, #INTEGER, #SENSOR_STEP_COUNTER)
TextOut(10, 60, "Step Counter started...")
; Wait longer for fresh data and read multiple times
p_waiting(100)
; Try reading the step counter value multiple times
For i = 1 To 3
stepCounterValues$ = CallJavaMethod("getSensorValues", {ReturnType=#STRING}, #INTEGER, #SENSOR_STEP_COUNTER)
If stepCounterValues$ <> "No data" And FindStr(stepCounterValues$, ":") > 0
Local n = FindStr(stepCounterValues$, ":")
Local prefix$ = LeftStr(stepCounterValues$, n+1)
Local valueStr$ = ReplaceStr(stepCounterValues$, prefix$, "")
initialSteps = ToNumber(valueStr$)
Break
EndIf
p_waiting(25)
Next
stepsStarted = True
EndIf
; Get current step counter value
stepCounterValues$ = CallJavaMethod("getSensorValues", {ReturnType=#STRING}, #INTEGER, #SENSOR_STEP_COUNTER)
If stepCounterValues$ <> "No data" And FindStr(stepCounterValues$, ":") > 0
Local n = FindStr(stepCounterValues$, ":")
Local prefix$ = LeftStr(stepCounterValues$, n+1)
Local valueStr$ = ReplaceStr(stepCounterValues$, prefix$, "")
currentSteps = ToNumber(valueStr$)
stepsSinceStart = currentSteps - initialSteps
TextOut(10, 90, "Total steps (since reboot): " .. currentSteps)
TextOut(10, 120, "Steps since app start: " .. stepsSinceStart)
TextOut(10, 150, "Walk normally to count steps...")
Else
TextOut(10, 90, "Waiting for step data...")
TextOut(10, 120, "Walk a few steps to initialize")
EndIf
Else
TextOut(10, 30, "No Step Counter available on this device")
EndIf
EndFunction
Function p_HandlerFunc(msg)
Switch(msg.Action)
Case "OnMouseDown":
sel = SystemRequest("Quit?", "Quit step counting?", "Yes|No")
Switch sel
Case 1:
CallJavaMethod("stopSensor", {ReturnType=#VOID}, #INTEGER, #SENSOR_STEP_COUNTER)
p_waiting(10)
quitnow = True
EndSwitch
EndSwitch
EndFunction
InstallEventHandler({OnMouseDown = p_HandlerFunc})
SetFillStyle(#FILLCOLOR)
SetFont(#SANS, 20)
Function p_waiting(times)
For i = 1 To times
CheckEvent
Wait(1)
Next
EndFunction
Repeat
Box(0,0,700,600, #BLACK)
TextOut(10, 0, "=== STEP COUNTER TEST ===")
p_StepCounterTest()
p_waiting(50) ; Update once per second to save battery
Until quitnow
End
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />
Here is a version of the HollywoodDelegate.java file modified to work with the stepcounter.
Modify the first line to your own package name.
Code: Select all
package com.amy66dev.stepcounter;
// Core Android functionality
import android.content.Intent; // Camera, GPS, Sharing, Permissions
import android.net.Uri; // Camera, Sharing, File operations
import android.os.Build; // Version checks throughout
import android.os.Environment; // File operations, SD card, Storage
import android.util.Log; // Logging throughout
import android.app.Activity; // Base class, context
// Permissions and hardware features
import android.Manifest; // Camera, Location permissions
import android.content.pm.PackageManager; // Permission checking
import android.location.Location; // GPS functionality
import android.location.LocationManager; // GPS functionality
import android.media.MediaScannerConnection; // Camera file scanning
import android.os.Vibrator; // Vibration (currently commented out)
import android.provider.MediaStore; // Camera, MediaStore operations
import android.widget.Toast; // Toast messages (optional)
import android.content.Context; // System services
import android.content.ContentValues; // MediaStore operations
import android.media.MediaScannerConnection; // Camera file scanning (duplicate)
import android.content.ClipboardManager; // Clipboard functions
import android.content.ClipData; // Clipboard functions
import android.view.WindowManager; // Keep Screen On
// AndroidX libraries
import androidx.annotation.Nullable; // Nullable annotations
import androidx.core.app.ActivityCompat; // Permission requests
import androidx.core.content.ContextCompat; // Permission checking
import androidx.core.content.FileProvider; // File sharing
// Java utilities
import java.text.SimpleDateFormat; // Camera timestamp
import java.util.Date; // Camera timestamp
import java.util.Locale; // String formatting
import java.util.List; // GPS location providers
import java.util.ArrayList; // Multiple permissions requests
// File I/O operations
import java.io.File; // All file operations
import java.io.FileInputStream; // File reading, copy operations
import java.io.FileOutputStream; // File writing, copy operations
import java.io.IOException; // Exception handling
import java.io.BufferedReader; // File reading
import java.io.InputStreamReader; // File reading
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import java.util.Map;
import java.util.HashMap;
/**
* HollywoodDelegate - Direct external storage file utilities.
* Must be included as Custom Code in the Hollywood APK Compiler.
*/
public class HollywoodDelegate extends HollywoodActivity {
private static final String TAG = "HollywoodDelegate";
private SensorManager sensorManager;
// --- Add SD card helper HERE (inside the class, not before imports)
private File getExternalSdCard() {
File[] externalDirs = getApplicationContext().getExternalFilesDirs(null);
if (externalDirs != null && externalDirs.length > 1) {
for (File dir : externalDirs) {
if (dir != null && Environment.isExternalStorageRemovable(dir)) {
return dir.getParentFile().getParentFile().getParentFile().getParentFile();
}
}
}
return null;
}
// --- PERMISSION METHODS ---
// Check if MANAGE_EXTERNAL_STORAGE is granted
public boolean hasAllFilesAccess() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
return Environment.isExternalStorageManager();
}
return true; // On Android 10 and below, WRITE_EXTERNAL_STORAGE is enough
}
// Open settings page for granting MANAGE_EXTERNAL_STORAGE
public void requestAllFilesAccess() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
try {
Intent intent = new Intent(android.provider.Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivity(intent);
} catch (Exception e) {
Intent intent = new Intent(android.provider.Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
startActivity(intent);
}
}
}
// --- FOLDER METHODS ---
// Check if folder exists
public boolean folderExists(String folderName) {
try {
File dir = new File(Environment.getExternalStorageDirectory(), folderName);
return dir.exists() && dir.isDirectory();
} catch (Exception e) {
Log.e(TAG, "Error checking folder existence: " + e.getMessage());
return false;
}
}
// Create folder
public boolean createFolder(String folderName) {
try {
File dir = new File(Environment.getExternalStorageDirectory(), folderName);
if (!dir.exists()) {
if (!dir.mkdirs()) return false;
}
return true;
} catch (Exception e) {
Log.e(TAG, "createFolder failed: " + e.getMessage());
return false;
}
}
// Delete folder recursively
public boolean deleteFolder(String folderName) {
try {
File dir = new File(Environment.getExternalStorageDirectory(), folderName);
if (!dir.exists() || !dir.isDirectory()) return false;
return deleteRecursive(dir);
} catch (Exception e) {
Log.e(TAG, "deleteFolder failed: " + e.getMessage());
return false;
}
}
private boolean deleteRecursive(File fileOrDirectory) {
if (fileOrDirectory.isDirectory()) {
File[] children = fileOrDirectory.listFiles();
if (children != null) {
for (File child : children) deleteRecursive(child);
}
}
return fileOrDirectory.delete();
}
// --- FILE METHODS ---
// Check if file exists AND is readable
public boolean fileExists(String folderName, String fileName) {
try {
File file = new File(new File(Environment.getExternalStorageDirectory(), folderName), fileName);
boolean exists = file.exists() && file.isFile();
boolean readable = exists && file.canRead();
Log.i(TAG, "fileExists: " + folderName + "/" + fileName + " - exists: " + exists + ", readable: " + readable);
return exists && readable;
} catch (Exception e) {
Log.e(TAG, "fileExists failed: " + e.getMessage());
return false;
}
}
// Create or overwrite file
public boolean createFile(String folderName, String fileName, String content) {
try {
File dir = new File(Environment.getExternalStorageDirectory(), folderName);
if (!dir.exists() && !dir.mkdirs()) return false;
File file = new File(dir, fileName);
try (FileOutputStream fos = new FileOutputStream(file)) {
if (content != null) fos.write(content.getBytes("UTF-8"));
fos.flush();
}
return true;
} catch (Exception e) {
Log.e(TAG, "createFile failed: " + e.getMessage());
return false;
}
}
// Read entire file
public String readFile(String folderName, String fileName) {
try {
File file = new File(new File(Environment.getExternalStorageDirectory(), folderName), fileName);
if (!file.exists() || !file.canRead()) return "";
StringBuilder sb = new StringBuilder();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"))) {
String line;
while ((line = reader.readLine()) != null) {
sb.append(line).append("\n");
}
}
return sb.toString().trim();
} catch (Exception e) {
Log.e(TAG, "readFile failed: " + e.getMessage());
return "";
}
}
// Append to file
public boolean appendToFile(String folderName, String fileName, String content) {
try {
File file = new File(new File(Environment.getExternalStorageDirectory(), folderName), fileName);
if (!file.exists()) return createFile(folderName, fileName, content);
try (FileOutputStream fos = new FileOutputStream(file, true)) {
if (content != null) fos.write(content.getBytes("UTF-8"));
fos.flush();
}
return true;
} catch (Exception e) {
Log.e(TAG, "appendToFile failed: " + e.getMessage());
return false;
}
}
// Delete file
public boolean deleteFile(String folderName, String fileName) {
try {
File file = new File(new File(Environment.getExternalStorageDirectory(), folderName), fileName);
if (!file.exists()) return false;
return file.delete();
} catch (Exception e) {
Log.e(TAG, "deleteFile failed: " + e.getMessage());
return false;
}
}
// Read a specific line
public String readLineFromFile(String folderName, String fileName, int lineNumber) {
try {
File file = new File(new File(Environment.getExternalStorageDirectory(), folderName), fileName);
if (!file.exists() || !file.canRead()) return "";
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"))) {
String line;
int count = 0;
while ((line = reader.readLine()) != null) {
if (count == lineNumber) {
return line;
}
count++;
}
}
} catch (Exception e) {
Log.e(TAG, "readLineFromFile failed: " + e.getMessage());
}
return "";
}
// Count number of lines
public int getNumberOfLines(String folderName, String fileName) {
int count = 0;
try {
File file = new File(new File(Environment.getExternalStorageDirectory(), folderName), fileName);
if (!file.exists() || !file.canRead()) return 0;
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"))) {
while (reader.readLine() != null) count++;
}
} catch (Exception e) {
Log.e(TAG, "getNumberOfLines failed: " + e.getMessage());
}
return count;
}
// List files in folder (newline-separated)
public String listFilesInFolder(String folderName) {
try {
File dir = new File(Environment.getExternalStorageDirectory(), folderName);
if (!dir.exists() || !dir.isDirectory()) return "";
StringBuilder sb = new StringBuilder();
File[] files = dir.listFiles();
if (files != null) {
for (File f : files) {
sb.append(f.getName());
if (f.isDirectory()) sb.append(" (dir)");
sb.append("\n");
}
}
return sb.toString().trim();
} catch (Exception e) {
Log.e(TAG, "listFilesInFolder failed: " + e.getMessage());
return "";
}
}
// Copy internal -> external
public boolean copyFileToExternal(String internalRelativePath, String folderName, String fileName) {
try {
File src = new File(getFilesDir(), internalRelativePath);
if (!src.exists()) return false;
File dst = new File(new File(Environment.getExternalStorageDirectory(), folderName), fileName);
if (!dst.getParentFile().exists()) dst.getParentFile().mkdirs();
try (FileInputStream in = new FileInputStream(src);
FileOutputStream out = new FileOutputStream(dst)) {
byte[] buf = new byte[4096];
int r;
while ((r = in.read(buf)) > 0) out.write(buf, 0, r);
out.flush();
}
return true;
} catch (Exception e) {
Log.e(TAG, "copyFileToExternal failed: " + e.getMessage());
return false;
}
}
// Copy external -> internal
public boolean copyFileFromExternal(String folderName, String fileName, String internalRelativePath) {
try {
File src = new File(new File(Environment.getExternalStorageDirectory(), folderName), fileName);
if (!src.exists() || !src.canRead()) return false;
File dst = new File(getFilesDir(), internalRelativePath);
if (!dst.getParentFile().exists()) dst.getParentFile().mkdirs();
try (FileInputStream in = new FileInputStream(src);
FileOutputStream out = new FileOutputStream(dst)) {
byte[] buf = new byte[4096];
int r;
while ((r = in.read(buf)) > 0) out.write(buf, 0, r);
out.flush();
}
return true;
} catch (Exception e) {
Log.e(TAG, "copyFileFromExternal failed: " + e.getMessage());
return false;
}
}
// --- Create folder on SD card ---
public boolean createFolderOnSDCard(String folderName) {
File sdRoot = getExternalSdCard();
if (sdRoot == null) return false;
File folder = new File(sdRoot, folderName);
return folder.exists() || folder.mkdirs();
}
// --- Create/overwrite file on SD card ---
public boolean createFileOnSDCard(String folderName, String fileName, String content) {
File sdRoot = getExternalSdCard();
if (sdRoot == null) return false;
try {
File folder = new File(sdRoot, folderName);
if (!folder.exists()) folder.mkdirs();
File file = new File(folder, fileName);
try (FileOutputStream fos = new FileOutputStream(file, false)) {
fos.write(content.getBytes("UTF-8"));
fos.flush();
}
return true;
} catch (Exception e) {
Log.e(TAG, "Error writing file to SD card", e);
return false;
}
}
// --- Read file from SD card ---
public String readFileFromSDCard(String folderName, String fileName) {
File sdRoot = getExternalSdCard();
if (sdRoot == null) return "";
try {
File file = new File(new File(sdRoot, folderName), fileName);
if (!file.exists() || !file.canRead()) return "";
StringBuilder sb = new StringBuilder();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"))) {
String line;
while ((line = reader.readLine()) != null) {
sb.append(line).append("\n");
}
}
return sb.toString().trim();
} catch (Exception e) {
Log.e(TAG, "Error reading file from SD card", e);
return "";
}
}
// --- Delete file from SD card ---
public boolean deleteFileFromSDCard(String folderName, String fileName) {
File sdRoot = getExternalSdCard();
if (sdRoot == null) return false;
File file = new File(new File(sdRoot, folderName), fileName);
return file.exists() && file.delete();
}
// --- SD CARD OPERATIONS ---
// Check if folder exists on SD card
public boolean folderExistsOnSDCard(String folderName) {
File sdCard = getExternalSdCard();
if (sdCard == null) return false;
File dir = new File(sdCard, folderName);
return dir.exists() && dir.isDirectory();
}
// Recursive delete helper for SD card
private boolean deleteRecursiveFromSDCard(File fileOrDirectory) {
if (fileOrDirectory.isDirectory()) {
File[] children = fileOrDirectory.listFiles();
if (children != null) {
for (File child : children) {
deleteRecursiveFromSDCard(child);
}
}
}
return fileOrDirectory.delete();
}
// Delete folder from SD card
public boolean deleteFolderFromSDCard(String folderName) {
File sdCard = getExternalSdCard();
if (sdCard == null) return false;
File dir = new File(sdCard, folderName);
if (dir.exists() && dir.isDirectory()) {
return deleteRecursiveFromSDCard(dir);
}
return false;
}
// Check if a file exists on SD card
public boolean fileExistsOnSDCard(String folderName, String fileName) {
File sdCard = getExternalSdCard();
if (sdCard == null) return false;
File file = new File(new File(sdCard, folderName), fileName);
boolean exists = file.exists() && file.isFile();
boolean readable = exists && file.canRead();
Log.i(TAG, "fileExistsOnSDCard: " + folderName + "/" + fileName + " - exists: " + exists + ", readable: " + readable);
return exists && readable;
}
// Append to file on SD card
public boolean appendToFileOnSDCard(String folderName, String fileName, String content) {
File sdCard = getExternalSdCard();
if (sdCard == null) return false;
File dir = new File(sdCard, folderName);
if (!dir.exists()) dir.mkdirs();
File file = new File(dir, fileName);
try (FileOutputStream fos = new FileOutputStream(file, true)) {
fos.write(content.getBytes("UTF-8"));
fos.flush();
return true;
} catch (Exception e) {
Log.e(TAG, "appendToFileOnSDCard failed", e);
return false;
}
}
// Read a specific line from a file on SD card
public String readLineFromFileOnSDCard(String folderName, String fileName, int lineNumber) {
File sdCard = getExternalSdCard();
if (sdCard == null) return "";
File file = new File(new File(sdCard, folderName), fileName);
if (!file.exists() || !file.canRead()) return "";
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"))) {
String line;
int count = 0;
while ((line = reader.readLine()) != null) {
if (count == lineNumber) return line;
count++;
}
} catch (Exception e) {
Log.e(TAG, "readLineFromFileOnSDCard failed", e);
}
return "";
}
// Get number of lines in a file on SD card
public int getNumberOfLinesOnSDCard(String folderName, String fileName) {
File sdCard = getExternalSdCard();
if (sdCard == null) return 0;
File file = new File(new File(sdCard, folderName), fileName);
if (!file.exists() || !file.canRead()) return 0;
int count = 0;
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"))) {
while (reader.readLine() != null) count++;
} catch (Exception e) {
Log.e(TAG, "getNumberOfLinesOnSDCard failed", e);
}
return count;
}
// List files in a folder on SD card
public String listFilesInFolderOnSDCard(String folderName) {
File sdCard = getExternalSdCard();
if (sdCard == null) return "";
File dir = new File(sdCard, folderName);
if (!dir.exists() || !dir.isDirectory()) return "";
StringBuilder sb = new StringBuilder();
File[] files = dir.listFiles();
if (files != null) {
for (File f : files) {
sb.append(f.getName());
if (f.isDirectory()) sb.append(" (dir)");
sb.append("\n");
}
}
return sb.toString().trim();
}
// Copy file from internal storage -> SD card
public boolean copyFileToSDCard(String internalRelativePath, String folderName, String fileName) {
File sdCard = getExternalSdCard();
if (sdCard == null) return false;
File src = new File(getFilesDir(), internalRelativePath);
if (!src.exists()) return false;
File dst = new File(new File(sdCard, folderName), fileName);
dst.getParentFile().mkdirs();
try (FileInputStream in = new FileInputStream(src);
FileOutputStream out = new FileOutputStream(dst)) {
byte[] buf = new byte[4096];
int r;
while ((r = in.read(buf)) > 0) out.write(buf, 0, r);
out.flush();
return true;
} catch (Exception e) {
Log.e(TAG, "copyFileToSDCard failed", e);
return false;
}
}
// Copy file from SD card -> internal storage
public boolean copyFileFromSDCard(String folderName, String fileName, String internalRelativePath) {
File sdCard = getExternalSdCard();
if (sdCard == null) return false;
File src = new File(new File(sdCard, folderName), fileName);
if (!src.exists() || !src.canRead()) return false;
File dst = new File(getFilesDir(), internalRelativePath);
dst.getParentFile().mkdirs();
try (FileInputStream in = new FileInputStream(src);
FileOutputStream out = new FileOutputStream(dst)) {
byte[] buf = new byte[4096];
int r;
while ((r = in.read(buf)) > 0) out.write(buf, 0, r);
out.flush();
return true;
} catch (Exception e) {
Log.e(TAG, "copyFileFromSDCard failed", e);
return false;
}
}
// Copy file from External (primary shared storage) -> SD card
public boolean copyFromExternalToSDCard(String externalFolder, String externalFile, String sdFolder, String sdFile) {
File external = Environment.getExternalStorageDirectory();
if (external == null) return false;
File src = new File(new File(external, externalFolder), externalFile);
if (!src.exists() || !src.canRead()) return false;
File sdCard = getExternalSdCard();
if (sdCard == null) return false;
File dst = new File(new File(sdCard, sdFolder), sdFile);
dst.getParentFile().mkdirs();
try (FileInputStream in = new FileInputStream(src);
FileOutputStream out = new FileOutputStream(dst)) {
byte[] buf = new byte[4096];
int r;
while ((r = in.read(buf)) > 0) out.write(buf, 0, r);
out.flush();
return true;
} catch (Exception e) {
Log.e(TAG, "copyFromExternalToSDCard failed", e);
return false;
}
}
// Copy file from SD card -> External (primary shared storage)
public boolean copyFromSDCardToExternal(String sdFolder, String sdFile, String externalFolder, String externalFile) {
File sdCard = getExternalSdCard();
if (sdCard == null) return false;
File src = new File(new File(sdCard, sdFolder), sdFile);
if (!src.exists() || !src.canRead()) return false;
File external = Environment.getExternalStorageDirectory();
if (external == null) return false;
File dst = new File(new File(external, externalFolder), externalFile);
dst.getParentFile().mkdirs();
try (FileInputStream in = new FileInputStream(src);
FileOutputStream out = new FileOutputStream(dst)) {
byte[] buf = new byte[4096];
int r;
while ((r = in.read(buf)) > 0) out.write(buf, 0, r);
out.flush();
return true;
} catch (Exception e) {
Log.e(TAG, "copyFromSDCardToExternal failed", e);
return false;
}
}
// ================================================================
// 📸 CAMERA CAPTURE (Complete Section)
// ================================================================
private String lastPhotoPath;
// Camera permission methods
public boolean hasCameraPermission() {
return ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
== PackageManager.PERMISSION_GRANTED;
}
public void requestCameraPermission() {
if (!hasCameraPermission()) {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.CAMERA},
2002
);
}
}
// Main camera method
public String openCamera() {
try {
// Check camera permission first
if (!hasCameraPermission()) {
Log.w(TAG, "Camera permission not granted");
return "camera_permission_denied";
}
// Check storage permission for saving photos
if (!hasAllFilesAccess()) {
Log.w(TAG, "Storage permission not granted");
return "storage_permission_denied";
}
// Use Pictures directory that Hollywood can access
File storageDir = new File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
"HollywoodPhotos"
);
if (!storageDir.exists()) storageDir.mkdirs();
// Create unique filename
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
String fileName = "photo_" + timeStamp + ".jpg";
File photoFile = new File(storageDir, fileName);
lastPhotoPath = photoFile.getAbsolutePath();
Log.i(TAG, "Photo will be saved to: " + lastPhotoPath);
// Use MediaStore to create the file entry
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.DISPLAY_NAME, fileName);
values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
values.put(MediaStore.Images.Media.DATA, lastPhotoPath);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
values.put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_PICTURES + "/HollywoodPhotos");
values.put(MediaStore.Images.Media.IS_PENDING, 1);
}
Uri imageUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
if (imageUri != null) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(intent, 2001);
Log.i(TAG, "Camera intent started");
return "camera_opened";
} else {
Log.e(TAG, "No camera app available");
lastPhotoPath = "";
return "no_camera_app";
}
} else {
Log.e(TAG, "Failed to create MediaStore entry");
lastPhotoPath = "";
return "media_store_error";
}
} catch (Exception e) {
Log.e(TAG, "openCamera failed: " + e.toString());
lastPhotoPath = "";
return "error: " + e.getMessage();
}
}
// Handle camera result
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 2001) {
if (resultCode == RESULT_OK) {
Log.i(TAG, "Camera returned OK, photo path: " + lastPhotoPath);
// Finalize MediaStore entry for Android Q+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && lastPhotoPath != null) {
try {
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.IS_PENDING, 0);
String selection = MediaStore.Images.Media.DATA + "=?";
String[] selectionArgs = new String[]{lastPhotoPath};
getContentResolver().update(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
values, selection, selectionArgs);
Log.i(TAG, "MediaStore entry finalized for: " + lastPhotoPath);
} catch (Exception e) {
Log.e(TAG, "Failed to finalize MediaStore entry", e);
}
}
// Trigger media scan so file is immediately visible to Hollywood
MediaScannerConnection.scanFile(this, new String[]{lastPhotoPath},
new String[]{"image/jpeg"}, null);
} else {
// Camera was cancelled
Log.i(TAG, "Camera was cancelled");
lastPhotoPath = "";
// Clean up pending file if camera was cancelled
if (lastPhotoPath != null) {
try {
File cancelledFile = new File(lastPhotoPath);
if (cancelledFile.exists()) {
cancelledFile.delete();
}
} catch (Exception e) {
Log.e(TAG, "Failed to delete cancelled photo", e);
}
lastPhotoPath = "";
}
}
}
}
// Get the photo path for Hollywood
public String getLastPhotoPath() {
if (lastPhotoPath != null) {
File photoFile = new File(lastPhotoPath);
if (photoFile.exists()) {
Log.i(TAG, "Returning existing photo path: " + lastPhotoPath);
return lastPhotoPath;
} else {
Log.w(TAG, "Photo file doesn't exist: " + lastPhotoPath);
return "";
}
}
return "";
}
// Check if camera is available on the device
public boolean isCameraAvailable() {
try {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
return intent.resolveActivity(getPackageManager()) != null;
} catch (Exception e) {
Log.e(TAG, "isCameraAvailable failed", e);
return false;
}
}
// ================================================================
// 📍 GPS LOCATION (Complete Section)
// ================================================================
// Location permission methods
public boolean hasLocationPermission() {
return ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED;
}
public void requestLocationPermission() {
if (!hasLocationPermission()) {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
2003
);
}
}
// Check if location services are enabled
public boolean isLocationEnabled() {
try {
LocationManager lm = (LocationManager) getSystemService(LOCATION_SERVICE);
if (lm == null) return false;
return lm.isProviderEnabled(LocationManager.GPS_PROVIDER) ||
lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
} catch (Exception e) {
Log.e(TAG, "isLocationEnabled failed", e);
return false;
}
}
// Get last known location (quick, cached location)
public String getLastKnownLocation() {
try {
// Check location permission
if (!hasLocationPermission()) {
Log.w(TAG, "Location permission not granted");
return "permission_denied";
}
LocationManager lm = (LocationManager) getSystemService(LOCATION_SERVICE);
if (lm == null) {
Log.e(TAG, "LocationManager is null");
return "service_unavailable";
}
// Check if location services are enabled
if (!isLocationEnabled()) {
Log.w(TAG, "Location services are disabled");
return "location_disabled";
}
// Try multiple location providers in order of preference
Location location = null;
List<String> providers = lm.getProviders(true);
for (String provider : providers) {
try {
Location loc = lm.getLastKnownLocation(provider);
if (loc != null) {
if (location == null || loc.getAccuracy() < location.getAccuracy()) {
location = loc;
}
}
} catch (SecurityException e) {
Log.w(TAG, "No permission for provider: " + provider);
} catch (Exception e) {
Log.w(TAG, "Error getting location from provider: " + provider, e);
}
}
if (location != null) {
double lat = location.getLatitude();
double lon = location.getLongitude();
float accuracy = location.getAccuracy();
long time = location.getTime();
String result = String.format(Locale.US, "%.6f,%.6f", lat, lon);
Log.i(TAG, "Location found: " + result + " (accuracy: " + accuracy + "m, time: " + time + ")");
return result;
} else {
Log.w(TAG, "No last known location available");
return "no_location_available";
}
} catch (SecurityException e) {
Log.e(TAG, "Location permission denied", e);
return "permission_denied";
} catch (Exception e) {
Log.e(TAG, "getLastKnownLocation failed", e);
return "error: " + e.getMessage();
}
}
// Get location with provider preference (GPS first, then network)
public String getCurrentLocation() {
try {
// Check location permission
if (!hasLocationPermission()) {
return "permission_denied";
}
LocationManager lm = (LocationManager) getSystemService(LOCATION_SERVICE);
if (lm == null) {
return "service_unavailable";
}
// Check if location services are enabled
if (!isLocationEnabled()) {
return "location_disabled";
}
// Try GPS first for highest accuracy
Location location = null;
if (lm.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
try {
location = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (location != null) {
Log.i(TAG, "Using GPS location");
}
} catch (SecurityException e) {
Log.w(TAG, "No permission for GPS provider");
}
}
// Fallback to network if GPS not available
if (location == null && lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
try {
location = lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (location != null) {
Log.i(TAG, "Using network location");
}
} catch (SecurityException e) {
Log.w(TAG, "No permission for network provider");
}
}
if (location != null) {
double lat = location.getLatitude();
double lon = location.getLongitude();
float accuracy = location.getAccuracy();
String result = String.format(Locale.US, "%.6f,%.6f", lat, lon);
Log.i(TAG, "Current location: " + result + " (accuracy: " + accuracy + "m)");
return result;
} else {
Log.w(TAG, "No current location available from any provider");
return "location_unavailable";
}
} catch (SecurityException e) {
Log.e(TAG, "Location permission denied", e);
return "permission_denied";
} catch (Exception e) {
Log.e(TAG, "getCurrentLocation failed", e);
return "error";
}
}
// Get detailed location info (returns comma-separated: lat,lon,accuracy,time,provider)
public String getDetailedLocation() {
try {
if (!hasLocationPermission()) {
return "permission_denied";
}
LocationManager lm = (LocationManager) getSystemService(LOCATION_SERVICE);
if (lm == null) return "service_unavailable";
if (!isLocationEnabled()) return "location_disabled";
Location bestLocation = null;
List<String> providers = lm.getProviders(true);
for (String provider : providers) {
try {
Location loc = lm.getLastKnownLocation(provider);
if (loc != null) {
if (bestLocation == null || loc.getAccuracy() < bestLocation.getAccuracy()) {
bestLocation = loc;
}
}
} catch (Exception e) {
// Continue with next provider
}
}
if (bestLocation != null) {
return String.format(Locale.US, "%.6f,%.6f,%.1f,%d,%s",
bestLocation.getLatitude(),
bestLocation.getLongitude(),
bestLocation.getAccuracy(),
bestLocation.getTime(),
bestLocation.getProvider()
);
} else {
return "no_location_available";
}
} catch (Exception e) {
Log.e(TAG, "getDetailedLocation failed", e);
return "error";
}
}
// Open location settings so user can enable location services
public void openLocationSettings() {
try {
Intent intent = new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);
} catch (Exception e) {
Log.e(TAG, "openLocationSettings failed", e);
// Fallback to general settings
try {
Intent intent = new Intent(android.provider.Settings.ACTION_SETTINGS);
startActivity(intent);
} catch (Exception e2) {
Log.e(TAG, "Fallback settings also failed", e2);
}
}
}
// ================================================================
// 💥 VIBRATION
// ================================================================
public void vibrateNow(int durationMs) {
try {
HollywoodActivity.vibrateDevice(durationMs);
} catch (Exception e) {
Log.e(TAG, "vibrateNow failed", e);
}
}
// ================================================================
// 📤 SHARE TEXT
// ================================================================
public void shareText(String message) {
try {
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, message);
sendIntent.setType("text/plain");
startActivity(Intent.createChooser(sendIntent, "Share via"));
} catch (Exception e) {
Log.e(TAG, "shareText", e);
}
}
// ================================================================
// 📤 SHARE IMAGE
// ================================================================
public void shareImage(String imagePath) {
try {
File imageFile = new File(imagePath);
if (!imageFile.exists()) {
Log.e(TAG, "Image file not found: " + imagePath);
return;
}
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("image/jpeg");
// Use YOUR existing FileProvider authority
Uri imageUri;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
imageUri = FileProvider.getUriForFile(this,
getPackageName() + ".fileprovider", // ← Changed to match your manifest
imageFile);
} else {
imageUri = Uri.fromFile(imageFile);
}
shareIntent.putExtra(Intent.EXTRA_STREAM, imageUri);
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(Intent.createChooser(shareIntent, "Share Photo"));
Log.i(TAG, "Sharing image: " + imagePath);
} catch (Exception e) {
Log.e(TAG, "shareImage failed", e);
}
}
// ================================================================
// 📋 CLIPBOARD FUNCTIONS
// ================================================================
// Copy text to clipboard
public void copyToClipboard(String text) {
try {
ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("Hollywood App", text);
clipboard.setPrimaryClip(clip);
Log.i(TAG, "Text copied to clipboard: " + text);
// Optional: Show a quick toast message
// Toast.makeText(this, "Copied to clipboard", Toast.LENGTH_SHORT).show();
} catch (Exception e) {
Log.e(TAG, "copyToClipboard failed", e);
}
}
// Get text from clipboard
public String getFromClipboard() {
try {
ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
if (clipboard.hasPrimaryClip()) {
ClipData.Item item = clipboard.getPrimaryClip().getItemAt(0);
String text = item.getText().toString();
Log.i(TAG, "Retrieved from clipboard: " + text);
return text;
}
} catch (Exception e) {
Log.e(TAG, "getFromClipboard failed", e);
}
return "";
}
// ================================================================
// 🔆 KEEP SCREEN ON
// ================================================================
private boolean screenShouldStayOn = false;
// Keep screen on - call this repeatedly if needed
public void keepScreenOn() {
try {
runOnUiThread(new Runnable() {
@Override
public void run() {
getWindow().addFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
screenShouldStayOn = true;
Log.i(TAG, "Screen keep-on flag set");
}
});
} catch (Exception e) {
Log.e(TAG, "keepScreenOn failed", e);
}
}
// Allow screen to turn off normally
public void allowScreenOff() {
try {
runOnUiThread(new Runnable() {
@Override
public void run() {
getWindow().clearFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
screenShouldStayOn = false;
Log.i(TAG, "Screen keep-on flag cleared");
}
});
} catch (Exception e) {
Log.e(TAG, "allowScreenOff failed", e);
}
}
// Force screen on and wake up device (requires WAKE_LOCK permission)
public void wakeUpScreen() {
try {
// This is more aggressive - wakes up the screen if it's off
android.view.Window window = getWindow();
window.addFlags(android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
android.view.WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON |
android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
Log.i(TAG, "Screen woken up and kept on");
} catch (Exception e) {
Log.e(TAG, "wakeUpScreen failed", e);
}
}
// Check if screen is currently kept on
public boolean isScreenKeptOn() {
try {
int flags = getWindow().getAttributes().flags;
return (flags & android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) != 0;
} catch (Exception e) {
Log.e(TAG, "isScreenKeptOn failed", e);
return false;
}
}
// ================================================================
// 📊 MULTI-SENSOR FUNCTIONS
// ================================================================
private Map<Integer, float[]> lastSensorValues = new HashMap<>();
private Map<Integer, SensorEventListener> sensorListeners = new HashMap<>();
// Check if specific sensor type is available
public boolean hasSensor(int sensorType) {
try {
if (sensorManager == null) {
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
}
if (sensorManager != null) {
Sensor sensor = sensorManager.getDefaultSensor(sensorType);
return sensor != null;
}
return false;
} catch (Exception e) {
Log.e(TAG, "hasSensor failed for type: " + sensorType, e);
return false;
}
}
// Get all available sensors
public String getAvailableSensors() {
try {
if (sensorManager == null) {
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
}
StringBuilder sb = new StringBuilder();
sb.append("Available Sensors:\n\n");
List<Sensor> sensors = sensorManager.getSensorList(Sensor.TYPE_ALL);
for (Sensor sensor : sensors) {
sb.append(sensor.getName()).append("\n");
sb.append(" Type: ").append(getSensorTypeName(sensor.getType())).append("\n");
sb.append(" Vendor: ").append(sensor.getVendor()).append("\n");
sb.append(" Power: ").append(sensor.getPower()).append(" mA\n");
sb.append(" Max Range: ").append(sensor.getMaximumRange()).append("\n");
sb.append(" Resolution: ").append(sensor.getResolution()).append("\n\n");
}
return sb.toString();
} catch (Exception e) {
Log.e(TAG, "getAvailableSensors failed", e);
return "Error getting sensor list";
}
}
// Start listening to any sensor
public boolean startSensor(int sensorType) {
try {
if (!hasSensor(sensorType)) {
Log.w(TAG, "Sensor not available: " + getSensorTypeName(sensorType));
return false;
}
Sensor sensor = sensorManager.getDefaultSensor(sensorType);
SensorEventListener listener = new SensorEventListener() {
@Override
public void onSensorChanged(SensorEvent event) {
lastSensorValues.put(event.sensor.getType(), event.values.clone());
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// Handle accuracy changes
}
};
sensorManager.registerListener(listener, sensor, SensorManager.SENSOR_DELAY_NORMAL);
sensorListeners.put(sensorType, listener);
// Initialize step counter with 0
if (sensorType == Sensor.TYPE_STEP_COUNTER) {
lastSensorValues.put(sensorType, new float[]{0});
}
Log.i(TAG, "Started sensor: " + getSensorTypeName(sensorType));
return true;
} catch (Exception e) {
Log.e(TAG, "startSensor failed for type: " + sensorType, e);
return false;
}
}
// Stop specific sensor
public void stopSensor(int sensorType) {
try {
SensorEventListener listener = sensorListeners.get(sensorType);
if (listener != null) {
sensorManager.unregisterListener(listener);
sensorListeners.remove(sensorType);
lastSensorValues.remove(sensorType);
Log.i(TAG, "Stopped sensor: " + getSensorTypeName(sensorType));
}
} catch (Exception e) {
Log.e(TAG, "stopSensor failed for type: " + sensorType, e);
}
}
// Stop all sensors
public void stopAllSensors() {
try {
for (Map.Entry<Integer, SensorEventListener> entry : sensorListeners.entrySet()) {
sensorManager.unregisterListener(entry.getValue());
}
sensorListeners.clear();
lastSensorValues.clear();
Log.i(TAG, "All sensors stopped");
} catch (Exception e) {
Log.e(TAG, "stopAllSensors failed", e);
}
}
// Get current sensor values
public String getSensorValues(int sensorType) {
try {
float[] values = lastSensorValues.get(sensorType);
if (values == null) return "No data";
StringBuilder sb = new StringBuilder();
sb.append(getSensorTypeName(sensorType)).append(": ");
for (int i = 0; i < values.length; i++) {
sb.append(String.format(Locale.US, "%.4f", values[i]));
if (i < values.length - 1) sb.append(", ");
}
return sb.toString();
} catch (Exception e) {
Log.e(TAG, "getSensorValues failed", e);
return "Error";
}
}
// Helper method to get sensor type names
private String getSensorTypeName(int sensorType) {
switch (sensorType) {
case Sensor.TYPE_ACCELEROMETER: return "Accelerometer";
case Sensor.TYPE_GYROSCOPE: return "Gyroscope";
case Sensor.TYPE_MAGNETIC_FIELD: return "Magnetometer";
case Sensor.TYPE_LIGHT: return "Light";
case Sensor.TYPE_PRESSURE: return "Pressure";
case Sensor.TYPE_PROXIMITY: return "Proximity";
case Sensor.TYPE_GRAVITY: return "Gravity";
case Sensor.TYPE_LINEAR_ACCELERATION: return "Linear Acceleration";
case Sensor.TYPE_ROTATION_VECTOR: return "Rotation Vector";
case Sensor.TYPE_RELATIVE_HUMIDITY: return "Humidity";
case Sensor.TYPE_AMBIENT_TEMPERATURE: return "Temperature";
case Sensor.TYPE_STEP_COUNTER: return "Step Counter";
case Sensor.TYPE_STEP_DETECTOR: return "Step Detector";
case Sensor.TYPE_ORIENTATION: return "Orientation";
default: return "Unknown (" + sensorType + ")";
}
}
// Get step count using the existing sensor listener
public float getStepCount() {
try {
float[] values = lastSensorValues.get(Sensor.TYPE_STEP_COUNTER);
if (values == null || values.length == 0) {
return 0;
}
return values[0];
} catch (Exception e) {
Log.e(TAG, "getStepCount failed", e);
return 0;
}
}
/**
// Motion Sensors (most common)
Sensor.TYPE_ACCELEROMETER = 1 // Hardware accelerometer
Sensor.TYPE_MAGNETIC_FIELD = 2 // Magnetometer (compass)
Sensor.TYPE_ORIENTATION = 3 // DEPRECATED - Use rotation vector instead
Sensor.TYPE_GYROSCOPE = 4 // Gyroscope
Sensor.TYPE_LIGHT = 5 // Light sensor
Sensor.TYPE_PRESSURE = 6 // Barometer
Sensor.TYPE_TEMPERATURE = 7 // DEPRECATED - Split into ambient and device temperature
Sensor.TYPE_PROXIMITY = 8 // Proximity sensor
Sensor.TYPE_GRAVITY = 9 // Software gravity (derived from accelerometer)
Sensor.TYPE_LINEAR_ACCELERATION = 10 // Software linear accel (accel minus gravity)
Sensor.TYPE_ROTATION_VECTOR = 11 // Software orientation (sensor fusion)
Sensor.TYPE_RELATIVE_HUMIDITY = 12 // Humidity sensor
Sensor.TYPE_AMBIENT_TEMPERATURE = 13 // Ambient/room temperature
Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED = 14 // Raw magnetometer data
Sensor.TYPE_GAME_ROTATION_VECTOR = 15 // Rotation without geomagnetic field
Sensor.TYPE_GYROSCOPE_UNCALIBRATED = 16 // Raw gyroscope data
Sensor.TYPE_SIGNIFICANT_MOTION = 17 // Significant motion detector
Sensor.TYPE_STEP_DETECTOR = 18 // Step detection
Sensor.TYPE_STEP_COUNTER = 19 // Step counting
Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR = 20 // Rotation using geomagnetic field
Sensor.TYPE_HEART_RATE = 21 // Heart rate monitor
Sensor.TYPE_POSE_6DOF = 28 // 6 degrees of freedom pose
Sensor.TYPE_STATIONARY_DETECT = 29 // Stationary detection
Sensor.TYPE_MOTION_DETECT = 30 // Motion detection
Sensor.TYPE_HEART_BEAT = 31 // Heart beat detector
Sensor.TYPE_LOW_LATENCY_OFFBODY_DETECT = 34 // Low latency off-body detection
Sensor.TYPE_ACCELEROMETER_UNCALIBRATED = 35 // Raw accelerometer data
Hollywood usage:
; Common sensor types
Const #SENSOR_ACCELEROMETER = 1
Const #SENSOR_MAGNETIC_FIELD = 2
Const #SENSOR_GYROSCOPE = 4
Const #SENSOR_LIGHT = 5
Const #SENSOR_PRESSURE = 6
Const #SENSOR_PROXIMITY = 8
Const #SENSOR_GRAVITY = 9
Const #SENSOR_LINEAR_ACCELERATION = 10
Const #SENSOR_ROTATION_VECTOR = 11
Const #SENSOR_HUMIDITY = 12
Const #SENSOR_AMBIENT_TEMPERATURE = 13
Const #SENSOR_STEP_COUNTER = 19
*/
// Check for activity recognition permission
public boolean hasActivityRecognitionPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
return ContextCompat.checkSelfPermission(this,
Manifest.permission.ACTIVITY_RECOGNITION) == PackageManager.PERMISSION_GRANTED;
}
return true; // Permission not required before Android 10
}
// Request activity recognition permission
public void requestActivityRecognitionPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
if (!hasActivityRecognitionPermission()) {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACTIVITY_RECOGNITION},
2004
);
}
}
}
// Force read step counter current value
public float getCurrentStepCount() {
try {
Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);
if (sensor == null) return 0;
final float[] steps = {0};
SensorEventListener tempListener = new SensorEventListener() {
@Override
public void onSensorChanged(SensorEvent event) {
steps[0] = event.values[0];
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {}
};
sensorManager.registerListener(tempListener, sensor, SensorManager.SENSOR_DELAY_NORMAL);
Thread.sleep(500);
sensorManager.unregisterListener(tempListener);
return steps[0];
} catch (Exception e) {
return 0;
}
}
// Debug method to check sensor status
public String debugSensorStatus(int sensorType) {
try {
if (sensorManager == null) {
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
}
Sensor sensor = sensorManager.getDefaultSensor(sensorType);
if (sensor == null) {
return "Sensor not found";
}
boolean hasListener = sensorListeners.containsKey(sensorType);
boolean hasValues = lastSensorValues.containsKey(sensorType);
return "Sensor: " + sensor.getName() +
", Listener: " + hasListener +
", Values: " + hasValues;
} catch (Exception e) {
return "Error: " + e.getMessage();
}
}
}