初次涉猎Android程序,使用 Xamarin 编写,这里不讨论 Xamarin 的好坏,重点是解决我们的问题。调用系统功能必不可少的便是 adb 命令 和 Android 共享库,来浅试下。
pm工具为包管理(package manager)的简称。
可以使用 pm 工具来执行应用的安装和查询应用包的信息、系统权限、控制应用。
pm 工具是 Android 开发与测试过程中必不可少的工具。
命令格式:pm
adb shell pm
即可获得关于 pm 的用法帮助usage: pm list packages [-f] [-d] [-e] [-s] [-3] [-i] [-u] [--user USER_ID] [FILTER]
pm list permission-groups
pm list permissions [-g] [-f] [-d] [-u] [GROUP]
pm list instrumentation [-f] [TARGET-PACKAGE]
pm list features
pm list libraries
pm list users
pm path PACKAGE
pm dump PACKAGE
pm install [-lrtsfd] [-i PACKAGE] [PATH]
pm install-create [-lrtsfdp] [-i PACKAGE] [-S BYTES]
pm install-write [-S BYTES] SESSION_ID SPLIT_NAME [PATH]
pm install-commit SESSION_ID
pm install-abandon SESSION_ID
pm uninstall [-k] [--user USER_ID] PACKAGE
pm set-installer PACKAGE INSTALLER
pm clear [--user USER_ID] PACKAGE
pm enable [--user USER_ID] PACKAGE_OR_COMPONENT
pm disable [--user USER_ID] PACKAGE_OR_COMPONENT
pm disable-user [--user USER_ID] PACKAGE_OR_COMPONENT
pm disable-until-used [--user USER_ID] PACKAGE_OR_COMPONENT
pm hide [--user USER_ID] PACKAGE_OR_COMPONENT
pm unhide [--user USER_ID] PACKAGE_OR_COMPONENT
pm grant PACKAGE PERMISSION
pm revoke PACKAGE PERMISSION
pm set-install-location [0/auto] [1/internal] [2/external]
pm get-install-location
pm set-permission-enforced PERMISSION [true|false]
pm trim-caches DESIRED_FREE_SPACE
pm create-user [--profileOf USER_ID] [--managed] USER_NAME
pm remove-user USER_ID
pm get-max-users
pm list packages: prints all packages, optionally only
those whose package name contains the text in FILTER. Options:
-f: see their associated file.
-d: filter to only show disbled packages.
-e: filter to only show enabled packages.
-s: filter to only show system packages.
-3: filter to only show third party packages.
-i: see the installer for the packages.
-u: also include uninstalled packages.
pm list permission-groups: prints all known permission groups.
pm list permissions: prints all known permissions, optionally only
those in GROUP. Options:
-g: organize by group.
-f: print all information.
-s: short summary.
-d: only list dangerous permissions.
-u: list only the permissions users will see.
pm list instrumentation: use to list all test packages; optionally
supply to list the test packages for a particular
application. Options:
-f: list the .apk file for the test package.
pm list features: prints all features of the system.
pm list users: prints all users on the system.
pm path: print the path to the .apk of the given PACKAGE.
pm dump: print system state associated with the given PACKAGE.
pm install: install a single legacy package
pm install-create: create an install session
-l: forward lock application
-r: replace existing application
-t: allow test packages
-i: specify the installer package name
-s: install application on sdcard
-f: install application on internal flash
-d: allow version code downgrade
-p: partial application install
-S: size in bytes of entire session
pm install-write: write a package into existing session; path may
be '-' to read from stdin
-S: size in bytes of package, required for stdin
pm install-commit: perform install of fully staged session
pm install-abandon: abandon session
pm set-installer: set installer package name
pm uninstall: removes a package from the system. Options:
-k: keep the data and cache directories around after package removal.
pm clear: deletes all data associated with a package.
pm enable, disable, disable-user, disable-until-used: these commands
change the enabled state of a given package or component (written
as "package/class").
pm grant, revoke: these commands either grant or revoke permissions
to applications. Only optional permissions the application has
declared can be granted or revoked.
pm get-install-location: returns the current install location.
0 [auto]: Let system decide the best location
1 [internal]: Install on internal device storage
2 [external]: Install on external media
pm set-install-location: changes the default install location.
NOTE: this is only intended for debugging; using this can cause
applications to break and other undersireable behavior.
0 [auto]: Let system decide the best location
1 [internal]: Install on internal device storage
2 [external]: Install on external media
pm trim-caches: trim cache files to reach the given free space.
pm create-user: create a new user with the given USER_NAME,
printing the new user identifier of the user.
pm remove-user: remove the user with the given USER_IDENTIFIER,
deleting all data associated with that user
Context 提供了关于应用环境全局信息的接口。它是一个抽象类,它的执行被Android系统所提供。它允许获取以应用为特征的资源和类型,是一个统领一些资源(应用程序环境变量等)的上下文。
也就是说Context描述一个应用程序环境的信息(即上下文);是一个抽象类,Android提供了该抽象类的具体实现类;通过它我们可以获取应用程序的资源和类。
下面的代码中使用到了 _context 对象这里交代下
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
internal static MainActivity Instance { get; private set; }
}
// 在各自的实现类中定义然后使用
private readonly Context _context = MainActivity.Instance;
su
权限using Java.IO;
private bool ExecuteCommand(string commandStr)
{
try
{
using Process p = Runtime.GetRuntime().Exec("su");
BufferedReader ins = new BufferedReader(new InputStreamReader(p.InputStream));
BufferedReader ie = new BufferedReader(new InputStreamReader(p.ErrorStream));
BufferedWriter w = new BufferedWriter(new OutputStreamWriter(p.OutputStream));
w.Write(commandStr);
w.Flush();
w.Close();
ins.Close();
ie.Close();
int res = p.WaitFor();
if (res is 0)
return true;
}
catch (Throwable ex)
{
return false;
}
return false;
}
检查 APP 是否安装,PackageManager 实例来获取当前系统安装的所有 APP 通过packageName 进行判断。
public bool CheckAppInstalled(string packageName)
{
var packageInfo = _context.PackageManager.GetInstalledPackages(PackageInfoFlags.Activities).Where(pm => pm.PackageName == packageName).FirstOrDefault();
if (packageInfo != null)
return true;
return false;
}
自动开关机,就属于 Android 共享库实现了
Android Intent
,具体怎么用自己搜很多,这里把开关机时间的设定作为例子。
///
/// 开机 Intent
///
private static readonly string SETPOWERON = "android.intent.action.setpoweron";
///
/// 关机 Intent
///
private static readonly string SETPOWEROFF = "android.intent.action.setpoweroff";
long
类型需要进行转换private static readonly string SETPOWERON = "android.intent.action.setpoweron";
private static readonly string SETPOWEROFF = "android.intent.action.setpoweroff";
private static readonly string POWERON = "poweron";
private static readonly string POWEROFF = "poweroff";
private static readonly string ENABLE = "enable";
public bool PowerOffPlan(bool enable, long planTime)
{
try
{
Intent intent = new Intent(SETPOWEROFF);
intent.PutExtra(ENABLE, enable);
if (enable && planTime > 0)
{
Date dateTime = new Date(planTime);
Calendar calendar = Calendar.GetInstance(Locale.SimplifiedChinese);
calendar.Time = dateTime;
calendar.Set(CalendarField.Second, 0);
int[] time = new int[]
{
calendar.Get(CalendarField.Year),
calendar.Get(CalendarField.Month),
calendar.Get(CalendarField.DayOfMonth),
calendar.Get(CalendarField.HourOfDay),
calendar.Get(CalendarField.Minute),
calendar.Get(CalendarField.Second),
};
intent.PutExtra(POWEROFF, time);
}
_context.SendBroadcast(intent);
return true;
}
catch (Throwable ex)
{
Toast.MakeText(_context, $"Exception:{ex.Message}", ToastLength.Short).Show();
}
return false;
}
public bool PowerOnPlan(bool enable, long planTime)
{
try
{
Intent intent = new Intent(SETPOWERON);
intent.PutExtra(ENABLE, enable);
if (enable && planTime > 0)
{
Date dateTime = new Date(planTime);
Calendar calendar = Calendar.GetInstance(Locale.SimplifiedChinese);
calendar.Time = dateTime;
calendar.Set(CalendarField.Second, 0);
int[] time = new int[]
{
calendar.Get(CalendarField.Year),
calendar.Get(CalendarField.Month),
calendar.Get(CalendarField.DayOfMonth),
calendar.Get(CalendarField.HourOfDay),
calendar.Get(CalendarField.Minute),
calendar.Get(CalendarField.Second),
};
intent.PutExtra(POWERON, time);
}
_context.SendBroadcast(intent);
return true;
}
catch (Throwable ex)
{
Toast.MakeText(_context, $"Exception:{ex.Message}", ToastLength.Short).Show();
}
return false;
}
通过监听系统的开机广播来实现,拉起app。
首先,需要在清单文件AndroidManifest.xml申请监听开机广播权限
android.intent.action.BOOT_COMPLETED
然后在清单文件 AndroidManifest.xml 声明该广播接收者,也就是下面实现监听广播处理自己的业务逻辑(拉起自己app)的类
BootReceiver
<receiver android:name=".base.BootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.LAUNCHER" />
intent-filter>
receiver>
最后实现一个BroadcastReceiver,该广播接收者监听
"android.intent.action.BOOT_COMPLETED"
广播,当接收到该广播时,打开该应用的启动页面。
[BroadcastReceiver(Enabled = true)]
[IntentFilter(new[] { Intent.ActionBootCompleted, Intent.ActionReboot })]
public class BootReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
try
{
if (intent.Action != null && intent.Action is Intent.ActionBootCompleted)
{
Intent _intent = new Intent();
_intent.SetClass(context, typeof(MainActivity));
_intent.SetFlags(ActivityFlags.NewTask);
context.StartService(_intent);
}
}
catch (System.Exception ex)
{
Toast.MakeText(context, ex.Message, ToastLength.Short).Show();
}
}
}
这种开机自启的方式不好的地方在于,需要在安装之后手动启动一下,才能收听广播。如果有好的方案,请不吝赐教