Search code examples
javaandroidprovisioningnfs

Android NFC device owner provisioning: send custom properties. Is it possible?


I'm currently developing an app and have the following issue.

While using NFC for device owner provisioning, I would like to send a string, which would be used by the new device owner app.

I'm aware of the standard MIME properties for device owner provisioning, found here

Here's a snippet that can give you a better visual of my issue. Notice the "myCustomValue" property.

Properties properties = new Properties();
properties.put("myCustomValue", value);
properties.put(DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME, "com.example.some.app");
try {                    
    properties.store(stream, "NFC Provisioning");            
    ndefMessage = new NdefMessage(new NdefRecord[{NdefRecord.createMime(DevicePolicyManager.MIME_TYPE_PROVISIONING_NFC, stream.toByteArray())});
} catch (IOException e) {                         

}

This snippet lies inside

public NdefMessage createNdefMessage(NfcEvent event)

and you can find a template here

In case this is possible, I also would like to know how to retrieve that string value as soon as the provisioned app has started.


Solution

  • The code below should be what you're looking for. For brevity, I only set the package name plus two strings that will be sent to your DeviceAdminReceiver.

    @Override
    public NdefMessage createNdefMessage(NfcEvent event) {
        try {
            Properties p = new Properties();
    
            p.setProperty(
                    DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME,
                    "com.example.some.app");
    
            Properties extras = new Properties();
            extras.setProperty("Key1", "TestString1");
            extras.setProperty("Key2", "TestString2");
            StringWriter sw = new StringWriter();
            try{
                extras.store(sw, "admin extras bundle");
                p.put(DevicePolicyManager.EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE,
                        sw.toString());
                Log.d(TAG, "Admin extras bundle=" + p.get(
                        DevicePolicyManager.EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE));
            } catch (IOException e) {
                Log.e(TAG, "Unable to build admin extras bundle");
            }
    
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            OutputStream out = new ObjectOutputStream(bos);
            p.store(out, "");
            final byte[] bytes = bos.toByteArray();
    
            NdefMessage msg = new NdefMessage(NdefRecord.createMime(
                    DevicePolicyManager.MIME_TYPE_PROVISIONING_NFC, bytes));
            return msg;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    

    This next snippet will go in your DeviceAdminReceiver in order to receive the "Admin Extras"... If you don't override onReceive, onProfileProvisioningComplete will need to be overridden with EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE handled in there instead.

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d(TAG, "onReceive " + intent.getAction());
        if (ACTION_PROFILE_PROVISIONING_COMPLETE.equals(intent.getAction())) {
            PersistableBundle extras = intent.getParcelableExtra(
                    EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE);
            Log.d(TAG, "onReceive Extras:" + extras.getString("Key1") + " / "  + extras.getString("Key2"));
        }
    }