I tried making a app with the instructions from here:
https://developer.android.com/guide/topics/connectivity/nfc/nfc
But when I compile the code and hold a card against my phone, I get a weird sound
My nfc is turned on, and I have a oneplus 6 running android 9
When I check logcat I see that I'm getting an error:
56:27.888 7834-7850/com.appname D/DecorView: onWindowFocusChangedFromViewRoot hasFocus: true, DecorView#6302a6f[MainActivity]
2019-10-12 22:56:27.913 7834-7834/com.appname W/RenderThread: type=1400 audit(0.0:2504791): avc: denied { read } for name="u:object_r:vendor_default_prop:s0" dev="tmpfs" ino=21655 scontext=u:r:untrusted_app:s0:c16,c257,c512,c768 tcontext=u:object_r:vendor_default_prop:s0 tclass=file permissive=0
2019-10-12 22:56:27.928 7834-7880/com.appname E/libc: Access denied finding property "vendor.debug.egl.swapinterval"
Why am I getting this error instead of the textview displaying the info of the nfc card im scanning (I tried mulitple nfc cards but its gives the same error)
I found someone with somewhat of the same problem. they say you should follow the link and then watch comment #3. and then they say it has something to do with not being allowed to write to a tmp directory due to a security issue.
Please help me resolve this issue, here is my MainActivity.java:
package com.packagename;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.NfcAdapter.CreateNdefMessageCallback;
import android.nfc.NfcEvent;
import android.os.Bundle;
import android.os.Parcelable;
import android.renderscript.RenderScript;
import android.widget.TextView;
import android.widget.Toast;
import static android.nfc.NdefRecord.createMime;
public class MainActivity extends AppCompatActivity implements CreateNdefMessageCallback {
NfcAdapter nfcAdapter;
TextView textView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Check for available NFC Adapter
nfcAdapter = NfcAdapter.getDefaultAdapter(this);
if (nfcAdapter == null) {
Toast.makeText(this, "NFC is not available", Toast.LENGTH_LONG).show();
finish();
return;
}
// Register callback
nfcAdapter.setNdefPushMessageCallback(this, this);
}
#Override
public NdefMessage createNdefMessage(NfcEvent event) {
String text = ("Beam me up, Android!\n\n" +
"Beam Time: " + System.currentTimeMillis());
NdefMessage msg = new NdefMessage(
new NdefRecord[] { createMime(
"application/vnd.com.example.android.beam", text.getBytes())
/**
* The Android Application Record (AAR) is commented out. When a device
* receives a push with an AAR in it, the application specified in the AAR
* is guaranteed to run. The AAR overrides the tag dispatch system.
* You can add it back in to guarantee that this
* activity starts when receiving a beamed message. For now, this code
* uses the tag dispatch system.
*/
//,NdefRecord.createApplicationRecord("com.example.android.beam")
});
return msg;
}
#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);
}
/**
* Parses the NDEF Message from the intent and prints to the TextView
*/
void processIntent(Intent intent) {
textView = findViewById(R.id.textView);
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()));
}
}
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.packagename">
<uses-permission android:name="android.permission.NFC" />
<uses-feature android:name="android.hardware.nfc" />
<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>
</application>
</manifest>
and here a picture of my activity_main.xml:
Thanks!
As NFC reading is handled by the Android OS, this will always make a sound when the card is read.
Depending on what NDEF records on the card and what you application is trying to do determines what the OS does with the NFC data.
You can download a generic NFC Application like https://play.google.com/store/apps/details?id=com.wakdev.wdnfc&hl=en_US to check what is on the card and write some sample data for you application to read.
It looks like you are trying to run this app on 2 phones and get them to talk using the deprecated Android Beam functionality https://developer.android.com/reference/android/nfc/NfcAdapter.CreateNdefMessageCallback (Which I found was never reliable - which is why they are removing it)
But you say
Why am I getting this error instead of the textview displaying the
info of the nfc card im scanning
Which suggest you are trying to read an NFC card and the methods used are not for this.
The question is are you wanting to do with NFC?
1) Have a NFC card cause you APP to be launched by the Android OS?
Then use the data on the NFC some how.
If yes then you should just be putting the correct intent filters in your manifest and handle them in your MainActivity as you would do for any other intent, and the parsing the NDEF message from the intent data.
See https://developer.android.com/guide/components/intents-filters#ExampleFilters for some non NFC examples on how your App can register to the OS what Intent types it can handle.
2) In you App handle reading from the NFC card at certain times
This seems more what you are trying to do (and what my Apps do)
To do this you use enable the NFC Foreground dispatcher https://developer.android.com/reference/android/nfc/NfcAdapter.html#enableForegroundDispatch(android.app.Activity,%20android.app.PendingIntent,%20android.content.IntentFilter%5B%5D,%20java.lang.String%5B%5D%5B%5D)
I use the following type of code to do this in my Activity
public class ViewNFCCardsActivity extends AppCompatActivity {
private NfcAdapter mNfcAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_nfccards);
mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
}
#Override
protected void onResume() {
super.onResume();
IntentFilter tagDetected = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
IntentFilter ndefDetected = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
IntentFilter techDetected = new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED);
IntentFilter[] nfcIntentFilter = new IntentFilter[]{techDetected,tagDetected,ndefDetected};
try {
ndefDetected.addDataType("*/*");
} catch (IntentFilter.MalformedMimeTypeException e) {}
PendingIntent pendingIntent = PendingIntent.getActivity(
this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
if(mNfcAdapter!= null)
mNfcAdapter.enableForegroundDispatch(this, pendingIntent, nfcIntentFilter, null);
}
#Override
protected void onPause() {
super.onPause();
if(mNfcAdapter!= null)
mNfcAdapter.disableForegroundDispatch(this);
}
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
TextView textView = (TextView) findViewById(R.id.MessageText);
// High level way to get Ndef records from what is already been read from the tag
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
Parcelable[] rawMessages = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
if (rawMessages != null) {
// Only need the first message
NdefMessage msg = (NdefMessage) rawMessages[0];
// Only need the first record in message
String message = new String(msg.getRecords()[0].getPayload());
textView.setText(message);
}
}
}
The onResume stuff tells Android OS to send all NFC card type messages to my Application and the onNewIntent method gets the Intent passed to it by the OS and processes the Message if it is an NDEF message.
You can also when creating the Foreground Dispatcher in onResume add additional filters like
try {
ndefDetected.addDataType("custom/text");
} catch (IntentFilter.MalformedMimeTypeException e) {}
or remove filters for non NDEF cards (Usually add all types because I don't want other card types like contactless bank cards triggering other apps while my app is in the foreground)
Related
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.
How can I open Main Activity if user taps on push notification sent from OpenSignal. I wanted to override the default behaviour which was causing some issue when App was active. I added following line as per the doc
<meta-data android:name="com.onesignal.NotificationOpened.DEFAULT" android:value="DISABLE" />
Now if app is closed, how can i open MainActivity, and let it execute NotificationOpenedHandler.
Thank you.
If you still always want your launcher / main Activity to open / resume when tapping on a OneSignal notification add the following code to your Activity intead.
private static boolean activityStarted;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if ( activityStarted
&& getIntent() != null
&& (getIntent().getFlags() & Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
finish();
return;
}
activityStarted = true;
}
See Resume last Activity when opening a Notification instructions for more details.
If you need to do something more custom keep the manifest entry you noted above and add a OneSignal NotificationOpenedHandler to OneSignal.startInit in your Application class.
import com.onesignal.OneSignal;
public class YourAppClass extends Application {
#Override
public void onCreate() {
super.onCreate();
OneSignal.startInit(this)
.setNotificationOpenedHandler(new ExampleNotificationOpenedHandler())
.init();
}
// This fires when a notification is opened by tapping on it or one is received while the app is running.
private class ExampleNotificationOpenedHandler implements NotificationOpenedHandler {
#Override
public void notificationOpened(String message, JSONObject additionalData, boolean isActive) {
// The following can be used to open an Activity of your choice.
/*
Intent intent = new Intent(getApplication(), YourActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
*/
// Follow the instructions in the link below to prevent the launcher Activity from starting.
// https://documentation.onesignal.com/docs/android-notification-customizations#changing-the-open-action-of-a-notification
}
}
See 4. Add Optional NotificationOpenedHandler for more details on this callback.
I have a problem with my app. It is using nfc tags for some actions (opening/locking door).
The app has a intent-filter at the default activity:
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="application/de.juwei.myapplication" />
</intent-filter>
But it seems it is ignoring the mimeType setting complety because it is starting even if i attach an empty tag to the phone and also if i try to beam data from another phone.
The code simply doing this:
public class MainActivity extends ActionBarActivity {
private NfcAdapter mAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mAdapter = NfcAdapter.getDefaultAdapter(this);
Intent intent = getIntent();
// see if app was started from a tag
if (mAdapter != null && intent.getType() != null && intent.getType().equals("application/de.juwei.myapplication")) {
}
}
#Override
protected void onResume() {
super.onResume();
if (mAdapter != null) {
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, this.getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
mAdapter.enableForegroundDispatch(this, pendingIntent, null, null);
}
}
#Override
protected void onPause() {
super.onPause();
if (mAdapter != null) {
mAdapter.disableForegroundDispatch(this);
}
}
#Override
public void onNewIntent(Intent intent) {
if (mAdapter != null && intent.getType() != null && intent.getType().equals("application/de.juwei.myapplication")) {
// ... reading tag
}
}
}
getIntent() is null if the tag doesn't has my mimetype. So the app is just starting if for example holding to smartphones together trying to beam some data. The activity is also starting if i hold my sony smartwatch 3 to my phone...
The very strange thing is - if i try to reproduce this on a new app with just that simple code, the app is not starting on every nfc command.
But in my main app, there are no more nfc specific methods.
I am completly lost.
Does anyone know how to track/debug why the app is opening by every piece of nfc data?
Best regards,
Juergen
In enableForegroundDispatch method you have to add filters and techLists
For instance:
IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
try {
ndef.addDataType("*/*"); /* Handles all MIME based dispatches.
You should specify only the ones that you need. */
}
catch (MalformedMimeTypeException e) {
throw new RuntimeException("fail", e);
}
mFilters = new IntentFilter[] {
ndef,
};
mTechLists = new String[][] { new String[] { NfcF.class.getName() } };
NfcAdapter.enableForegroundDispatch(this, mPendingIntent, mFilters,
mTechLists);
Looks like the problem was the enableForegroundDispatch.
I commented out both calls at onResume and onPause and changed Manifest to android:launchMode="singleTask" and it seems to work.
Must be some nfc bug, i don't know.
However, within my first tests it seems to work now, the app isn't starting every time i hold a nfc tag on back of the device.
I have set up parse push notifications and I had my app crash when I tried to open it, now I found a work around my making a new java class and overriding onPushOpen like this:
public class Receiver extends ParsePushBroadcastReceiver {
#Override
public void onPushOpen(Context context, Intent intent) {
Intent i = new Intent(context, MainActivity.class);
i.putExtras(intent.getExtras());
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
}
But in order to still receive push notifications I still need this depreciated method in my MyApplication.java class PushService.setDefaultPushCallback(this, MainActivity.class);
How could I get rid of this depreciated method I have looked at this question where I got some help but it did not answer this part about the depreciated method. Exception when opening Parse push notification.
I was thinking that maybe this method could be over ridden but Im not sure if it acutely handles recvieving the push or more handles the push after it has been received?
#Override
public void onPushReceive(final Context c, Intent i) {
// Handle the received push
}
Thanks for the help in advance.
You are subclassing ParsePushBroadcastReceiver.
Then in manifest
<receiver
android:name=".Receiver " // your broadcastreceiver
android:exported="false" >
<intent-filter>
// youtr actions
</intent-filter>
</receiver>
In BroadCastReceiver
public class Receiver extends ParseBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
extras = intent.getExtras();
if(intent.hasExtra("com.parse.Data"))
{
try
{
json = new JSONObject(intent.getExtras().getString("com.parse.Data"));
int notificationtype = json.getInt("notificationtype"); // this is send on the sender side
switch(notificationtype)
{
case 1:
// show your custom notification. Refer android notification guide
break;
case 2:
//rest of the code
Note : If either "alert" or "title" are specified in the push, then a Notification is constructed using getNotification. So no alert and title on the sender side.
Read Managing Push Lifecycle #
https://www.parse.com/docs/push_guide#receiving/Android
Reference
https://www.parse.com/questions/how-suppress-push-notification-from-being-displayed
Ho do i lock my android phone programmatically ?
I tried following this example. But when i click on the enable button the Activity pops up for few milliseconds and then closes automatically
The log shows no error just this log
Log.i("DeviceAdminSample", "Admin enable FAILED!");
Can any one tell me how to lock the android screen (Like the lock when make to many attempts in pattern lock and the phone locks down)
Any help is appreciated
You have to make your app as admin, Read something over here
Create a new empty project and create a class called MyAdminReceiver that extends DeviceAdminReceiver like this
import android.app.admin.DeviceAdminReceiver;
public class MyAdminReceiver extends DeviceAdminReceiver{
}
Create a new folder called xml and create an .xml file for your admin rights called admin.xml and add the policies, in you case its locking the screen
<device-admin xmlns:android="http://schemas.android.com/apk/res/android" >
<uses-policies>
<force-lock />
</uses-policies>
</device-admin>
In your manifest add the receiver under Application tag
<receiver
android:name="MyAdminReceiver"
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>
And in your MainActivity.java add code like this
import android.app.Activity;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends Activity implements OnClickListener {
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);
setContentView(R.layout.activity_main);
mDevicePolicyManager = (DevicePolicyManager)getSystemService(
Context.DEVICE_POLICY_SERVICE);
mComponentName = new ComponentName(this, MyAdminReceiver.class);
Button btnEnableAdmin = (Button) findViewById(R.id.btnEnableAdmin);
Button btnDisableAdmin = (Button) findViewById(R.id.btnDisableAdmin);
Button btnLock = (Button) findViewById(R.id.btnLock);
btnEnableAdmin.setOnClickListener(this);
btnDisableAdmin.setOnClickListener(this);
btnLock.setOnClickListener(this);
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnEnableAdmin:
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);
break;
case R.id.btnDisableAdmin:
mDevicePolicyManager.removeActiveAdmin(mComponentName);
Toast.makeText(getApplicationContext(), "Admin registration removed", Toast.LENGTH_SHORT).show();
break;
case R.id.btnLock:
boolean isAdmin = mDevicePolicyManager.isAdminActive(mComponentName);
if (isAdmin) {
mDevicePolicyManager.lockNow();
}else{
Toast.makeText(getApplicationContext(), "Not Registered as admin", Toast.LENGTH_SHORT).show();
}
break;
}
}
#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();
}
}
}
}
Note: If you try to call the Intent for Admin Device other that from an Activity subclass there are chances you might get an error to use Intent.FLAG_ACTIVITY_NEW_TASK but when you use that your window might not pop like in your case so Try opening it from a subclass of an activity only
Also you cannot un-install your app unless it has not be unregistered as an admin
But when i click on the enable button the Activity pops up for few milliseconds and then closes automatically
The code shown in that sample will bring up the Settings application when clicked.
Can any one tell me how to lock the android screen
You use the code that you linked to. Here is my sample app showing the same basic thing.
Specifically:
You need to have a BroadcastReceiver in your manifest that is set up to be a device admin component
The user has to activate your app as a device admin
You then call lockNow() on DevicePolicyManager
Here is the developer documentation on the device admin APIs.