I'm trying to create an application that allow the user to lock his android device with a password from a website. So I must find a method to lock the device programmatically, it means is there anyone that have a code that allow me to set a password for the device and when I unlock my screen it demands to enter the code to access to the home? Basically, what I'm trying to create is a app where device owners can lock the device from the website. The android app will be calling an api every 10 min checking for lock command. Currently I'm struggling to lock device with this code.
Policies.xml
<?xml version="1.0" encoding="utf-8"?>
<device-admin xmlns:android="http://schemas.android.com/apk/res/android" >
<uses-policies>
<force-lock />
<reset-password/>
</uses-policies>
</device-admin>
MainActivity
lock.setOnClickListener(v -> {
//Keep the CPU running while screen is off
wakeLock.acquire();
SecureRandom secureRandom = new SecureRandom();
byte[] token = secureRandom.generateSeed(32);
DevicePolicyManager devicePolicyManager = (DevicePolicyManager) getApplicationContext().getSystemService(
DEVICE_POLICY_SERVICE);
if (devicePolicyManager != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
devicePolicyManager.setResetPasswordToken(compName, token);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
devicePolicyManager.resetPasswordWithToken(compName, "4321", token, 0);
}
}
//Lock the screen
deviceManger.lockNow() ;
//Wait 5 secs before starting the next activity
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
Intent intent = new Intent(MainActivity.this,MainActivity2.class);
MainActivity.this.startActivity(intent);
//Release cpu
wakeLock.release();
}
},5000);
});
Related
I developed this app that needs to send data to Firestore when user press a button and ends when user stop it (by pressing another button). The data must be sent even if the user is doing other things or even if the user leavs the phone in standby for hours (so i need to avoid Doze and App Standby).
I used a service to achieve this and just one thing seems to work in the wrong way.
Service
public class MyService extends Service {
public static final String CHANNEL_ID = "ForegroundServiceChannel";
// vars declaration
private Date date = null;
// get every X seconds
public static final long DEFAULT_SYNC_INTERVAL = 60000;
private Runnable runnableService = new Runnable() {
#Override
public void run() {
class GetDataTask extends AsyncTask<String, Void, List<Data>> {
#Override
protected void onPreExecute() {
super.onPreExecute();
if(getPositionData.isCancelled()){
return;
}
}
#SuppressLint({"MissingPermission", "HardwareIds"})
#Override
protected List<Data> doInBackground(String... v) {
// skipping get Timestamp code
// skipping get position code
myPos = new Data(position.getId(), latitude, longitude, timestamp);
// Insert data into Firebase
documentReference = firebaseFirestore.collection("data").document();
Map<String, Object> data = new HashMap<>();
data.put("lat", myPos.getLat());
data.put("date", myPos.getDate().toString());
documentReference.set(data).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Log.i("data", "data added.\n");
}
});
Toast.makeText(DataPollService.this, "" +
"ID: " + myPos.getImei()
+ " Latitude: " + myPos.getLat()
+ " Longitude " + myPos.getLng()
+ " Date: " + myPos.getDate()
, Toast.LENGTH_SHORT).show();
}
}
}, Looper.getMainLooper());
positionsList.add(myPos);
return positionsList;
}
protected void onPostExecute(List<Data> result) {
Position.getInstance().setPositions(result);
}
}
// RUN TASK
getPositionData = new GetDataTask();
getPositionData.execute(position.getId());
handler.postDelayed(runnableService, DEFAULT_SYNC_INTERVAL);
}
};
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
String input = intent.getStringExtra("inputExtra");
createNotificationChannel();
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,
0, notificationIntent, 0);
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("Foreground Service")
.setContentText(input)
.setSmallIcon(R.drawable.ksurf)
.setContentIntent(pendingIntent)
.build();
startForeground(1, notification);
handler = new Handler();
handler.post(runnableService);
return START_NOT_STICKY;
}
// onBind
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
Toast.makeText(this, "Service Stopped", Toast.LENGTH_LONG).show();
Log.d("show", "onDestroy");
handler.removeCallbacks(runnableService);
stopSelf();
}
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel serviceChannel = new NotificationChannel(
CHANNEL_ID,
"Foreground Service Channel",
NotificationManager.IMPORTANCE_DEFAULT
);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(serviceChannel);
}
}
}
In MainActivity starting the service like this:
Intent serviceIntent = new Intent(this, MyService.class);
serviceIntent.putExtra("inputExtra", "run");
ContextCompat.startForegroundService(this, serviceIntent);
If I don't use the phone and let the app sending data in background, the data are not sent to Firebase until I open the app back again. The service is not stopped, I just need to open the app in order to send data to firebase!
I read about Firebase Cloud Messaging but I didn't understand if I need them for my purpose. What am I doing wrong?
The data must be sent even if the user is doing other things or even if the user leavs the phone in standby for hours (so i need to avoid Doze and App Standby).
Generally speaking, it is not a good idea to have your app running processes when in Doze or App Standby mode. The Android documentation even points out that Network access is suspended; and therefore, your process might not be guaranteed to run reliably or terminate over other apps that may have a higher priority.
The problem is that if I don't use app for like 1 hour (so phone is in standby) data on firebase are only added when I open the app again. It's like they are saved in cache and sent to DB when app is opened again.
According to the documentation, "Cloud Firestore supports offline data persistence. This feature caches a copy of the Cloud Firestore data that your app is actively using, so your app can access the data when the device is offline. You can write, read, listen to, and query the cached data. When the device comes back online, Cloud Firestore synchronizes any local changes made by your app to the Cloud Firestore backend."
The service is not stopped, I just need to open the app in order to send data to firebase! I read about Firebase Cloud Messaging but I didn't understand if I need them for my purpose.
A recommended solution would to ping your app from your server using Firebase Cloud Messaging when your client app goes into idle mode. This feature is useful when you need to send real-time downstream messages to your backend server or simply notify your client app that new data is available to sync (which may be what you're looking for).
You can refer to the above documentation for further details.
in every platform or language, there is a deferent way to connect to the firebase, so, please more information about the platform can help ??,
but you can check this link maybe his can to help you -> link
I want to run my app in background if I kill the app instance also. But after I kill my app the service also stops working. Here is my code please any one help me to solve my issue.
I followed this link for running in the background but it is not working if I remove the instance. Please can any one show me how to run a background service if the instance is removed also?
This is my MainActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ctx = this;
setContentView(R.layout.activity_main);
Intent alarmIntent = new Intent(MainActivity.this, AlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(MainActivity.this, ALARM_REQUEST_CODE, alarmIntent, 0);
mSensorService = new SensorService(getCtx());
mServiceIntent = new Intent(getCtx(), mSensorService.getClass());
if (!isMyServiceRunning(mSensorService.getClass())) {
startService(mServiceIntent);
}
}
Ths is my service class
public class SensorService extends Service{
public int counter=0;
public SensorService(Context applicationContext) {
super();
Log.i("HERE", "here I am!");
}
public SensorService() {
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
startTimer();
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Log.i("EXIT", "ondestroy!");
Intent broadcastIntent = new Intent("uk.ac.shef.oak.ActivityRecognition.RestartSensor");
sendBroadcast(broadcastIntent);
}
private Timer timer;
private TimerTask timerTask;
long oldTime=0;
public void startTimer() {
//set a new Timer
timer = new Timer();
//initialize the TimerTask's job
initializeTimerTask();
//schedule the timer, to wake up every 1 second
timer.schedule(timerTask, 1000, 1000); //
}
/**
* it sets the timer to print the counter every x seconds
*/
public void initializeTimerTask() {
timerTask = new TimerTask() {
public void run() {
Log.i("in timer", "in timer ++++ "+ (counter++));
}
};
}
/**
* not needed
*/
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
Its a long story. I have gone through it. Still implemented it. Now my service runs on every boot_complete event and keeps running all the time ( with a notification ).
Official Documentation:
Big NO. Google android developer documentation is poor, with no proper sample example too. It is theoretical and just theoretical. Keep reading if interested
https://developer.android.com/about/versions/oreo/background
Synopsis 1:
You can only receive BOOT_COMPLETE and only few broadcasts in traditional receiver. Rest all broadcast receivers you need to implement runtime in a service by registering them through a code from service which always runs.
Synopsis 2:
Again, you can not have always running processes in or above 8.0 (Oreo)...
To achieve always running process... Create a Intentservice with proper notification of type ongoing and make OnStartCommand START_STICKY and register receiver with code in OnCreate
How to implement it :
I have implemented it take reference from here :
Oreo: Broadcast receiver Not working
Now Your Question : I want to run my app in background if it kills the
app instance also.
With the help of above implementation link of my own you can achieve it
*Terms and conditions
You device must have proper android operating system released and burnt as it is.
Yes, I am using android :
No... You are Using Funtouch OS : VIVO ( By modifying Android)
There are many devices in market COLOR OS : OPPO ( By modifying Android)
....
....
Already google has made it complicated... version by version....
With no proper documentation and sample codes....
And Now Independent mobile device manufacturers making a lot of
changes to allow only selective applications run in background
like WhatsApp, Facebook, Google Twitter Instagram
Now you will ask a developer question If these app runs in background then I can make my app run in background too....
No... They are OS based modifications to check if a service is from allowed vendors then only it can be alive there in background. If they will not allow these vendors then no one take phones which does not run these famous social apps.
Hushhhhhhhh.......
You need to create ForegroundService in order continue processing when your app is killed, as follows:
public class SensorService extends Service{
private PowerManager.WakeLock wakeLock;
#Override
public void onCreate() {
super.onCreate();
//wake lock is need to keep timer alive when device goes to sleep mode
final PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "PARTIAL_WAKE_LOCK_TAG");
createNotificationChannel(this);
Notification notification = new NotificationCompat.Builder(this, "NOTIFICATION_CHANNEL").setSmallIcon
(<icon>).setContentTitle("Title")
.setContentText("Content").build();
startForeground(1001, notification);
}
#Override
public void onDestroy() {
super.onDestroy();
if (wakeLock.isHeld()) {
wakeLock.release();
}
}
public void createNotificationChannel() {
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = "Channel name";
String description = "Description";
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel("NOTIFICATION_CHANNEL", name, importance);
channel.setDescription(description);
NotificationManager notificationManager = getApplicationContext().getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
}
}
To start the service:
Intent i = new Intent(context, SensorService.class);
ContextCompat.startForegroundService(context, i)
Note:
You cannot run service endlessly with this approach. During doze mode if OS recognizes it as CPU intensive then your Service will be terminated.
You need to call stopSelf() when your Timer task has been executed successfully.
Oreo Introduced
new Concept PIP (Picture in Picture Mode )
and it have categories services control by making channels and priority to them.you have to change the code just for oreo to create notifications and services
read about google developers documentation carefully here
https://developer.android.com/guide/topics/ui/notifiers/notifications
both java and kotlin code is available here to create notification in oreo
https://developer.android.com/training/notify-user/build-notification
it was my effort to find the solution after searching and sharing with you.
here is some sample code :
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("My notification")
.setContentText("Much longer text that cannot fit one line...")
.setStyle(new NotificationCompat.BigTextStyle()
.bigText("Much longer text that cannot fit one line..."))
.setPriority(NotificationCompat.PRIORITY_DEFAULT);
for creating channels write this code:
private void createNotificationChannel() {
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = getString(R.string.channel_name);
String description = getString(R.string.channel_description);
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
channel.setDescription(description);
// Register the channel with the system; you can't change the importance
// or other notification behaviors after this
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
}
you can see full detials for push notifications and sending messages by clicking on the above links.
I am using geofence in my app and based on geofence events (Enter or Exit) I want to perform some action. Geofence documentation says that once you set geofence it will trigger events automatically and you can catch this events with IntentService. For that I have made intentservice as below:
GeofenceTransitionsIntentService.java
public class GeofenceTransitionsIntentService extends IntentService {
Handler mHandler;
public GeofenceTransitionsIntentService() {
super("GeofenceTransitionsIntentService");
mHandler = new Handler();
}
#Override
public void onCreate() {
super.onCreate();
Log.e("JK-->>","service started!");
}
#Override
protected void onHandleIntent(Intent intent) {
Log.e("JK-->>","onHandel--->>");
GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
if (geofencingEvent.hasError()) {
Log.e("JK-->>","geofenceEvent has error!");
return;
}
int geofenceTransitionType = geofencingEvent.getGeofenceTransition();
if (geofenceTransitionType == Geofence.GEOFENCE_TRANSITION_ENTER) {
Log.e("JK-->>","enter!");
mHandler.post(new DisplayToast(this,"Enter"));
} else if (geofenceTransitionType == Geofence.GEOFENCE_TRANSITION_EXIT) {
mHandler.post(new DisplayToast(this,"Exit"));
Log.e("JK-->>","exit");
}
}
public class DisplayToast implements Runnable {
private final Context mContext;
String mText;
public DisplayToast(Context mContext, String text){
this.mContext = mContext;
mText = text;
}
public void run(){
Toast.makeText(mContext, mText, Toast.LENGTH_SHORT).show();
}
}
}
Now, problem is that when app is open(No matter foreground or background) and I enter or exit in geofence it works fine and show me a toast message and logcat shows log but when I remove app from recent apps there is no toast message showing to me or no log is showing in logcat.
I have tried to find solution on google but mostly all answers suggests to use the service but if i am not wrong then IntentService stops itself automatically after work is done and start itself when any intent received. So, I think it's more efficient to use IntentService to do this task.
UPDATE
I am registering geofence using following line of code.
geofencingClient.addGeofences(getGeofencingRequest(),getGeofencePendingIntent());
and in getGeofencePendingIntent() i am starting intent service using following line of code.
private PendingIntent getGeofencePendingIntent() {
if(geofencePendingIntent != null)
return geofencePendingIntent;
Intent in = new Intent(SetProfileOnlineActivity.this,GeofenceTransitionsIntentService.class);
geofencePendingIntent = PendingIntent.getService(SetProfileOnlineActivity.this,111451,in,PendingIntent.FLAG_UPDATE_CURRENT);
return geofencePendingIntent;
}
This Service will run always :
Goto project java -> right click->New->service->service
name it watchman
watchman.java
public class watchman extends Service
{
NotificationManager mNotifyManager;
NotificationCompat.Builder mBuilder;
NotificationChannel notificationChannel;
String NOTIFICATION_CHANNEL_ID = "1";
public watchman() { }
#Override
public void onCreate()
{
try
{
mNotifyManager = (NotificationManager) getApplicationContext().getSystemService(NOTIFICATION_SERVICE);
mBuilder = new NotificationCompat.Builder(this, null);
mBuilder.setContentTitle("Insta Promo")
.setContentText("We are ready to help you.")
.setSmallIcon(R.drawable.ic_launcher_background);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "My Notifications", NotificationManager.IMPORTANCE_HIGH);
// Configure the notification channel.
notificationChannel.setDescription("Channel description");
notificationChannel.enableLights(true);
notificationChannel.setLightColor(Color.RED);
notificationChannel.setVibrationPattern(new long[]{0, 1000, 500, 1000});
notificationChannel.enableVibration(true);
notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
mNotifyManager.createNotificationChannel(notificationChannel);
}
else
{
mBuilder.setContentTitle("Insta Promo")
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setColor(ContextCompat.getColor(this, R.color.colorAccent))
.setVibrate(new long[]{100, 250})
.setLights(Color.YELLOW, 500, 5000)
.setAutoCancel(true);
}
mBuilder.setChannelId(NOTIFICATION_CHANNEL_ID);
mNotifyManager.notify(1, mBuilder.build());
startForeground(1, mBuilder.build());
}
catch(Exception e)
{
Log.d(TAG, "EXCEPTION IN SHOWING NOTIFICATION xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...\n");
Log.e("MY_APP", "exception", e);
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
new Thread(new Runnable()
{
public void run()
{
while (true)
{
try
{
Log.d(TAG, "Thread : Running again...\n");
Thread.sleep(10000);
}
catch (InterruptedException e)
{
Log.d(TAG, "Thread : InterruptedException Error in service...\n");
}
}
}
}).start();
return START_STICKY;
}
#Override
public void onDestroy()
{
super.onDestroy();
}
#Override
public IBinder onBind(Intent intent)
{
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
}
It will get automatically registered in manifest file as you created it as service, no need to update manifest file.
From main activity or from wherever you want to start it call it like
Log.d(TAG, " Good to Go \n");
Log.d(TAG, "Starting Service from main...\n");
Intent intent = new Intent(MainActivity.this, watchman.class);
startService(intent);
Log.d(TAG, "Main has started the service...\n");
Now you even if removed it from recents..., It will be there in memory running always for you, To check it keep eye on logcat. Hope it helps. Its working in project from 4.1 onwards upto latest 8.0 oreo
for showing notifications i am using vibration permission so also making manifest file available for you.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.rushi.oreo">
<uses-permission android:name="android.permission.VIBRATE"/>
<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">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".watchman"
android:enabled="true"
android:exported="true" />
</application>
</manifest>
Hope it really helps you or someone else.
IntentService will stop automatically when the work assigned to it is finished.
If you want a service to run in background with very less chances of getting stopped, it has to be a Foreground Service. Please make sure to start your Service in a background worker thread because by default a Service runs on the main thread.
More details are here - https://developer.android.com/reference/android/app/Service.html#startForeground(int, android.app.Notification)
But please note that making a Service as foreground impacts your phone's battery life too much. And a making a Service as Foreground is also annoying to the user since it shows a notification always and cannot be closed.
You can better use a JobScheduler or Firebase JobDispatcher to schedule background works.
I had found an answer... there was no problem in my code and IntentService was also working perfectly but the mistake was in the testing. I was testing my application on android Oreo running device.
In android oreo google has updated their policy that in foreground they will send location updates any number of times but in background they will send location updates only few times in hour.
The main reason behind it to save the bettery life of device.
For more information about android oreo location updates you can check out this documentation.
I have read plenty of tutorial and posts here on SO regarding the use of WakeLock and WifiLock, but still didn't get to a solution of my issue.
I'm writing an app that has, when you start it, the only effect of creating and starting a (foreground) service. This service run two threads that are an UDP broadcast listener (using java.io) and a TCP server (using java.nio). In the onCreate of the service I acquire a wakelock and a wifilock, and I release them in the onDestroy.
Everything works fine as far as the phone is awake, but when the display goes off the UDP broadcast receiver stops receiving broadcast messages, and will not receive any until I switch on again the display. Practically, the locks are not working at all and there is no difference in put them...where am I wrong? I'm sure I'm doing something stupid somewhere, but can't find it by myself.
Here is some code:
This is what Activity does:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
onlyStartService = true;
}#Override
protected void onStart() {
super.onStart();
Intent bIntent = new Intent(this, FatLinkService.class);
getApplicationContext().startService(bIntent);
getApplicationContext().bindService(bIntent, flConnection, BIND_AUTO_CREATE);
}
// service connection to bind idle service
private ServiceConnection flConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder binder) {
linkService.MyLinkBinder flBinder = (LinkService.MylinkBinder) binder;
flServiceInstance = flBinder.getService();
if (onlyStartService) {
condLog("Service bound and finishing activity...");
finish();
}
}
public void onServiceDisconnected(ComponentName className) {
flServiceInstance = null;
}
};
#Override
protected void onStop() {
super.onStop();
if (fatFinish) {
Intent bIntent = new Intent(this, FatLinkService.class);
flServiceInstance.stopServices();
flServiceInstance.stopForeground(true);
flServiceInstance.stopService(bIntent);
condLog("Service stop and unbound");
flServiceInstance = null;
}
getApplicationContext().unbindService(flConnection);
}
This is how service is:
public class LinkService extends Service {
InetAddress iaIpAddr, iaNetMask, iaBroadcast;
private final IBinder mBinder = new MyLinkBinder();
private linklistenBroadcast flBroadServer = null;
private linkTCPServer flTCPServer = null;
private linkUDPClient flBroadClient = null;
List<String> tokens = new ArrayList<String>();
private PowerManager.WakeLock wakeLock;
private WifiManager.WifiLock wifiLock;
public class MylLinkBinder extends Binder {
lLinkService getService() { return LinkService.this; }
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
#Override
public void onCreate() {
super.onCreate();
getLocks();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
instantiateServices();
// notifies presence to other fat devices
condLog("Service notifying fat presence...");
flBroadClient = new LinkUDPClient();
flBroadClient.startSending(LinkProtocolConstants.BRCMD_PRESENCE + String.valueOf(LinkProtocolConstants.tcpPort), iaBroadcast, LinkProtocolConstants.brPort);
return START_STICKY;
}
public void getLocks() {
// acquire a WakeLock to keep the CPU running
condLog("Acquiring power lock");
WifiManager wm = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
wifiLock = wm.createWifiLock(WifiManager.WIFI_MODE_FULL , "MyWifiLock");
wifiLock.acquire();
PowerManager pm = (PowerManager) getApplicationContext().getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyWakeLock");
wakeLock.acquire();
}
public void stopServices() {
if (flTCPServer != null)
flTCPServer.stopServer();
if (flBroadServer != null)
flBroadServer.stopSelf();
}
private void instantiateServices() {
populateAddresses(); // just obtain iaIpAddr
if (flTCPServer == null) {
condLog("Instantiating TCP server");
flTCPServer = new LinkTCPServer(iaIpAddr, FatLinkProtocolConstants.tcpPort);
flTCPServer.execute();
}
if (flBroadServer == null) {
condLog("Instantiating UDP broadcast server");
Intent notifyIntent = new Intent(this, LinkMain.class); // this is the main Activity class
notifyIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
notifyIntent.setAction("FROM_NOTIFICATION");
PendingIntent notifyPIntent = PendingIntent.getActivity(this, 0, notifyIntent, 0);
Notification fixNotification = new Notification.Builder(getApplicationContext())
.setContentTitle("Link")
.setSmallIcon(R.mipmap.imgLink)
.setContentIntent(notifyPIntent)
.build();
startForeground(1234, fixNotification);
flBroadServer = new LinklistenBroadcast();
flBroadServer.start();
}
}
private final class LinklistenBroadcast extends Thread {
private boolean bStopSelf = false;
DatagramSocket socket;
public void stopSelf() {
bStopSelf = true;
socket.close();
}
#Override
public void run() {
condLog( "Listening broadcast thread started");
bStopSelf = false;
try {
//Keep a socket open to listen to all the UDP trafic that is destinated for this port
socket = new DatagramSocket(null);
socket.setReuseAddress(true);
socket.setSoTimeout(LinkGeneric.BR_SOTIMEOUT_MILS);
socket.setBroadcast(true);
socket.bind(new InetSocketAddress(InetAddress.getByName("0.0.0.0"), FatLinkProtocolConstants.brPort));
while (true) {
condLog("Ready to receive broadcast packets...");
//Receive a packet
byte[] recvBuf = new byte[1500];
DatagramPacket packet = new DatagramPacket(recvBuf, recvBuf.length);
try {
socket.receive(packet);
} catch (InterruptedIOException sException) {
condLog(sockExcept.toString());
break;
} catch (SocketException sockExcept) {
condLog(sockExcept.toString());
}
if (bStopSelf) {
condLog("Broadcast server stopped...");
break;
}
int len = packet.getLength();
String datarecvd = new String(packet.getData()).trim();
//datarecvd = datarecvd.substring(0, len);
//Packet received
String message = new String(packet.getData()).trim();
condLog("<<< broadcast packet received from: " + packet.getAddress().getHostAddress() + " on port: " + packet.getPort() + ", message: " + message);
if (packet.getAddress().equals(iaIpAddr)) {
condLog("Ooops, it's me! discarding packet...");
continue;
}
else
condLog("<<< Packet received; data size: " + len + " bytes, data: " + datarecvd);
//See if the packet holds the right command (message)
// protocol decode
// here do some tuff
} catch (IOException ex) {
condLog(ex.toString());
}
if (socket.isBound()) {
condLog( "Closing socket");
socket.close();
}
condLog( "UDP server thread end.");
flTCPServer = null;
flBroadServer = null;
}
public boolean isThreadRunning() {
return !bStopSelf;
};
}
// Utility functions
public boolean checkBroadcastConnection (DatagramSocket socket, int timeOutcycles) {
int tries = 0;
while (!socket.isConnected()) {
tries++;
if (tries >= timeOutcycles)
return false;
}
return true;
}
#Override
public void onDestroy() {
super.onDestroy();
if (wakeLock != null) {
if (wakeLock.isHeld()) {
wakeLock.release();
}
}
if (wifiLock != null) {
if (wifiLock.isHeld()) {
wifiLock.release();
}
}
}
}
And, finally, here is the manifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="xxxxxx.ink" >
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<application
android:allowBackup="true"
android:icon="#mipmap/imgLinkmascotte"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".LinkMain"
android:label="#string/app_name"
android:theme="#android:style/Theme.Translucent.NoTitleBar.Fullscreen">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".LinkService" />
</application>
</manifest>
I have read this, and I have the doubt the problem is the same but it is actually happening to me on all the phone I have tried (galaxy Tab 7.1, galaxy tag 10, Galaxy SIII, Galaxy Note 3 Neo, Galaxy SIII mini) with android releases from 4.0 to 4.4.
I have already tried the solution posted here, but anything changed (again...it is a bit frustrating).
I have even tried to set the "Keep wifi option in standby" to "Always" in all the phones I've tried, but still nothing.
I have studied the WakeFulIntentService class, that is supposed to work as everybody is saying that it is, but I can't see any significant different in my code.
I really hope someone can help me, I'm really stuck on this since last week.
EDIT: following the waqaslam answer, I have checked on a device that has "Wifi optimisation" option in Wifi-Advaced settings, and it actually works as soon as I uncked the option. So, now, the problem become: can I disable Wifi optimisation in devices that haven't that option shown in the advanced menu? as I wrote below in my comment, this seems not to be related to android release, as I have two devices (both Samsung) with 4.4.2 and they are not showing the option.
New EDIT: from the edited waqaslam answer, I have tried to add multicastlock to my service, but again anything changed. This is getting annoying, there's hardly something easy and clear to do with android.
thank you very much
C.
I think the problem is not with the WakeLocks but the Wi-Fi settings.
In newer versions of android, there's an additional setting in Settings -> Wi-Fi -> Advanced called Wi-Fi optimization, which (if turned-on) disables all the low priority communications (like listening to UDP broadcasts) when the display is off.
Disabling the option should allow your device to listen UDP broadcasts even when the display is switched-off.
You may also use WifiManager.MulticastLock in order to acquire WiFi lock that should listen to these special broadcasts when screen is switched-off.
WifiManager wifi = (WifiManager) this.getSystemService(Context.WIFI_SERVICE);
MulticastLock lock = wifi.createMulticastLock("lockWiFiMulticast");
lock.setReferenceCounted(false);
lock.acquire();
and when done with the lock, then call:
lock.release();
Also, don't forget to add the following permission to your manifest:
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
For more info, you may read this.
Writing that just to mark the post as answered. I finally realilzed that there is no solution, or at least there is no solution working well on "all" the phones with "all" the android distribution (or at least from JB).
I have solved my personal issue just revisiting the concept of my app, considering that:
- Sending UDP broadcast is always working even in idle mode
- TCP servers are not affected by WiFi optimisation.
thank you all for the help and suggestion
C.
May be the reason is this .
Starting from Android 6.0 (API level 23), Android introduces two
power-saving features that extend battery life for users by managing
how apps behave when a device is not connected to a power source. Doze
reduces battery consumption by deferring background CPU and network
activity for apps when the device is unused for long periods of time.
App Standby defers background network activity for apps with which the
user has not recently interacted
I create a lock screen widget app recently. It always has the exception:
( java.lang.SecurityException: No active admin owned by uid 10034 for policy #3)
I try many methods and can not eliminate the exception. I open the activity to realize the purpose of the lock screen when the condition was founded.
public class tempActivity extends Activity {
private static final String TAG = "tempActivity";
private DevicePolicyManager policyManager;
private ComponentName componentName;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.temp);
Log.e(TAG, "Activity created~");
policyManager = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
componentName = new ComponentName(this, AdminReceiver.class);
mylock();
}
private void mylock() {
boolean active = policyManager.isAdminActive(componentName);
if (!active) { // Without permission
Log.e(TAG, "No authority~");
activeManage(); // To get access
policyManager.lockNow(); // And lock screen
} else {
Log.e(TAG, "Has authority");
policyManager.lockNow(); // lock screen directly
}
this.finish();
}
private void activeManage() {
Log.e(TAG, "activeManage");
Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, componentName);
intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION, "developers:liushuaikobe");
startActivityForResult(intent, 1);
}
}
The point is when the device admin is not active, your call to prompt it (ACTION_ADD_DEVICE_ADMIN) only ensures that the user is shown the activation intent. If he or she chooses not to activate (and which is quite likely) the lock command in the next line will fail and give the error you are encountering now.
So, basically you can only prompt the users to activate the device admin, not force them.
Delete the lockNow call in the if not active block to avoid the error.
Hope this helps.
-SB
Try:
if(Build.VERSION.SDK_INT > 8){
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}