I am attempting to create a COSU device. It will be hardware sold by my company that runs a single application developed by us. I have looked through many tutorials in an attempt to set up a proof of concept for this.
I currently have the following.
In my AndroidManaifest.xml
Then later...
<application android:allowBackup="true" android:label="#string/app_name" android:keepScreenOn="true" >
<receiver android:name="DeviceAdmin"
android:label="#string/sample_device_admin"
android:description="#string/sample_device_admin_description"
android:permission="android.permission.BIND_DEVICE_ADMIN">
<intent-filter>
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
</intent-filter>
<device-admin>
<uses-policies>
<limit-password />
<watch-login />
<reset-password />
<force-lock />
<wipe-data />
</uses-policies>
</device-admin>
</receiver>
<uses-permission android:name="android.permission.MANAGE_DEVICE_ADMINS" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</application>
In device_admin_receiver.xml
<?xml version="1.0" encoding="utf-8"?>
<device-admin xmlns:android="http://schemas.android.com/apk/res/android">
<uses-policies>
<limit-password />
<watch-login />
<reset-password />
<force-lock />
<wipe-data />
</uses-policies>
</device-admin>
DeviceAdmin.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.App.Admin;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
namespace CB.App
{
public class DeviceAdmin : DeviceAdminReceiver
{
}
}
And finally the OnCreate of MainActivity.cs
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Window.DecorView.SystemUiVisibility = (StatusBarVisibility)flags;
// Setup the collection and register implementations
IServiceCollection coll = new ServiceCollection();
RegisterDependencies(coll);
// Build the global services
ServiceRegistrationHelper.RegisterCoreServices(coll);
// Register the provide with the GlobalServices
GlobalServices.RegisterServiceProvider(coll.BuildServiceProvider(new ServiceProviderOptions()));
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
DevicePolicyManager myDevicePolicyManager = (DevicePolicyManager)this.GetSystemService(Activity.DevicePolicyService);
// get this app package name
ComponentName mDPM = new ComponentName(this, typeof(DeviceAdmin).Name);
if( myDevicePolicyManager.IsDeviceOwnerApp(this.PackageName))
{
//myDevicePolicyManager.ClearDeviceOwnerApp(this.PackageName);
String[] packages = { this.PackageName };
myDevicePolicyManager.SetLockTaskPackages(mDPM, packages);
StartLockTask();
SetUpClock();
DisplayHome();
}
else
{
Toast.MakeText(this.ApplicationContext, "Not Owner", ToastLength.Long).Show();
}
}
In the ADB Shell I ran the command dpm set-device-owner com.companyname.productname/.DeviceAdmin and received Success: Device owner set to package componentinfo{com.companyname.productname/com.companyname.productname.DeviceAdmin} Active admin set to component {com.companyname.productname/com.companyname.productename.DeviceAdmin}
It builds and deploys but when it gets to the line
myDevicePolicyManager.SetLockTaskPackages(mDPM, packages);
It throws the error Java.Lang.SecurityException: No active admin ComponentInfo(com.lathem.cumberland/DeviceAdmin
What am I missing?
Remove the <device-admin> section from your receiver, this should be referenced via a separate xml resource, either via hard-coding the meta-data section in the receiver's manifest section or via class attributes:
[BroadcastReceiver(
Name = "com.sushihangover.cosu.DeviceAdminReceiver",
Label = "StackOverflow",
Permission = "android.permission.BIND_DEVICE_ADMIN",
Exported = true
)]
[MetaData("android.app.device_admin", Resource = "#xml/device_admin_receiver")]
[IntentFilter(new[] {
"android.intent.action.DEVICE_ADMIN_ENABLE",
"android.intent.action.PROFILE_PROVISIONING_COMPLETE",
"android.intent.action.BOOT_COMPLETED"
})]
public class MyDeviceAdminReceiver : DeviceAdminReceiver {}
Use the Java class name, not the C# name:
ComponentName mDPM = new ComponentName(this, Java.Lang.Class.FromType(typeof(DeviceAdminReceiver)));
Note: Based upon my use of the Java name for my DeviceAdminReceiver subclass, the dpm set-device-owner would be:
adb shell dpm set-device-owner com.sushihangover.cosu/com.sushihangover.cosu.DeviceAdminReceiver
Related
I am currently trying to add deep linking support (via Intents) to an Android application written using .NET MAUI.
I have added an activity XML element under the application element in my AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application android:allowBackup="true" android:icon="#mipmap/appicon" android:roundIcon="#mipmap/appicon_round" android:supportsRtl="true">
<activity android:name="TestApp.MainActivity" android:exported="true">
<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="https"
android:host="test"
android:pathPrefix="/group" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
</manifest>
I have also added an IntentFilter to the MainActivity.cs under Platforms\Android (see below):
[IntentFilter(new[] { Intent.ActionView },
Categories = new[]
{
Intent.ActionView,
Intent.CategoryDefault,
Intent.CategoryBrowsable
},
DataScheme = "https", DataHost = "test", DataPathPrefix = "/group"
)
]
public class MainActivity : MauiAppCompatActivity
Just not sure what to do at this point to react (where to put event handler, etc.) to the intent.
If anyone has any suggestions, it would be greatly appreciated.
You can handle the intent by overriding OnNewIntent method .
Fetch the information from intent.DataString and do what you want.
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
//test
OnNewIntent(Intent);
}
protected override void OnNewIntent(Intent intent)
{
base.OnNewIntent(intent);
var data = intent.DataString;
if (intent.Action != Intent.ActionView) return;
if (string.IsNullOrWhiteSpace(data)) return;
if (data.Contains("/group"))
{
//do what you want
}
}
I am trying to set the lock task packages but IsAdminActive is returning false.
To set the device owner and active admin I used the command dpm set-device-owner PinningTest.PinningTest/.AdminReceiverTest from the adb shell. This completed successfully.
My MainActivity:
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
DevicePolicyManager devicePolicyManager = (DevicePolicyManager)GetSystemService(Context.DevicePolicyService);
ComponentName testDeviceAdmin = new ComponentName(this, Java.Lang.Class.FromType(typeof(AdminReceiverTest)).Name);
if (devicePolicyManager.IsAdminActive(testDeviceAdmin))
{
devicePolicyManager.SetLockTaskPackages(testDeviceAdmin, new string[] { PackageName });
}
}
My AndroidManifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="PinningTest.PinningTest"
android:versionCode="1" android:versionName="1.0"
android:installLocation="auto">
<uses-sdk android:minSdkVersion="21" />
<uses-permission android:name="android.permission.BIND_DEVICE_ADMIN" />
<application android:label="PinningTest">
<receiver android:name=".AdminReceiverTest"
android:label="#string/ApplicationName"
android:description="#string/ApplicationName"
android:permission="android.permission.BIND_DEVICE_ADMIN">
<meta-data android:name="android.app.device_admin" android:resource="#xml/device_admin" />
<intent-filter>
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
</intent-filter>
</receiver>
</application>
</manifest>
AdminReceiverTest.cs:
namespace PinningTest
{
class AdminReceiverTest : DeviceAdminReceiver
{
}
}
I was following the tutorial here and have also looked at various others but I haven't been able to find a complete Xamarin example.
Any help is appreciated.
Many thanks.
I originally had the same issue, but I've just got this working by using the following
[BroadcastReceiver(Name = "com.sceneskope.survey.DeviceAdminReceiver", Enabled = true, Exported = true, Permission = "android.permission.BIND_DEVICE_ADMIN")]
[MetaData("android.app.device_admin", Resource = "#xml/device_admin_receiver")]
[IntentFilter(new[] { "android.app.action.DEVICE_ADMIN_ENABLED" })]
public class DeviceAdminReceiver : Android.App.Admin.DeviceAdminReceiver
{
}
And setting the device owner using
.\adb.exe shell dpm set-device-owner com.afwsamples.testdpc/.DeviceAdminReceiver
That appears to solve my problems, so I guess this was down to issues with the names when putting in the manifest manually.
It looks like your manual manifest entries are not taking into account the auto-generated class names (Md5-based) that Xamarin.Android generates to avoid namespace collisions.
Since DeviceAdminReceiver is a subclass of BroadcastReceiver, use the [BroadcastReceiver] class attribute to override the auto-generated class names in your manifest:
[BroadcastReceiver(Name = "com.sushihangover.deviceownerapp.adminreceiver", Enabled = true, Exported = true)]
[IntentFilter(new[] { "android.app.action.DEVICE_ADMIN_ENABLED" })]
public class AdminReceiverTest : DeviceAdminReceiver
{
public override void OnReceive(Context context, Intent intent)
{
base.OnReceive(context, intent);
}
}
Thus in your manifest, the following is auto-generated:
<receiver android:enabled="true" android:exported="true" android:name="com.sushihangover.deviceownerapp.adminreceiver">
<intent-filter>
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
</intent-filter>
</receiver>
please help . . I build app, but i want to when user try to uninstall mp app, it's require password. I try this but it doesn't work:
In myActivity:
AdminReceiver a = new AdminReceiver();
a.onDisableRequested(getApplicationContext(), getIntent());
AdminReceiver :
public class AdminReceiver extends DeviceAdminReceiver{
static DevicePolicyManager dpm;
static ComponentName devAdminReceiver;
public CharSequence onDisableRequested(final Context context, Intent intent) {
Intent startMain = new Intent(Intent.ACTION_MAIN);
startMain.addCategory(Intent.CATEGORY_HOME);
startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(startMain); //switch to the home screen, not totally necessary
lockPhone(context, "pass");
//Log.i(TAG, "DEVICE ADMINISTRATION DISABLE REQUESTED & LOCKED PHONE");
return "haha. i locked your phone.";
}
public static boolean lockPhone(Context context, String password){
devAdminReceiver = new ComponentName(context, AdminReceiver.class);
dpm = (DevicePolicyManager)context.getSystemService(Context.DEVICE_POLICY_SERVICE);
boolean pwChange = dpm.resetPassword(password, 0);
dpm.lockNow();
return pwChange;
}
And in AndroidManifest:
<receiver android:name=".app.AdminReceiver"
android:label="#string/app_name"
android:description="#string/hello_world"
android:permission="android.permission.BIND_DEVICE_ADMIN">
<meta-data android:name="android.app.device_admin"
android:resource="#xml/deviceadmin" />
<intent-filter>
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
</intent-filter>
</receiver>
and last in xml/deviceadmin:
<device-admin xmlns:android="http://schemas.android.com/apk/res/android">
<uses-policies>
<limit-password />
<watch-login />
<reset-password />
<force-lock />
<wipe-data />
</uses-policies>
</device-admin>
actually i really confused, how it works. Please help me i really need it for my final project
That is not possible in Android without firmware modifications.
Refer AOSP code for further managing policy
OR
IN AndroidL push deviceower.xml which will make ur app device owner hence u can apply the policy but prerequisites is device should be rroted
I am trying to develop the push notification with Urban Airship. I am successfully running the app, but my device is not registering in my Account. ANd I am getting these errors also in logcate.
01-24 19:20:47.480: W/GCMNotification - UALib(30560): Activity com.example.gcmnotification.MainActivity#416c6fb8 was not manually added during onStart(). Call UAirship.shared().getAnalytics().activityStarted in every activity's onStart() method.
01-24 19:21:14.400: E/GCMNotification - UALib(31088): AndroidManifest.xml missing required service: com.urbanairship.analytics.EventService
01-24 19:21:14.410: E/GCMNotification - UALib(31088): AndroidManifest.xml's com.urbanairship.push.GCMPushReceiver declaration missing required com.google.android.c2dm.intent.RECEIVE filter with category=com.example.gcmnotification
01-24 19:21:14.410: E/GCMNotification - UALib(31088): AndroidManifest.xml's com.urbanairship.push.GCMPushReceiver declaration missing required com.google.android.c2dm.intent.REGISTRATION filter with category=com.example.gcmnotification
code is here.
public class MyApplication extends Application{
#Override
public void onCreate() {
AirshipConfigOptions options = AirshipConfigOptions.loadDefaultOptions(this);
options.developmentAppKey = "pahvQlDxxx";
options.developmentAppSecret = "bOltfxxx";
options.productionAppKey = "AIzaSyCS_QxF-AtTglLf5BWxxx";
options.inProduction = false;
//options.iapEnabled = false;
UAirship.takeOff(this, options);
PushManager.enablePush();
}
}
The LogCat tells you exactly what is missing in your AndroidManifest.xml.
Your broadcast receiver should be declared as follows :
<receiver android:name="com.urbanairship.push.GCMPushReceiver"
android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.example.gcmnotification" />
</intent-filter>
</receiver>
And you should declare com.urbanairship.analytics.EventService :
<service android:name="com.urbanairship.analytics.EventService" />
When user want to uninstall app from android device, I want user uninstall button click event for that application.
I am getting event of application is removed from device, but I want to show pop-up before application is removed. I am trying to achieve same like doing in 'App Lock' application.
Here is my code to get application removed event through broadcast receiver. But I am totally blank about uninstall button click or before pop-up click. Please guide me in right direction.
Thanks in advance.
public class MainActivity extends Activity {
CustomBroadcastReceiver mApplicationsReceiver;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mApplicationsReceiver=new CustomBroadcastReceiver();
IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
filter.addAction(Intent.ACTION_PACKAGE_ADDED);
filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
filter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
filter.addAction(Intent.ACTION_PACKAGE_VERIFIED);
filter.addAction(Intent.ACTION_PACKAGE_INSTALL);
filter.addAction(Intent.ACTION_PACKAGE_FIRST_LAUNCH);
filter.addAction(Intent.ACTION_DELETE);
filter.addAction(Intent.ACTION_DEFAULT);
filter.addDataScheme("package");
registerReceiver(mApplicationsReceiver, filter);
}
}
public class CustomBroadcastReceiver extends BroadcastReceiver {
/**
* This method captures the event when a package has been removed
*/
#Override
public void onReceive(Context context, Intent intent)
{
System.out.println("Hello from CustomBroadcastReceiver");
if (intent != null) {
String action = intent.getAction();
System.out.println("L1123 : "+action);
if (action.equals(intent.ACTION_PACKAGE_REMOVED)) {
//Log the event capture in the log file ...
System.out.println("The package has been removed");
}
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.bits.uninstallappdemo"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.BROADCAST_PACKAGE_REMOVED" />
<uses-permission android:name="android.permission.INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.DELETE_PACKAGES" />
<uses-permission android:name="android.permission.BROADCAST_PACKAGE_ADDED" />
<uses-permission android:name="android.permission.BROADCAST_PACKAGE_CHANGED" />
<uses-permission android:name="android.permission.BROADCAST_PACKAGE_INSTALL" />
<uses-permission android:name="android.permission.BROADCAST_PACKAGE_REPLACED" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- <receiver android:name=".CustomBroadcastReceiver" >
<intent-filter>
<action android:name="android.intent.action.PACKAGE_REMOVED" />
<action android:name="android.intent.action.PACKAGE_ADDED" />
<category android:name="android.intent.category.DEFAULT" />
<action android:name="android.intent.action.PACKAGE_ADDED" />
<action android:name="android.intent.action.PACKAGE_CHANGED" />
<action android:name="android.intent.action.PACKAGE_INSTALL" />
<action android:name="android.intent.action.PACKAGE_REMOVED" />
<action android:name="android.intent.action.PACKAGE_REPLACED" />
</intent-filter>
</receiver> -->
</application>
</manifest>
Please try to get the top activity in the task via ActivityManager, and check if it is the uninstall activity.
Core code:
ComponentName topActivity = mActivityManager.getRunningTasks(1).get(0).topActivity;
String packageName = topActivity.getPackageName();
String className = topActivity.getClassName();
Log.v(TAG, "packageName" + packageName);
Log.v(TAG, "className" + className);
if ("com.android.packageinstaller".equals(packageName)
&& "com.android.packageinstaller.UninstallerActivity".equals(className)) {
//Do anything you want here
}
The following permissions which you are using are granted to system apps only. Make sure you have rooted device to allow such permissions.
<uses-permission android:name="android.permission.BROADCAST_PACKAGE_REMOVED" />
<uses-permission android:name="android.permission.INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.DELETE_PACKAGES" />