MDM(Mobile Device Manager) 通俗来讲就是管理设备使用
国内 MDM 服务商有 360 等
国外 MDM 服务商有 hexnode 等
当你在设备上配置了 DeviceOwner 后,状态栏下拉中会多出如下
Android Device Administration 应用的能力
接下来我们自己写一个 MDM apk,打开 AS 新建一个工程,就叫 DeviceOwnerDemo,包名 cn.test.deviceownerdemo
public class TestDeviceAdminReceiver extends DeviceAdminReceiver {
@Override
public void onReceive(@NonNull Context context, @NonNull Intent intent) {
super.onReceive(context, intent);
String action = intent.getAction();
Log.e("TestDeviceAdminReceiver","action="+action);
//action=android.app.action.DEVICE_ADMIN_ENABLED
}
}
<receiver
android:name=".TestDeviceAdminReceiver"
android:permission="android.permission.BIND_DEVICE_ADMIN">
<intent-filter>
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
<action android:name="android.app.action.PROFILE_PROVISIONING_COMPLETE" />
</intent-filter>
<meta-data
android:name="android.app.device_admin"
android:resource="@xml/device_admin" />
</receiver>
<?xml version="1.0" encoding="utf-8"?>
<device-admin xmlns:android="http://schemas.android.com/apk/res/android">
<uses-policies>
<watch-login />
<reset-password />
<force-lock />
<wipe-data />
<encrypted-storage />
<disable-camera />
<limit-password />
<expire-password />
<disable-keyguard-features />
</uses-policies>
</device-admin>
这样一个最简单的 MDM 应用就完成了,接下来就需要激活权限
DeviceAdmin 权限
通过 app 申请,先手动授权
DevicePolicyManager mDPM = (DevicePolicyManager)getSystemService(Context.DEVICE_POLICY_SERVICE);
ComponentName testDeviceAdmin = new ComponentName(this, TestDeviceAdminReceiver.class);
boolean adminActive = mDPM.isAdminActive(testDeviceAdmin);
if (!adminActive){
Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, testDeviceAdmin);
intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION, "");
startActivityForResult(intent, REQUEST_ACTIVATE);
}
DeviceOwner 权限,通过 adb 设置
adb shell dpm set-device-owner cn.test.deviceownerdemo/.TestDeviceAdminReceiver
DevicePolicyManager mDPM = (DevicePolicyManager)getSystemService(Context.DEVICE_POLICY_SERVICE);
ComponentName testDeviceAdmin = new ComponentName(this, TestDeviceAdminReceiver.class);
if(mDPM.isAdminActive(testDeviceAdmin)){
mDPM.setStatusBarDisabled(testDeviceAdmin, false);
}
使用上搞清楚了,接下来我们就来修改源码了,一般 MDM apk 都是客户提供的,都需要预装到系统中且默认授权
实际上重要的就两个 xml 文件 device_owner_2.xml device_policies.xml
当你手动授权成功后,在设备 /data/system/ 目录下就有这两文件,所以我们可以将两个 xml 预制到系统中
data 分区下预制文件,开机会无法启动,所以我们曲线救国,先将文件放到 system 下,系统起来后在 init.rc 执行 copy
注意 xml 文件中的 package 和 name 对应你实际的 MDM 包名
system/extras/su/device_owner_2.xml
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<root>
<device-owner package="cn.test.deviceownerdemo" name="" component="cn.test.deviceownerdemo/cn.test.deviceownerdemo.TestDeviceAdminReceiver" userRestrictionsMigrated="true" canAccessDeviceIds="true" />
<device-owner-context userId="0" />
</root>
system/extras/su/device_policies.xml
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<policies setup-complete="true" provisioning-state="3">
<admin name="cn.test.deviceownerdemo/cn.test.deviceownerdemo.TestDeviceAdminReceiver">
<policies flags="991" />
<strong-auth-unlock-timeout value="0" />
<test-only-admin value="true" />
<user-restrictions no_add_managed_profile="true" />
<default-enabled-user-restrictions>
<restriction value="no_add_managed_profile" />
</default-enabled-user-restrictions>
<cross-profile-calendar-packages />
</admin>
<lock-task-features value="16" />
</policies>
device/mediateksample/k67v1_64_bsp/device.mk
PRODUCT_COPY_FILES += \
system/extras/su/device_policies.xml:system/device_policies.xml \
system/extras/su/device_owner_2.xml:system/device_owner_2.xml
system/core/rootdir/init.rc
copy /system/device_policies.xml /data/system/device_policies.xml
chmod 0600 /data/system/device_policies.xml
chown system system /data/system/device_policies.xml
copy /system/device_owner_2.xml /data/system/device_owner_2.xml
chmod 0600 /data/system/device_owner_2.xml
chown system system /data/system/device_owner_2.xml
这样烧写后,MDM apk 就默认拥有 DeviceOwner 权限了,DeviceAdmin 权限可以通过
hide 方法 DevicePolicyManager.setActiveAdmin(@NonNull ComponentName policyReceiver, boolean refreshing, int userHandle)
随便找个系统应用,Settings 里加一下就行
对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl
我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此
我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r
这是在Ruby中设置默认值的常用方法:classQuietByDefaultdefinitialize(opts={})@verbose=opts[:verbose]endend这是一个容易落入的陷阱:classVerboseNoMatterWhatdefinitialize(opts={})@verbose=opts[:verbose]||trueendend正确的做法是:classVerboseByDefaultdefinitialize(opts={})@verbose=opts.include?(:verbose)?opts[:verbose]:trueendend编写Verb
刚入门rails,开始慢慢理解。有人可以解释或给我一些关于在application_controller中编码的好处或时间和原因的想法吗?有哪些用例。您如何为Rails应用程序使用应用程序Controller?我不想在那里放太多代码,因为据我了解,每个请求都会调用此Controller。这是真的? 最佳答案 ApplicationController实际上是您应用程序中的每个其他Controller都将从中继承的类(尽管这不是强制性的)。我同意不要用太多代码弄乱它并保持干净整洁的态度,尽管在某些情况下ApplicationContr
我想设置一个默认日期,例如实际日期,我该如何设置?还有如何在组合框中设置默认值顺便问一下,date_field_tag和date_field之间有什么区别? 最佳答案 试试这个:将默认日期作为第二个参数传递。youcorrectlysetthedefaultvalueofcomboboxasshowninyourquestion. 关于ruby-on-rails-date_field_tag,如何设置默认日期?[rails上的ruby],我们在StackOverflow上找到一个类似的问
我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R
两者都可以defsetup(options={})options.reverse_merge:size=>25,:velocity=>10end和defsetup(options={}){:size=>25,:velocity=>10}.merge(options)end在方法的参数中分配默认值。问题是:哪个更好?您更愿意使用哪一个?在性能、代码可读性或其他方面有什么不同吗?编辑:我无意中添加了bang(!)...并不是要询问nobang方法与bang方法之间的区别 最佳答案 我倾向于使用reverse_merge方法:option
是否可以在应用程序中包含的gem代码中知道应用程序的Rails文件系统根目录?这是gem来源的示例:moduleMyGemdefself.included(base)putsRails.root#returnnilendendActionController::Base.send:include,MyGem谢谢,抱歉我的英语不好 最佳答案 我发现解决类似问题的解决方案是使用railtie初始化程序包含我的模块。所以,在你的/lib/mygem/railtie.rbmoduleMyGemclassRailtie使用此代码,您的模块将在
无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD