Android 12 Device Owner Provisioning - android

I have an application, that can be successfully setup as Device Owner on devices up to Android 12 via QR code from JSON below:
{
"android.app.extra.PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME":
"package.CustomDeviceAdminReceiver",
"android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM":
"actual_checksum",
"android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION":
"https://Site/APK_Link",
"android.app.extra.PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED": true
}
App contains declared receiver:
<receiver
android:name=".deviceadmin.CustomDeviceAdminReceiver"
android:description="#string/app_name"
android:label="#string/app_name"
android:permission="android.permission.BIND_DEVICE_ADMIN">
<meta-data
android:name="android.app.device_admin"
android:resource="#xml/enterprise_device_admin" />
<intent-filter>
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
<action android:name="android.app.action.PROFILE_PROVISIONING_COMPLETE" />
</intent-filter>
</receiver>
For Android 12 (as described here https://source.android.com/devices/tech/admin/provision) I added 2 activities:
<activity
android:name=".deviceadmin.AdminPolicyComplianceActivity"
android:screenOrientation="portrait"
android:permission="android.permission.BIND_DEVICE_ADMIN">
<intent-filter>
<action android:name="android.app.action.ADMIN_POLICY_COMPLIANCE"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".deviceadmin.ProvisioningModeActivity"
android:screenOrientation="portrait"
android:permission="android.permission.BIND_DEVICE_ADMIN">
<intent-filter>
<action android:name="android.app.action.GET_PROVISIONING_MODE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
1st one:
public class ProvisioningModeActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_provisioning_mode);
Intent intent = getIntent();
int provisioningMode = 1;
List<Integer> allowedProvisioningModes = intent.getIntegerArrayListExtra(DevicePolicyManager.EXTRA_PROVISIONING_ALLOWED_PROVISIONING_MODES);
if (allowedProvisioningModes.contains(DevicePolicyManager.PROVISIONING_MODE_FULLY_MANAGED_DEVICE))
provisioningMode = DevicePolicyManager.PROVISIONING_MODE_FULLY_MANAGED_DEVICE;
else if (allowedProvisioningModes.contains(DevicePolicyManager.PROVISIONING_MODE_MANAGED_PROFILE))
provisioningMode = DevicePolicyManager.PROVISIONING_MODE_MANAGED_PROFILE;
Intent resultIntent = new Intent();
resultIntent.putExtra(DevicePolicyManager.EXTRA_PROVISIONING_MODE, provisioningMode);
setResult(RESULT_OK, resultIntent);
finish();
}
}
and 2nd one (almost empty):
public class AdminPolicyComplianceActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_admin_policy_compliance);
setResult(RESULT_OK);
finish();
}
}
but I got error while enrollment: "Can't setup device. Can't use the admin app. It's missing components or corrupted".
Can somebody find that I missed please?

From Android 12 we are supposed to have components exported safely. Since your activities ProvisioningModeActivity and AdminPolicyComplianceActivity uses intent filter, we have to set the exported flag.
<activity
android:name=".deviceadmin.AdminPolicyComplianceActivity"
android:screenOrientation="portrait"
android:permission="android.permission.BIND_DEVICE_ADMIN"
android:exported="true">
<intent-filter>
<action
android:name="android.app.action.ADMIN_POLICY_COMPLIANCE"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".deviceadmin.ProvisioningModeActivity"
android:screenOrientation="portrait"
android:permission="android.permission.BIND_DEVICE_ADMIN"
android:exported="true">
<intent-filter>
<action android:name="android.app.action.GET_PROVISIONING_MODE"
/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
This way firmware will be able to recognize the activity and launch it.
Also, regarding android:testOnly="false", this flag must be false if you are going to do QR code provisioning. If its true then, you will be able to remove admin via android settings.

#faz the reason this code doesn't work on Android 11 and below is because the ProvisioningModeActivity intent is not fired with an extra integer array of DevicePolicyManager.EXTRA_PROVISIONING_ALLOWED_PROVISIONING_MODES. To overcome this add a null check to the allowedProvisioningModes

Related

Android Chrome Custom Tab Intent Filter Restricted to Only My App?

I'm trying to achieve https://mobikul.com/use-safariviewcontroller-callback-url-objective-c/ on Android, where "sourceApplication" is checked in the iOS example and only allows an SFSafariViewController to redirect back to the application (presumably it's a SFSafariViewController instantiated by the app...but that's another question!).
I am having trouble achieving parity in Android. In my app, BrowserActivity opens up a Chrome Custom Tab, which redirects back to the CallbackActivity from the HTML. Chrome / any browser on phone, I find, is also allowed to redirect back to CallbackActivity if I just enter the correct URL schema, and that's bad news! It seems like there should be a whitelist mechanism in the manifest to only allow a Chrome Custom Tab opened from my application to redirect back to my activity, while disallowing anybody else. I can not set android:exported="false" on CallbackActivity in the manifest because that breaks the redirect capability from my application. How does one achieve this?
Here's what I've got for the Android manifest:
<activity android:name="com.epicgames.ue4.SplashActivity" android:launchMode="singleTask" android:debuggable="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.epicgames.ue4.GameActivity" android:exported="false">
<meta-data android:name="android.app.lib_name" android:value="UE4" />
</activity>
<activity android:name=".BrowserActivity" android:launchMode="singleTask" android:exported="false">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
</activity>
<activity android:name=".CallbackActivity" android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="customscheme" android:host="callback" />
</intent-filter>
And here's what I've got for the relevant activities:
public class BrowserActivity extends Activity {
#Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
final Uri uri = Uri.parse(getIntent().getStringExtra("url"));
final CustomTabsIntent intent = new CustomTabsIntent.Builder().build();
intent.intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
intent.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.intent.setData(uri);
startActivity(intent.intent);
}
}
public class CallbackActivity extends Activity {
#Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
//TODO validate only chrome custom tab HTML, started from my app, redirected here
//getCallingPackage() is always null and referrer host can be spoofed...how to?
final Intent intent = new Intent(this, com.epicgames.ue4.GameActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);
}
}

Two launcher activities creating two APKs

I recently added a splash-screen to my app and made it as launcher activity to display it when the app started, the manifest looks like,
<activity android:name=".LaucherActivity" android:theme="#style/SplashTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
And I have the MainActivity which is already a launcher activity in the manifest shown below,
<activity
android:name=".MainActivity"
android:screenOrientation="portrait"
android:theme="#style/AppTheme.TransparentTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> s
</intent-filter>
</activity>
So, this is actually creating two APKs, one for the splash and the other main activity. But I wanted the SplashActivity and MainActivity in the same APK running one after the other. How can I achieve that? I found many related questions but none of them are working for me.
Use <intent-filter> only once in manifest. like this
<activity android:name=".LaucherActivity" android:theme="#style/SplashTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".MainActivity"
android:screenOrientation="portrait"
android:theme="#style/AppTheme.TransparentTheme">
</activity>
public class LaucherActivity extends Activity {
private static int SPLASH_TIME_OUT = 3000;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
Intent i = new Intent(LaucherActivity.this, MainActivity.class);
startActivity(i);
finish();
}
}, SPLASH_TIME_OUT);
}
}
Remove this from you MainActivity.
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
Now call your MainActivity from your Splash Activity

How to make activity launcher for different api version?

I'm building an kiosk App for two different versions: Android 6 and before.
When app started I have StartActivity and 2 Activities for different APK lvl, start this:
public class StartActivity extends AppCompatActivity {
#Override
protected void onCreate(#Nullable final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
startActivity(new Intent(this, MainActivityNew.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
} else {
startActivity(new Intent(this, MainActivityOld.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}
finish();
}
}
MainActivityNew and MainActivityOld must be launchers (when button home is pressed he must call)
In Manifest file i write:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ng.lockergks">
<application
android:name="com.gks.locker.App"
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/Theme.AppCompat.Light.NoActionBar.FullScreen">
<activity android:name="ru.gks.locker.ui.activity.StartActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name=".MainActivityOld"
android:launchMode="singleInstance"
android:screenOrientation="portrait"
android:stateNotNeeded="true">
<intent-filter>
<category android:name="android.intent.category.HOME"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name=".MainActivityNew"
android:launchMode="singleInstance"
android:screenOrientation="portrait"
android:stateNotNeeded="true">
<intent-filter>
<category android:name="android.intent.category.HOME"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".AppListActivity"/>
</application>
</manifest>
That is, when the application starts, check the version of the API, and depending on it, runs one way or the other activity which should be a launcher. On both versions it does not work. How to define such behavior?

My application not get started when device started?

I've written following class to start my application activity Home.class but on device start up it shows error forced close.
public class MyBootRecvr extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, Home.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.addFlags(Intent.FLAG_FROM_BACKGROUND);
context.startActivity(i);
Toast.makeText(context, "Where is my KeyBoard", Toast.LENGTH_LONG)
.show();
}
}
Permissions and receiver tags in application.
<receiver
android:name=".Home"
android:enabled="true"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
If this is the only code in your application, it will never run. Android applications must have at least one subclass of Activity as a starting point for when you run the app. The Activity could should at a minimum look something like this:
class MyActivity extends Activity {
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
this.setContentView(R.layout.my_layout); /* my_layout should be an XML layout in res/layout */
}
}
Make sure the following code in is your AndroidManifest.xml file
<activity android:name="MyActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
If you create a new Android project in Eclipse, it will do this setting up for you. There are a lot of tutorials on both setting up a basic application in Android, and using Eclipse to do it for you.
doing this solve the problem
thanks to xono
<receiver
android:name=".MyBootRecvr"
android:enabled="true"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>

How to start a new application on Android

How can I start a new application on Android? I have done a new applications NewHomeScreen and Hello and on NewHomeScreen I wrote this code.
#Override public void onCreate(Bundle state) {
super.onCreate(state);
setContentView(R.layout.main);
Intent mainIntent = new Intent(this,Hello.class);
startActivity(mainIntent);
}
However, it does not start Hello application. Debugger says that state has value null but what should it be? I also wrote this to Manifest:
<activity android:name="Hello">
<intent-filter>
<action android:name="android.intent.action.HELLO" />
<category android:name="android.intent.category.HELLO"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Try getting rid of the intent-filter in your Home activity. You don't need it anyway, if it's not your main screen.
I think you forgot to specify the main Activity in your AndroidManifest.xml file:
<application android:icon="#drawable/icon">
<activity android:name="NewHomeScreen" android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.HELLO" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

Categories

Resources