I create a app which uses accessibility. I passed intent for android accessibility settings but its not executed.
Here is code of android manifest.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.new_app">
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
<application
android:allowBackup="true"
android:label="#string/app_name"
android:icon="#mipmap/safety"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".Service_Running" />
<activity android:name=".MainActivity" />
<activity android:name=".injured_activity" />
<activity android:name=".splash_Activity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".Whatsapp_Accessibility"
android:label="Accessibility Service"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
<meta-data
android:name="android.accessibilityservice"
android:resource="#xml/whatsapp_service"/>
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService"/>
</intent-filter>
</service>
<service
android:name=".Background_Service"
android:enabled="true"
android:exported="true" />
</application>
</manifest>
Here is code of accessiblity service xml file
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service
xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeWindowContentChanged"
android:packageNames="com.whatsapp"
android:accessibilityFeedbackType="feedbackSpoken"
android:notificationTimeout="100"
android:canRetrieveWindowContent="true"/>
Here is the code of activity in which intent is passed
package com.example.new_app;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import android.app.ActivityManager;
import android.app.UiAutomation;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;
import java.util.concurrent.TimeUnit;
public class splash_Activity extends AppCompatActivity {
SharedPreferences sharedPreferences;
#RequiresApi(api = Build.VERSION_CODES.O)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash_);
sharedPreferences= getSharedPreferences("MySharedPreferences",MODE_PRIVATE);
String phone=sharedPreferences.getString("Phone_Number","");
String message=sharedPreferences.getString("Message","");
if (!isAccessibilitySettingsOn(getApplicationContext())) {
startActivity(new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS));
}
if(phone!="" && message!="")
{
if(!isMyServiceRunning(Background_Service.class))
{
startForegroundService(new Intent(this,Background_Service.class));
}
Intent intent1=new Intent(this,Service_Running.class);
startActivity(intent1);
}
else
{
Intent intent1=new Intent(this,MainActivity.class);
startActivity(intent1);
}
}
private boolean isMyServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
private boolean isAccessibilitySettingsOn(Context mContext) {
int accessibilityEnabled = 0;
final String service = getPackageName() + "/" + Whatsapp_Accessibility.class.getCanonicalName();
try {
accessibilityEnabled = Settings.Secure.getInt(
mContext.getApplicationContext().getContentResolver(),
android.provider.Settings.Secure.ACCESSIBILITY_ENABLED);
Log.v("this", "accessibilityEnabled = " + accessibilityEnabled);
} catch (Settings.SettingNotFoundException e) {
Log.e("this", "Error finding setting, default accessibility to not found: "
+ e.getMessage());
}
TextUtils.SimpleStringSplitter mStringColonSplitter = new TextUtils.SimpleStringSplitter(':');
if (accessibilityEnabled == 1) {
Log.v("this", "***ACCESSIBILITY IS ENABLED*** -----------------");
String settingValue = Settings.Secure.getString(
mContext.getApplicationContext().getContentResolver(),
Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
if (settingValue != null) {
mStringColonSplitter.setString(settingValue);
while (mStringColonSplitter.hasNext()) {
String accessibilityService = mStringColonSplitter.next();
Log.v("this", "-------------- > accessibilityService :: " + accessibilityService + " " + service);
if (accessibilityService.equalsIgnoreCase(service)) {
Log.v("this", "We've found the correct setting - accessibility is switched on!");
return true;
}
}
}
} else {
Log.v("this", "***ACCESSIBILITY IS DISABLED***");
}
return false;
}
}
Here is the code of Accessiblity Service
package com.example.new_app;
import android.accessibilityservice.AccessibilityService;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
import java.util.List;
public class Whatsapp_Accessibility extends AccessibilityService {
#Override
public void onAccessibilityEvent(AccessibilityEvent event) {
if(getRootInActiveWindow() == null){
return;
}
AccessibilityNodeInfoCompat rootNodeInfo = AccessibilityNodeInfoCompat.wrap(getRootInActiveWindow());
//get edit text if message from whats app
List<AccessibilityNodeInfoCompat> messageNodeList = rootNodeInfo.findAccessibilityNodeInfosByViewId("com.whatsapp:id/entry");
if(messageNodeList == null || messageNodeList.isEmpty())
return;
//checking if message field if filled with text and ending with our suffix
AccessibilityNodeInfoCompat messageField = messageNodeList.get(0);
if(messageField == null || messageField.getText().length() == 0 || !messageField.getText().toString().endsWith(" Send by Safety App"))
return;
// get whatsapp send message button node list
List<AccessibilityNodeInfoCompat> sendMessageNodeList = rootNodeInfo.findAccessibilityNodeInfosByViewId("com.whatsapp:id/send");
if(sendMessageNodeList == null || sendMessageNodeList.isEmpty())
return;
AccessibilityNodeInfoCompat sendMessage = sendMessageNodeList.get(0);
if(!sendMessage.isVisibleToUser())
return;
//fire send button
sendMessage.performAction(AccessibilityNodeInfo.ACTION_CLICK);
try{
Thread.sleep(2000);
performGlobalAction(GLOBAL_ACTION_BACK);
Thread.sleep(2000);
performGlobalAction(GLOBAL_ACTION_BACK);
}catch (InterruptedException ignored) {}
}
#Override
public void onInterrupt() {
}
}
I tested all this code on android 10
Related
See lines 94-95 in mainactivity file.
**bluetoothSocket = bluetoothDevice.createRfcommSocketToServiceRecord(MY_UUID);
bluetoothSocket.connect();**
inputStream = bluetoothSocket.getInputStream();
Am receiving this error:
"Call requires permission which may be rejected by user: code should explicitly check to see if permission is available (with checkPermission) or explicitly handle a potential SecurityException."
I tried adding the onRequestPermissionsResult method and preceding if-statement, but I am still receiving the error. What more is needed?
Am using HC-05 module to transmit serial data from arduino to android device. Thanks.
Manifest attached as well
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
\<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"\>
<!--Before Android 12 (but still needed location, even if not requested)-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
<!--From Android 12-->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<application
android:allowBackup="true"
android:dataExtractionRules="#xml/data_extraction_rules"
android:fullBackupContent="#xml/backup_rules"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/Theme.StrikeTec"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="android.app.lib_name"
android:value="" />
</activity>
</application>
MainActivity.java
`
package com.example.striketec;
import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.UUID;
public class MainActivity extends AppCompatActivity {
private static final int REQUEST_BLUETOOTH_PERMISSIONS = 1;
private static final String\[\] BLUETOOTH_PERMISSIONS = {
Manifest.permission.BLUETOOTH,
Manifest.permission.BLUETOOTH_ADMIN
};
private static final String MAC_ADDRESS = "00:11:22:33:44:55"; // Replace with your device's MAC address
private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); // Standard SPP UUID
private BluetoothAdapter bluetoothAdapter;
private BluetoothDevice bluetoothDevice;
private BluetoothSocket bluetoothSocket;
private InputStream inputStream;
private BufferedReader reader;
private TextView fastestTextView;
private TextView slowestTextView;
private TextView averageTextView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fastestTextView = findViewById(R.id.fastest_text_view);
slowestTextView = findViewById(R.id.slowest_text_view);
averageTextView = findViewById(R.id.average_text_view);
// Check if the app has the required permissions
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH) != PackageManager.PERMISSION_GRANTED
|| ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_ADMIN) != PackageManager.PERMISSION_GRANTED) {
// Request the permissions if they are not granted
ActivityCompat.requestPermissions(this, BLUETOOTH_PERMISSIONS, REQUEST_BLUETOOTH_PERMISSIONS);
} else {
// Initialize Bluetooth if the permissions are already granted
initBluetooth();
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String\[\] permissions, #NonNull int\[\] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_BLUETOOTH_PERMISSIONS) {
if (grantResults.length \> 0 && grantResults\[0\] == PackageManager.PERMISSION_GRANTED
&& grantResults\[1\] == PackageManager.PERMISSION_GRANTED) {
// Initialize Bluetooth if the permissions are granted
initBluetooth();
} else {
Toast.makeText(this, "Bluetooth permissions are required", Toast.LENGTH_SHORT).show();
finish();
}
}
}
private void initBluetooth() {
// Initialize Bluetooth here
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (bluetoothAdapter == null) {
Toast.makeText(this, "Bluetooth is not supported on this device", Toast.LENGTH_SHORT).show();
finish();
return;
}
if (!bluetoothAdapter.isEnabled()) {
Toast.makeText(this, "Please enable Bluetooth", Toast.LENGTH_SHORT).show();
finish();
return;
}
bluetoothDevice = bluetoothAdapter.getRemoteDevice(MAC_ADDRESS);
try {
**bluetoothSocket = bluetoothDevice.createRfcommSocketToServiceRecord(MY_UUID);
bluetoothSocket.connect();**
inputStream = bluetoothSocket.getInputStream();
reader = new BufferedReader(new InputStreamReader(inputStream));
new Thread(new Runnable() {
#Override
public void run() {
while (true) {
try {
final String data = reader.readLine();
runOnUiThread(new Runnable() {
#Override
public void run() {
// Update the UI with the data received
fastestTextView.setText(data);
slowestTextView.setText(data);
averageTextView.setText(data);
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
}
}).start();
} catch (IOException e) {
e.printStackTrace();
}
}
}\`
I tried adding the onRequestPermissionsResult method and preceding if-statement, but I am still receiving the error. What more is needed? Expected this to suffice and the error to disappear.
I'm building an Android Wear service which runs in the background and logs device data every three minutes. For this logging, I am using a Handler, which records the values and then has an interval of three minutes. This will be used to monitor user behaviour for one month, and as such it should not randomly stop.
I have also used android.intent.action.BOOT_COMPLETED in my manifest and this successfully runs the application whenever the watch is booted.
My issue is that the service can run correctly for 12 hours...and then just suddenly stop. The amount of time appears to be non-deterministic, as sometimes it will stop after 40 minutes. I suspect it's being killed by Android, but in this case I would like it to restart. I have included return START_STICKY in my service and this should minimise the chance of it being killed.
In some solutions, I have seen onDestroy() overridden and a refresh broadcast being sent to the service. While this appears to work, the onDestroy() function is being called every time the Handler completes one piece of work. This leads to the service restarting every three minutes, rather than when the application is actually killed by Android.
I have also looked at the intent actions to see whether my service could be called at regular intervals. However, aside from android.intent.action.BOOT_COMPLETED, all the useful ones cannot be registered in the Manifest file. Since the service will not be running, registerReceiver() would serve little purpose.
Does anybody know of a technique to either a) guarantee a service will not be killed by Android; or b) guarantee that a service will always be restarted after it has been killed. Any help would be greatly appreciated, as I've even started considering writing a Cron job on the device and setting it to execute my app every three minutes! I've also looked at the AlarmManager class, but I fear it is as likely to be killed if running for long periods.
Please find my code below: (AndroidManifest.xml)
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.study">
<uses-feature android:name="android.hardware.type.watch" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#android:style/Theme.DeviceDefault">
<receiver android:name="com.example.study.MyServiceManager" android:enabled="true">
<intent-filter>
<action android:name="com.example.study.RestartAction" />
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<activity
android:name="com.example.study.MainActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name="com.example.study.RecordService"
android:exported="false" />
</application>
</manifest>
RecordService.java
package com.example.study;
import android.Manifest;
import android.app.AlarmManager;
import android.app.IntentService;
import android.app.KeyguardManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.location.Location;
import com.google.android.gms.location.LocationServices;
import android.os.Build;
import android.os.Handler;
import android.os.PowerManager;
import android.provider.Settings;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.text.TextUtils;
import com.google.android.gms.location.*;
import com.google.android.gms.tasks.OnSuccessListener;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutionException;
public class RecordService extends IntentService {
private static Context context;
private final static int INTERVAL = 1000 * 5; // 1 minutes
Handler handler = new Handler();
Location myLocation;
private FusedLocationProviderClient mFusedLocationClient;
SensorManager sensorManager;
SensorManager gyroSensorManager;
SensorManager compassSensorManager;
SensorEventListener sensorEventListener;
float[] accValues;
float[] gyroValues;
float[] compassValues;
Runnable handlerTask = new Runnable() {
#Override
public void run() {
try {
recordData();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
handler.postDelayed(handlerTask, INTERVAL);
}
};
public RecordService() {
super("RecordService");
}
#Override
protected void onHandleIntent(#Nullable Intent intent) {
handlerTask.run();
}
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
public void recordData() throws ExecutionException, InterruptedException {
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(MainActivity.getAppContext());
boolean fineLocationGranted = ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
boolean coarseLocationGranted = ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED;
boolean isLocationEnabled = isLocationEnabled(this);
if(fineLocationGranted && coarseLocationGranted && isLocationEnabled) {
long startTime = System.currentTimeMillis();
long timeWaiting = 0L;
mFusedLocationClient.getLastLocation()
.addOnSuccessListener(MainActivity.getActivity(), new OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
if (location != null) {
myLocation = location;
} else {
System.out.print("");
}
}
});
do {
timeWaiting = System.currentTimeMillis() - startTime;
} while (myLocation == null && timeWaiting < 200);
}
List<PackageInfo> packages = getPackageManager().getInstalledPackages(PackageManager.GET_PERMISSIONS);
KeyguardManager kg = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
boolean isLocked = kg.isDeviceSecure();
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
gyroSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
compassSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
sensorEventListener = new SensorEventListener() {
#Override
public void onSensorChanged(SensorEvent sensorEvent) {
if(sensorEvent.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
accValues = sensorEvent.values;
} else if(sensorEvent.sensor.getType() == Sensor.TYPE_GYROSCOPE){
gyroValues = sensorEvent.values;
} else if(sensorEvent.sensor.getType() == Sensor.TYPE_ORIENTATION) {
compassValues = sensorEvent.values;
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int i) {}
};
try {
sensorManager.registerListener(sensorEventListener, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);
gyroSensorManager.registerListener(sensorEventListener, sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE), SensorManager.SENSOR_DELAY_NORMAL);
compassSensorManager.registerListener(sensorEventListener, sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION), SensorManager.SENSOR_DELAY_NORMAL);
} catch(SecurityException e) {
e.printStackTrace();
}
long startTime2 = System.currentTimeMillis();
long timeWaiting2 = 0L;
do {
timeWaiting2 = System.currentTimeMillis() - startTime2;
} while((accValues == null || gyroValues == null || compassValues == null) && timeWaiting2 < 200);
StringBuilder builder = new StringBuilder();
builder.append("G" + (isLocationEnabled ? 1 : 0));
builder.append(" L" + (isLocked ? 1 : 0));
if(accValues != null && gyroValues != null && compassValues != null) {
builder.append(" ACX" + accValues[0]);
builder.append(" ACY" + accValues[1]);
builder.append(" ACZ" + accValues[2]);
builder.append(" GYX" + gyroValues[0]);
builder.append(" GYY" + gyroValues[1]);
builder.append(" GYZ" + gyroValues[2]);
builder.append(" CMX" + gyroValues[0]);
builder.append(" CMY" + gyroValues[1]);
builder.append(" CMZ" + gyroValues[2]);
}
if(myLocation != null) {
builder.append(" LT" + myLocation.getLatitude());
builder.append(" LN" + myLocation.getLongitude());
}
builder.append("\n");
for(PackageInfo info: packages) {
int lastDot = info.packageName.lastIndexOf('.');
builder.append(info.packageName + "\n");
if(info.requestedPermissions != null) {
for (String rqprm : info.requestedPermissions) {
int dot = rqprm.lastIndexOf('.');
builder.append(rqprm.substring(dot != -1 ? dot + 1 : 0) + " ");
}
builder.append("\n");
for (int permflag : info.requestedPermissionsFlags) {
builder.append("" + permflag + " ");
}
builder.append("\n");
}
}
SimpleDateFormat sdf = new SimpleDateFormat("yy-MM-dd--HH-mm-ss");
String currentDateString = sdf.format(new Date());
File log = new File("/sdcard/Recordings/" + currentDateString);
try {
if (!log.exists()) {
log.createNewFile();
}
BufferedWriter writer = new BufferedWriter(new FileWriter(log, true));
writer.append(builder.toString());
writer.newLine();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static boolean isLocationEnabled(Context context) {
int locationMode = 0;
String locationProviders;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
try {
locationMode = Settings.Secure.getInt(context.getContentResolver(), Settings.Secure.LOCATION_MODE);
} catch (Settings.SettingNotFoundException e) {
e.printStackTrace();
return false;
}
return locationMode != Settings.Secure.LOCATION_MODE_OFF;
} else {
locationProviders = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
return !TextUtils.isEmpty(locationProviders);
}
}
MainActivity.java
package com.example.study;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends Activity {
private TextView mTextView;
private static Context context;
private static MainActivity activity;
Intent serviceIntent;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MainActivity.context = getApplicationContext();
activity = this;
serviceIntent = new Intent(this, RecordService.class);
startForegroundService(serviceIntent)
startService(serviceIntent);
}
public static Context getAppContext() {
return MainActivity.context;
}
public static MainActivity getActivity() {
return activity;
}
}
MyServiceManager.java
package com.example.study;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
public class MyServiceManager extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent myIntent = new Intent(context, MainActivity.class);
myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(myIntent);
}
}
}
The alarmmanager is working perfectly on emulator but not on physical device.
It works sometimes on the device. Please help. i cant find why its not working on device. Is there a bug?
The same code was working fine earlier.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.wim.wimonandroid"
android:versionCode="94"
android:versionName="10.1" >
<uses-sdk android:minSdkVersion="10" />
<uses-permission android:name="android.permission.INTERNET" >
</uses-permission>
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK"></uses-permission>
<application
android:icon="#drawable/icon"
android:label="#string/app_name" >
<activity
android:screenOrientation="portrait"
android:name=".wimOnAndroid"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".Compas"
android:label="#string/app_name"
android:screenOrientation="portrait" >
</activity>
<activity
android:name=".TutorialZoomActivity1"
android:label="#string/ramadan" >
</activity>
<activity
android:name=".AlarmListView"
android:label="#string/app_name3" >
</activity>
<activity
android:name=".wimRss"
android:label="#string/app_name1" >
</activity>
<activity
android:name=".CityListView"
android:label="#string/app_name4" >
</activity>
<activity
android:name=".jummah"
android:label="#string/jummah" >
</activity>
<activity
android:name=".settings"
android:label="#string/settings" >
</activity>
<activity
android:name=".QA"
android:label="#string/QA" >
</activity>
<activity
android:name=".SendEmailActivity"
android:label="#string/app_name_Sendmail" >
</activity>
<activity
android:name=".Touch"
android:label="#string/app_name" >
</activity>
<activity
android:name=".compass"
android:label="#string/compass" >
</activity>
<activity
android:screenOrientation="landscape"
android:configChanges="orientation|keyboardHidden"
android:name=".sehri"
android:label="sehri" >
</activity>
<activity
android:screenOrientation="landscape"
android:configChanges="orientation|keyboardHidden"
android:name=".iftari"
android:label="iftari" >
</activity>
<activity
android:name=".felles"
android:label="felles" >
</activity>
<!-- <service android:enabled="true" android:name=".AlarmService" /> -->
<service android:name=".MyAlarmService" >
</service>
<service android:name=".UpdateWidgetService" >
</service>
<!-- Broadcast Receiver that will process AppWidget updates -->
<receiver android:name=".MyBroadcastreceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.PACKAGE_REPLACED"/>
<data android:scheme="package" />
</intent-filter>
</receiver>
<receiver
android:name=".wimWidget"
android:label="#string/app_nameWid" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/hello_widget_provider" />
</receiver>
<activity
android:name=".SehriActivity"
android:label="#string/title_activity_sehri" >
</activity>
</application>
package com.wim.wimonandroid;
import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.Calendar;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Handler;
import android.os.IBinder;
import android.os.Vibrator;
import android.util.Log;
import android.widget.Toast;
public class MyAlarmService extends Service {
MediaPlayer player;
String readString = new String("");
String readAlarm = new String("");
String readSpilt = new String("");
String readForste = new String("");
private PendingIntent pendingIntent;
private AlarmManager alarmManager;
#Override
public void onCreate() {
Log.v("tid", "MyAlarmService - onCreate()" );
try {
readFile(); //sjekker om Alarm er slått på eller ei
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try{
hent(); //setter neste alarm
} catch (IOException e) {
e.printStackTrace();
}
if(readString.equals("2") ){
Log.v("tid", "MyAlarmService - onCreate - Kaller onDestroy()" );
onDestroy() ;
}
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
//Toast.makeText(this, "MyAlarmService.onBind()", Toast.LENGTH_LONG).show();
return null;
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
Log.v("tid", "MyAlarmService - onDestroy");
//writeFile(2);
}
public int onStartCommand(Intent intent, int flags, int startId) {
Log.v("tid", "MyAlarmService - onStartCommand()");
String forste = new String("");
try {
readFile(); // Sjekker om alarm er på eller ei.
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
forste = readForste();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
Calendar cal = Calendar.getInstance();
int hour = cal.get(Calendar.HOUR_OF_DAY) ; //1300
int minutes = cal.get(Calendar.MINUTE);
Log.v("tid", "MyAlarmService - onStartCommand - readAlarm: " +
readAlarm);
AudioManager am =
(AudioManager)getSystemService(Context.AUDIO_SERVICE);
switch (am.getRingerMode()) {
case AudioManager.RINGER_MODE_SILENT:
Log.v("tid","Silent mode");
break;
case AudioManager.RINGER_MODE_VIBRATE:
Log.v("tid","Vibrate mode");
break;
case AudioManager.RINGER_MODE_NORMAL:
Log.v("tid","Normal mode - onStart");
// if(Integer.parseInt(readAlarm.trim()) == 0){
if(readAlarm.equals("0")){
Log.i("tid","Normal mode - door - Minutter: " + minutter);
am.setStreamVolume(AudioManager.STREAM_MUSIC,
am.getStreamMaxVolume(AudioManager.STREAM_MUSIC),
AudioManager.FLAG_SHOW_UI);
player = MediaPlayer.create(this, R.raw.door);
player.setLooping(false); // Set looping
player.setVolume(1, 1);
player.start();
player.release();
Runnable r = new Runnable() {
public void run(){
}
};
Handler h = new Handler();
h.postDelayed(r, 60000);
//alarmHjelp.restart();
}
//else if(Integer.parseInt(readAlarm.trim()) == 1){
else if(readAlarm.equals("1")){
Log.i("tid","Normal mode - azaan");
am.setStreamVolume(AudioManager.STREAM_MUSIC,
am.getStreamMaxVolume(AudioManager.STREAM_MUSIC),
AudioManager.FLAG_SHOW_UI);
player = MediaPlayer.create(this, R.raw.azan);
player.setLooping(false); // Set looping
player.setVolume(1, 1);
player.start();
player.release();
Runnable r = new Runnable() {
public void run(){
}
};
Handler h = new Handler();
h.postDelayed(r, 60000);
}
break;
}
if(readAlarm.equals("0") || readAlarm.equals("1")){
Log.i("tid","vibrasjon");
Vibrator v = (Vibrator)
getSystemService(Context.VIBRATOR_SERVICE);
v.vibrate(4000);
Toast.makeText(getApplicationContext(), "Tid for bønn..." ,
Toast.LENGTH_LONG).show();
}
}
try {
hent(); //setter neste alarm
} catch (IOException e) {
e.printStackTrace();
}
//} // 2 er lydløs
Log.v("tid","MyAlarmService - OnStartCommand - Start sticky");
return START_STICKY;
}
public void hent() throws IOException{
Log.v("tid", "MyAlarmService - hent()");
int alarmH = 0;
int alarmM = 0;
Calendar cal2 = Calendar.getInstance();
int hour = cal2.get(Calendar.HOUR_OF_DAY) ;
int minutes = cal2.get(Calendar.MINUTE);
try {
checkBy = readCity();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String tider = new String("");
Log.v("tid", "MyAlarmService - hent() - By: " + checkBy);
//Setting alarm every second hour
alarmH = alarmH + 2;
Intent myIntent = new Intent(this, MyAlarmService.class);
pendingIntent = PendingIntent.getService(this, 0, myIntent, 0);
alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
Calendar cal = Calendar.getInstance();
if(nesteDag == 1)
{
Log.v("tid", "MyAlarmService - hent() - nestedag");
cal.add( Calendar.DATE, 1 );
}
cal.set(Calendar.HOUR_OF_DAY, alarmH);
cal.set(Calendar.MINUTE, alarmM);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
alarmManager.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(),
pendingIntent);
Log.i("tid", "MyAlarmService - hent() - Neste alarm: " + alarmH +
":" + alarmM);
}
}
public void readFile() throws IOException{
Log.v("tid", "MyAlarmService - readFile() - readAlarm: " + readAlarm);
// open the file for reading
InputStream instream = openFileInput("alarm.txt");
InputStreamReader inputreader = new InputStreamReader(instream);
BufferedReader buffreader = new BufferedReader(inputreader);
while (( readAlarm = buffreader.readLine()) != null) {
Log.v("tid", "readAlarm: " + readAlarm);
break;
}
instream.close();
if(readAlarm == null){
Log.v("tid", "MyAlarmService - readFile - readAlarm er NULL");
readAlarm = "2";
writeFile(2);
Log.v("tid", "MyAlarmService - readFile - readAlarm (ny verdi):
" + readAlarm);
}
}
public void onBackPressed()
{
this.startActivity(new Intent(this,wimOnAndroid.class));
}
#Override
public boolean onUnbind(Intent intent) {
// TODO Auto-generated method stub
Toast.makeText(this, "MyAlarmService.onUnbind()", Toast.LENGTH_LONG).show();
return super.onUnbind(intent);
}
}
}
I am developing an app which uses getRunningTasks() function to get the top activity name. But getRunningTasks() is deprecated in Android L. Is there any other way to get the top activity name (not package name) in Lollipop.
Class<?> currentClassName; // Declare Globally
Activity activity = (Activity) context;//casting context into activity
try
{
currentClassName = Class.forName(activity.getClass().getName()); //getting the current activity's class name from activity object
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
}
Please read SO Answer
I found a solution to get top activity name on Lollipop with the new Class UsageStatsManager added in Android L.
First you need the permission
<uses-permission
android:name="android.permission.PACKAGE_USAGE_STATS"
tools:ignore="ProtectedPermissions" />
And the user must enable this option.
Then use this method queryEvents()
There is a simple example.
while (true) {
final long INTERVAL = 1000;
final long end = System.currentTimeMillis();
final long begin = end - INTERVAL;
final UsageEvents usageEvents = manager.queryEvents(begin, end);
while (usageEvents.hasNextEvent()) {
UsageEvents.Event event = new UsageEvents.Event();
usageEvents.getNextEvent(event);
if (event.getEventType() == UsageEvents.Event.MOVE_TO_FOREGROUND) {
Log.d("event", "timestamp : " + event.getTimeStamp());
Log.d("event", "package name : " + event.getPackageName());
Log.d("event", "class name : " + event.getClassName());
}
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
When an activity become to foreground, you can see its class name and package name in Logcat.
AccessibilityService can resolve this requirement, but the Accessibilityservice
api in android not stable, sometimes need checkbox off and on again, some code
<application>
<service
android:name=".service.DetectService"
android:exported="false"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
<meta-data
android:name="android.accessibilityservice"
android:resource="#xml/accessibility_service" />
</service>
<?xml version="1.0" encoding="UTF-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeAllMask"
android:accessibilityFeedbackType="feedbackAllMask"
android:accessibilityFlags="flagReportViewIds"
android:canPerformGestures="true"
android:canRetrieveWindowContent="true"
android:notificationTimeout="100" />
import android.accessibilityservice.AccessibilityService;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
public class DetectService extends AccessibilityService {
#Override
protected void onServiceConnected() {
super.onServiceConnected();
}
#Override
public void onAccessibilityEvent(AccessibilityEvent event) {
AccessibilityNodeInfo source = event.getSource();
if (source == null) {
return;
}
Log.d("DetectService", "type: " + event.getEventType());
CharSequence packageName = source.getPackageName();
if (event.getEventType() != AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
return;
}
ComponentName componentName = new ComponentName(event.getPackageName().toString(), event.getClassName().toString());
try {
String activityName = getPackageManager().getActivityInfo(componentName, PackageManager.GET_META_DATA
| PackageManager.MATCH_ALL).toString();
activityName = activityName.substring(activityName.indexOf(" "), activityName.indexOf("}"));
Log.e("DetectService", packageName + ": " + activityName);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
// sometime getActivityInfo will get NameNotFoundException,try use componentName
}
}
#Override
public void onInterrupt() {
Log.w("DetectService", "onInterrupt");
}
#Override
public boolean onUnbind(Intent intent) {
Log.w("DetectService", "onUnbind");
return super.onUnbind(intent);
}
}
I am sure this is simple but I cannot figure it out. All I am trying to do is send a message via NFC. The code I have work perfectly if I am sending it to the main activity, but I don't know how to send it to a different activity. I have looked over both the NFC and Intent Filter articles on the Android Developer pages but am still not sure exactly how to do this. I am trying to send it to a NFC activity, I will post my manifest and NFC class below.
Manifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.justbaumdev.tagsense"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="15" />
<uses-permission android:name="android.permission.NFC" />
<uses-feature android:name="android.hardware.nfc" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#android:style/Theme.Holo" >
<activity
android:name=".TagSense"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.justbaumdev.tagsense.NFC" android:exported="false">
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="application/com.justbaumdev.tagsense" />
</intent-filter>
</activity>
</application>
</manifest>
NFC Class:
package com.justbaumdev.tagsense;
import org.json.JSONArray;
import org.json.JSONException;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.wifi.WifiManager;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.NfcAdapter.CreateNdefMessageCallback;
import android.nfc.NfcAdapter.OnNdefPushCompleteCallback;
import android.nfc.NfcEvent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Parcelable;
import android.widget.Toast;
public class NFC extends Activity implements CreateNdefMessageCallback, OnNdefPushCompleteCallback {
private NfcAdapter mNfcAdapter;
private static final int MESSAGE_SENT = 1;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.nfc);
mNfcAdapter = NfcAdapter.getDefaultAdapter(this); // Check for available NFC Adapter
if (mNfcAdapter == null)
{
Toast.makeText(this, "NFC is not available", Toast.LENGTH_LONG).show();
finish();
return;
}
else
{
mNfcAdapter.setNdefPushMessageCallback(this, this); // Register callback to set NDEF message
mNfcAdapter.setOnNdefPushCompleteCallback(this, this); // Register callback to listen for message-sent success
}
}
#Override
public void onResume() {
super.onResume();
// Check to see that the Activity started due to an Android Beam
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {
processIntent(getIntent());
}
}
#Override
public void onNewIntent(Intent intent) {
// onResume gets called after this to handle the intent
setIntent(intent);
}
#Override
public NdefMessage createNdefMessage(NfcEvent event) {
WifiManager wm = (WifiManager) getSystemService(Context.WIFI_SERVICE);
String mac = wm.getConnectionInfo().getMacAddress();
String newMac = mac.substring(0, 2);
mac = mac.substring(2);
int hex = Integer.parseInt(newMac, 16) + 0x2;
newMac = Integer.toHexString(hex);
String text = newMac + mac;
NdefMessage msg = new NdefMessage(NdefRecord.createMime(
"application/com.justbaumdev.tagsense", text.getBytes()));
return msg;
}
/**
* Implementation for the OnNdefPushCompleteCallback interface
*/
#Override
public void onNdefPushComplete(NfcEvent arg0) {
// A handler is needed to send messages to the activity when this
// callback occurs, because it happens from a binder thread
mHandler.obtainMessage(MESSAGE_SENT).sendToTarget();
}
/** This handler receives a message from onNdefPushComplete */
private final Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_SENT:
Toast.makeText(getApplicationContext(), "Message sent!", Toast.LENGTH_LONG).show();
break;
}
}
};
/**
* Parses the NDEF Message from the intent and prints to the TextView
*/
//TODO Currently overwrites any previously saved mac addresses. Get FB ID as value. Auto end activity.
void processIntent(Intent intent) {
Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
// only one message sent during the beam
NdefMessage msg = (NdefMessage) rawMsgs[0];
// record 0 contains the MIME type, record 1 is the AAR, if present
//textView.setText(new String(msg.getRecords()[0].getPayload()));
String payload = new String(msg.getRecords()[0].getPayload());
Toast.makeText(this, new String(msg.getRecords()[0].getPayload()), Toast.LENGTH_LONG).show();
SharedPreferences appData = getSharedPreferences("appData", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = appData.edit();
String addresses = appData.getString("mac_address", null);
if(addresses==null)
{
JSONArray addressArray = new JSONArray();
addressArray.put(payload);
addresses = addressArray.toString();
}
else
{
try {
if(!addresses.contains(payload))
{
JSONArray addressArray = new JSONArray(addresses);
addressArray.put(payload);
addresses = addressArray.toString();
}
} catch (JSONException e) {
Toast.makeText(this, "Error adding new friend. Please try again.", Toast.LENGTH_SHORT).show();
}
}
editor.putString("mac_address", addresses);
editor.commit();
}
}
Thanks for your help.
Remove the attribute android:exported="false". See also https://stackoverflow.com/a/12719621/1202968