I will make a new Android application. How to to auto-start it as soon as the mobile is plugged into charging?
If this is successfully done, then the application will be opened automatically when the charger is plugged to the mobile phone.
You need a broadcast receiver for this.
Add this to your manifest:
<receiver android:name=".PowerConnectionReceiver">
<intent-filter>
<action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
<action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>
</intent-filter>
</receiver>
Now add this to your class
public class PowerConnectionReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
status == BatteryManager.BATTERY_STATUS_FULL;
int chargePlug = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
boolean usbCharging = chargePlug == BatteryManager.BATTERY_PLUGGED_USB;
boolean acCharging = chargePlug == BatteryManager.BATTERY_PLUGGED_AC;
if (isCharging) {
Intent i = new Intent();
i.setClassName("com.className", "com.classname.YourActivityClass");
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i)
}
}
}
Don't forget to replace things like com.className with yours.
Related
I'm setting up AudioManager with bluetooth to record an audio , the code is already there but not working and whenever i check for AudioManager.EXTRA_SCO_AUDIO_STATE , it never connects and returns -1 , i do not know why , can anyone please guide me to solve this issue , Thank you .
This is my receiver
public class CallReceiver extends BroadcastReceiver {
public CallReceiver() {
super();
}
#Override
public void onReceive(Context context, Intent intent) {
Bundle bundle;
String state;
String incomingNumber;
String action = intent.getAction();
int BLE = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1); // always return -1
if (BLE == AudioManager.SCO_AUDIO_STATE_CONNECTED){ // never connected
// start bluetooth headset
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE)
audioManager.setMode(AudioManager.MODE_IN_CALL);
audioManager.setBluetoothScoOn(true);
audioManager.startBluetoothSco();
}
}
}
Receiver in Manifest File
<receiver
android:name=".recorder.CallReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.media.extra.SCO_AUDIO_STATE"/>
<action
android:name="android.media.ACTION_SCO_AUDIO_STATE_UPDATED"/>
</intent-filter>
</receiver>
Before checking the current state, first need to find the action, I check for AudioManager.EXTRA_SCO_AUDIO_STATE, it never connects and returns -1. After finding the current state, If found 'SCO_AUDIO_STATE_CONNECTED' setBluetoothScoOn and startBluetoothSco.
#Override public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
if (action.equalsIgnoreCase(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED))
{
int currentState = context . getIntExtra (AudioManager.EXTRA_SCO_AUDIO_STATE, -1);
Log.d("Bluetooth Connect - ", "Audio SCO: " + AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED);
switch(currentState) {
case AudioManager.SCO_AUDIO_STATE_CONNECTED :
{
Log.i("Bluetooth Connect", "SCO_AUDIO_STATE_CONNECTED");
AudioManager audioManager =(AudioManager) context . getSystemService (Context.AUDIO_SERVICE)
audioManager.setMode(AudioManager.MODE_IN_CALL);
audioManager.setBluetoothScoOn(true);
audioManager.startBluetoothSco();
}
break;
case AudioManager.SCO_AUDIO_STATE_DISCONNECTED :
{
Log.e("Bluetooth disconnect", "SCO_AUDIO_STATE_DISCONNECTED");
}
break;
default: Log.e("Bluetooth unknown - ", "unknown state received:"+l_state);
}
} else Log.e("Bluetooth Connect - ", "onReceive:action=" + action);
}
I'm working on application which shows list of certain connected bluetooth low energy devices, so user can choose which one of them he wants to configure.
The problem is that you can't just list all connected devices. As far as I know there are three possible ways:
Use BluetoothProfiles
bluetoothManager.getConnectedDevices(BluetoothProfile.GATT_SERVER);
This fails because android won't connect to GATT server, when device connects, so device is neither under GATT_SERVER nor GATT profile. However once I call connectGatt method,
bluetoothDevice.connectGatt(getApplicationContext(), false, gattCallback);
device can be found under both GATT_SERVER and GATT profile. Other profiles are not supported by low energy devices.
List paired devices and try connectGatt on each of them
List<BluetoothDevice> connectedDevices = new ArrayList<BluetoothDevice>();
for(BluetoothDevice device : bluetoothAdapter.getBondedDevices()) {
BluetoothGatt gatt = device.connectGatt(getApplicationContext(), false, gattCallback);
if(gatt != null) {
connectedDevices.add(device);
}
gatt.disconnect();
}
This method cannot be used as it cannot determine if device is already connected or only in range but not connected
On system boot start service listening to ACL_CONNECTED and ACL_DISCONNECTED intents and maintaining list of connected devices
Manifest
<service android:name=".ManagerService" android:enabled="true" />
<receiver
android:name=".BootFinishedReceiver"
android:directBootAware="true"
android:enabled="true"
android:exported="false"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
Receiver
public class BootFinishedReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent serviceIntent = new Intent(context, ManagerService.class);
context.startService(serviceIntent);
}
}
Service
public class ManagerService extends Service {
private static List<BluetoothDevice> connectedDevices;
#Override
public void onCreate() {
connectedDevices = new ArrayList<BluetoothDevice>();
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
registerReceiver(connectionReceiver, filter);
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy() {
unregisterReceiver(connectionReceiver);
super.onDestroy();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
private final BroadcastReceiver connectionReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if(BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) {
connectedDevices.add(device);
}else{
connectedDevices.remove(device);
}
}
};
public static List<BluetoothDevice> getConnectedDevices() {
return connectedDevices;
}
}
Since 3.1 apps can no longer receive system intents before activity is started, so this cannot be used either.
Is there any other way or how can I achieve it now in later android versions?
Thanks for any suggestions
Well, I found out that you can still use ON_BOOT_COMPLETED, but you have to allow it in setting on your device. So my problem is solved
I'm trying to make an app that monitors the users phone usage by tracking time of screen lock and unlock. I tried to setup a BroadcastReceiver which works fine when the app is running the background. But won't work when I close the app. Is there a solution for this.
The code I'm using now is as follows :
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this, ScreenListenerService.class);
startService(intent);
}
}
ScreenListenerService class is as follows..
public class ScreenListenerService extends Service {
private BroadcastReceiver mScreenStateBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
// Save something to the server
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
// Save something to the server
}
}
};
#Override
public void onCreate() {
super.onCreate();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_SCREEN_ON);
intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
registerReceiver(mScreenStateBroadcastReceiver, intentFilter);
}
#Override
public void onDestroy() {
unregisterReceiver(mScreenStateBroadcastReceiver);
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
My AndroidManifest file is as follows :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.abbinvarghese.calculu">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<service android:name=".ScreenListenerService" />
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
To overcome the imposed limitations of 8.0 you could run a foreground service. Just like a service but a notification is posted to the foreground.
Then the service code would be like this (remember to unregister the receiver onDestory):
BroadcastReceiver screenReceiver;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
startRunningInForeground();
detectingDeterminateOfServiceCall(intent.getExtras());
registerBroadcastReceivers();
return START_STICKY;
}
private void startRunningInForeground() {
//if more than or equal to 26
if (Build.VERSION.SDK_INT >= 26) {
//if more than 26
if(Build.VERSION.SDK_INT > 26){
String CHANNEL_ONE_ID = "sensor.example. geyerk1.inspect.screenservice";
String CHANNEL_ONE_NAME = "Screen service";
NotificationChannel notificationChannel = null;
notificationChannel = new NotificationChannel(CHANNEL_ONE_ID,
CHANNEL_ONE_NAME, NotificationManager.IMPORTANCE_MIN);
notificationChannel.enableLights(true);
notificationChannel.setLightColor(Color.RED);
notificationChannel.setShowBadge(true);
notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
if (manager != null) {
manager.createNotificationChannel(notificationChannel);
}
Bitmap icon = BitmapFactory.decodeResource(getResources(), R.drawable.background_running);
Notification notification = new Notification.Builder(getApplicationContext())
.setChannelId(CHANNEL_ONE_ID)
.setContentTitle("Recording data")
.setContentText("ActivityLog is logging data")
.setSmallIcon(R.drawable.background_running)
.setLargeIcon(icon)
.build();
Intent notificationIntent = new Intent(getApplicationContext(), MainActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
notification.contentIntent = PendingIntent.getActivity(getApplicationContext(), 0, notificationIntent, 0);
startForeground(101, notification);
}
//if version 26
else{
startForeground(101, updateNotification());
}
}
//if less than version 26
else{
Notification notification = new NotificationCompat.Builder(this)
.setContentTitle("Activity logger")
.setContentText("data recording on going")
.setSmallIcon(R.drawable.background_running)
.setOngoing(true).build();
startForeground(101, notification);
}
}
private Notification updateNotification() {
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
new Intent(this, MainActivity.class), 0);
return new NotificationCompat.Builder(this)
.setContentTitle("Activity log")
.setTicker("Ticker")
.setContentText("recording of data is on going")
.setSmallIcon(R.drawable.activity_log_icon)
.setContentIntent(pendingIntent)
.setOngoing(true).build();
}
private void detectingDeterminateOfServiceCall(Bundle b) {
if(b != null){
Log.i("screenService", "bundle not null");
if(b.getBoolean("phone restarted")){
storeInternally("Phone restarted");
}
}else{
Log.i("screenService", " bundle equals null");
}
documentServiceStart();
}
private void documentServiceStart() {
Log.i("screenService", "started running");
}
private void registerBroadcastReceivers() {
screenReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
switch (Objects.requireNonNull(intent.getAction())){
case Intent.ACTION_SCREEN_ON:
//or do something else
storeInternally("Screen on");
break;
case Intent.ACTION_SCREEN_OFF:
//or do something else
storeInternally("Screen off");
break;
}
}
};
IntentFilter screenFilter = new IntentFilter();
screenFilter.addAction(Intent.ACTION_SCREEN_ON);
screenFilter.addAction(Intent.ACTION_SCREEN_OFF);
registerReceiver(screenReceiver, screenFilter);
}
#Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(screenReceiver);
}
and call it from the main activity:
private void startServiceRunning() {
if(!isMyServiceRunning(Background.class)){
if(Build.VERSION.SDK_INT >25){
startForegroundService(new Intent(this, Background.class));
}else{
startService(new Intent(this, Background.class));
}
}
}
As Background Execution Limit imposes on Android 8.0 (API level 26) so now it's not possible to listen SCREEN_OFF and SCREEN_ON action in background by running the service.
I have found a work around for same with the help of JobScheduler which works fine for listen broadcast in background without running any service.
Please check on this: Screen OFF/ON broadcast listener without service on Android Oreo
Instead of creating a new service for broadcast receiver, you can directly create a broadcast receiver class that will listen to system broadcasts even when the app is not running.
Create a new class which extends BroadcastReceiver.
public class YourReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//Do your stuff
}
}
And register it in manifest.
<receiver
android:name=".YourReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.ACTION_SCREEN_ON" />
<action android:name="android.intent.action. ACTION_SCREEN_OFF" />
<category android:name="android.intent.category.DEFAUL" />
</intent-filter>
</receiver>
Read about Manifest-declared receivers here.
Above solution won't work, here is the reason why. Problem is that your service is getting killed when the app is killed, so your receiver instance is removed from memory. Here is a little trick to re-start the service in background. Add the following code to your service.
#Override
public void onTaskRemoved(Intent rootIntent){
Intent restartServiceIntent = new Intent(getApplicationContext(), this.getClass());
restartServiceIntent.setPackage(getPackageName());
PendingIntent restartServicePendingIntent = PendingIntent.getService(getApplicationContext(), 1, restartServiceIntent, PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmService = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
alarmService.set(
AlarmManager.ELAPSED_REALTIME,
SystemClock.elapsedRealtime() + 1000,
restartServicePendingIntent);
super.onTaskRemoved(rootIntent);
}
Although this is not the right way to do it. Also in Android 26+ you won't be able to do this and you'd go for foreground service. https://developer.android.com/about/versions/oreo/background
I've an app where the user can call custom lock screen to lock his/her mobile, that is an activity called LockScreen.class.
One this screen is loaded, i.e. the deviced is locked, a SharedPreferences called IsLocked is assigned to be true.
once the user do what he need with tthe lock screen this islocked became false, and the mobile is back to normal.
Every hing is working fine as expected.
The problem is, if for some reason the mobile had been rebooted while the lock screen is active, it is not running back upon a reboot.
So, I created a BootReciever as below, this works fine BUT after having the reboot process completed, and the user can do many things before it is loaded, my question is how can I make it loaded faster? so that the mobile screen is locked again with the custom activity before giving the chance for the user to do anything with the mobile?
public class BootReciever extends BroadcastReceiver
{
SharedPreferences mPrefs;
final String IsLockedPref = "IsLocked";
#Override
public void onReceive(Context context, Intent intent) {
mPrefs = PreferenceManager.getDefaultSharedPreferences(context);
Boolean islocked = mPrefs.getBoolean(IsLockedPref, false);
Intent i;
if (islocked)
i = new Intent(context, LockScreen.class);
else
i = new Intent(context, MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
}
part of the manifiest file is:
<receiver android:name=".BootReciever"
android:enabled="true"
android:exported="true">
<intent-filter >
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
</intent-filter>
</receiver>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
UPDATE
I tried to get use of this by granting Device Admin by adding the below, but nothing improved:
In the main Activity:
private static final int ADMIN_INTENT = 15;
private static final String description = "Some Description About Your Admin";
private DevicePolicyManager mDevicePolicyManager;
private ComponentName mComponentName;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mDevicePolicyManager = (DevicePolicyManager)getSystemService(
this.DEVICE_POLICY_SERVICE);
mComponentName = new ComponentName(this, AdminReceiver.class);
Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, mComponentName);
intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION,description);
startActivityForResult(intent, ADMIN_INTENT);
.
.
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == ADMIN_INTENT) {
if (resultCode == RESULT_OK) {
Toast.makeText(getApplicationContext(), "Registered As Admin", Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(getApplicationContext(), "Failed to register as Admin", Toast.LENGTH_SHORT).show();
}
}
}
and created empty receiver to extend the DeviceAdminReceiver as:
public class AdminReceiver extends DeviceAdminReceiver {
}
and added the below to the manifiest:
<receiver
android:name="AdminReceiver"
android:permission="android.permission.BIND_DEVICE_ADMIN">
<meta-data
android:name="android.app.device_admin"
android:resource="#xml/admin"/>
<intent-filter>
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
</intent-filter>
</receiver>
One thing you can do from your side is to set a priority to your intent-filter. From documentation
It controls the order in which broadcast receivers are executed to receive broadcast messages. Those with higher priority values are called before those with lower values.
<intent-filter
android:priority="100">
...
</intent-filter>
The value must be an integer, such as "100". Higher numbers have a higher priority. The default value is 0. The value must be greater than -1000 and less than 1000.
I've created an app that listens for the last installed app on my phone, and notifies me when a new app was installed. Right now it is correctly notifying me for the last installed app, but it also notifies me when any apps are updated. Does anyone know how to JUST listen for the last installed app, and not listen for when an app goes through an update?
Here is my code:
public class NewInstallReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("tag_name", "NewInstallReceiver" + intent.getAction());
final PackageManager pm = context.getPackageManager();
ApplicationInfo ai;
try {
ai = pm.getApplicationInfo(intent.getData().getSchemeSpecificPart(), 0);
Log.d("tag_name", "Application Info" + ai);
} catch (final PackageManager.NameNotFoundException e) {
ai = null;
}
List<PackageInfo> packages = pm.getInstalledPackages(PackageManager.GET_META_DATA);
Collections.sort(packages, new Comparator<PackageInfo>() {
#Override
public int compare(PackageInfo p1, PackageInfo p2) {
return Long.toString(p2.firstInstallTime).compareTo(Long.toString(p1.firstInstallTime));
}
});
}
}
My intent filters for Broadcast Receiver
<receiver android:name="com.example.natalie.listener.NewInstallReceiver">
<intent-filter android:priority="100">
<action
android:name="android.intent.action.PACKAGE_INSTALL"/>
<action
android:name="android.intent.action.PACKAGE_ADDED"/>
<action
android:name="android.intent.action.PACKAGE_DATA_CLEARED"/>
<action
android:name="android.intent.action.PACKAGE_REMOVED"/>
<data android:scheme="package"/>
</intent-filter>
</receiver>
With this code you can see a application was installed on your phone before :
PackageManager pm = context.getPackageManager();
ApplicationInfo appInfo = pm.getApplicationInfo("application package name", 0);
String appFile = appInfo.sourceDir;
long installed = new File(appFile).lastModified();