I am trying to set the device owner package on a device using NFC. The is mentioned in the Lollipop overview here:
To deploy and activate a device owner, you must perform an NFC data
transfer from a programming app to the device while the device is in
its unprovisioned state. This data transfer sends the same information
as in the provisioning intent described in Managed provisioning.
The reason is once this is set you can use the screen pinning feature to lock the device in a kiosk mode. I have been able to test the this kiosk mode by manually setting the device owner by placing a device_owner.xml file to data/system/ on a rooted device.
I have never used NFC before so I may be way off but I came up with the following NdefMessage based on the info here:
Properties properties = new Properties();
properties.setProperty(DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME, "com.my.package");
properties.setProperty(DevicePolicyManager.EXTRA_PROVISIONING_WIFI_SSID, "MyWiFiSSID");
properties.setProperty(DevicePolicyManager.EXTRA_PROVISIONING_WIFI_PASSWORD, "WifiPassword");
properties.setProperty(DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM, "C9AD9E082457819B54CF76255A400375E4127112");
properties.setProperty(DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION, "https://dl.dropboxusercontent.com/u/xxx/app-release.apk");
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutput out = new ObjectOutputStream(bos);
out.writeObject(properties);
byte[] yourBytes = bos.toByteArray();
NdefRecord ndefRecord = NdefRecord.createMime(DevicePolicyManager.MIME_TYPE_PROVISIONING_NFC, yourBytes);
NdefMessage msg = new NdefMessage(ndefRecord);
Sending this to a device that I have just restored with the Lollipop preview causes it to show:
Oops! Couldn't set up your device. Contact your IT department.
Its seems to be recognising the fact that it is receiving a provision request, but I do not think it is reading the properties I set, it does not try to connect the the wifi.
It appears you need to use the Properties.store
to correctly create the bytes for the NdefRecord.
Properties properties = new Properties();
properties.setProperty(...);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
OutputStream out = new ObjectOutputStream(bos);
properties.store(out, "");
byte[] bytes = bos.toByteArray();
NdefMessage msg = new NdefMessage(NdefRecord.createMime(DevicePolicyManager.MIME_TYPE_PROVISIONING_NFC, bytes));
Currently, I'm having an issue with it downloading my APK and the checksum failing. Not at all sure why.
I've been trying to get this to work over NFC too. I installed a simple app on my Nexus 4 (KitKat) with an activity:
@Override
protected void onResume() {
super.onResume();
try {
Properties properties = new Properties();
properties.setProperty(DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME, "com.deviceowner.app");
properties.setProperty(DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION, "https://docs.google.com/uc?export=download&id=........");
properties.setProperty(DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM, "6ee735dfb8090ab1862fecce430864e21a0e37");
properties.setProperty(DevicePolicyManager.EXTRA_PROVISIONING_WIFI_SSID, "wlan");
properties.setProperty(DevicePolicyManager.EXTRA_PROVISIONING_WIFI_PASSWORD, "XXXXXX");
properties.setProperty(DevicePolicyManager.EXTRA_PROVISIONING_WIFI_SECURITY_TYPE, "WPA2");
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutput out = new ObjectOutputStream(bos);
out.writeObject(properties);
byte[] yourBytes = bos.toByteArray();
NdefRecord ndefRecord = NdefRecord.createMime(DevicePolicyManager.MIME_TYPE_PROVISIONING_NFC, yourBytes);
NdefMessage msg = new NdefMessage(ndefRecord);
nfcAdapter.setNdefPushMessage(msg, this);
} catch (IOException e) {
e.printStackTrace();
}
}
I flashed my Nexus 7 flashed with the Lollipop preview image (razor-lpx13d-preview-ae4f461f.tgz) and gave it an NFC bump with the Nexus 4 when the Nexus 7 was un-provisioned (no setup - fresh after flashing) and got the same error message:
Oops! Couldn't set up your device. Contact your IT department.
Then I tried the same thing but this time after running through the initial device setup on the Nexus 7 (to the point where I could see the home screen). This time I got the message
Oops! This device is already set up
But this time, I was able to see some logging as I was able to setup USB debugging on the Nexus 7:
10-22 10:31:29.947 2610-2610/? D/NfcService﹕ LLCP Activation message
10-22 10:31:29.947 2610-2610/? I/NfcP2pLinkManager﹕ LLCP activated
10-22 10:31:29.947 2610-2610/? D/NfcP2pLinkManager﹕ onP2pInRange()
10-22 10:31:29.954 2610-2610/? W/AudioTrack﹕ AUDIO_OUTPUT_FLAG_FAST denied by client
10-22 10:31:29.962 184-547/? D/audio_hw_primary﹕ select_devices: out_snd_device(2: speaker) in_snd_device(0: none)
10-22 10:31:29.962 184-547/? D/ACDB-LOADER﹕ ACDB -> send_afe_cal
10-22 10:31:29.962 184-547/? D/audio_hw_primary﹕ enable_snd_device: snd_device(2: speaker)
10-22 10:31:29.974 184-547/? D/audio_hw_primary﹕ enable_audio_route: apply and update mixer path: low-latency-playback
10-22 10:31:29.981 2610-2610/? D/NfcP2pLinkManager﹕ Last registered callback is not running in the foreground.
10-22 10:31:29.987 2610-2610/? D/NfcP2pLinkManager﹕ Disabling default Beam behavior
10-22 10:31:29.987 2610-2610/? D/NfcP2pLinkManager﹕ mMessageToSend = null
10-22 10:31:29.987 2610-2610/? D/NfcP2pLinkManager﹕ mUrisToSend = null
10-22 10:31:29.996 2610-2610/? D/NfcP2pLinkManager﹕ Took 48 to get first LLCP PDU
10-22 10:31:30.599 3224-3224/? I/wpa_supplicant﹕ wlan0: CTRL-EVENT-SCAN-STARTED
10-22 10:31:31.741 2610-2610/? D/NfcP2pLinkManager﹕ onP2pReceiveComplete()
10-22 10:31:31.751 2610-2610/? D/NfcService﹕ mock NDEF tag, starting corresponding activity
10-22 10:31:31.751 2610-2610/? D/NfcService﹕ TAG: Tech [android.nfc.tech.Ndef]
10-22 10:31:31.757 2610-3275/? W/AudioTrack﹕ AUDIO_OUTPUT_FLAG_FAST denied by client
10-22 10:31:31.770 549-2765/? I/ActivityManager﹕ START u0 {flg=0x10008000 cmp=com.android.nfc/.NfcRootActivity (has extras)} from uid 1027 on display 0
10-22 10:31:31.795 7237-7237/? D/ManagedProvisioning﹕ Device owner provisioning activity ONDESTROY
10-22 10:31:31.827 2610-3275/? W/AudioTrack﹕ AUDIO_OUTPUT_FLAG_FAST denied by client
10-22 10:31:31.848 549-2335/? I/ActivityManager﹕ START u0 {act=android.nfc.action.NDEF_DISCOVERED typ=application/com.android.managedprovisioning cmp=com.android.managedprovisioning/.DeviceOwnerProvisioningActivity (has extras)} from uid 1027 on display 0
10-22 10:31:31.886 7237-7237/? D/ManagedProvisioning﹕ Device owner provisioning activity ONCREATE
10-22 10:31:31.887 7237-7237/? E/ManagedProvisioning﹕ Device already provisioned.
10-22 10:31:31.903 7237-7237/? D/ManagedProvisioning﹕ Device owner provisioning activity ONRESUME
10-22 10:31:32.011 549-621/? I/ActivityManager﹕ Displayed com.android.managedprovisioning/.DeviceOwnerProvisioningActivity: +149ms (total +200ms)
10-22 10:31:32.955 2610-2610/? D/NfcService﹕ LLCP Link Deactivated message. Restart polling loop.
10-22 10:31:32.955 2610-2610/? I/NfcP2pLinkManager﹕ LLCP deactivated.
10-22 10:31:32.955 2610-2610/? D/NfcP2pLinkManager﹕ Debounce timeout
10-22 10:31:32.955 2610-2610/? D/NfcP2pLinkManager﹕ onP2pOutOfRange()
So it does seem that the Device Owner NFC bump can only happen on an unprovisioned device. I appreciate this doesn't answer your question, but the log output might help. Getting hold of the source code for DeviceOwnerProvisioningActivity would certainly help.
You should enter the WiFi parameters manually. There is a bug that has been corrected in Android 5.1.