|
吾爱游客
发表于 2023-12-31 13:26
申 请 I D:无氪
个人邮箱:1919968827@qq.com
原创技术文章:安卓刷机软件(秋之盒)
源码下载:https://codeload.github.com/zsh2 ... p/refs/heads/master
准备开发环境
开发秋之盒,或进行秋之盒拓展模块开发,至少需要.NET Core SDK。而进行.NET Core开发的最好工具就是Visual Studio了。[size=0.85em]#安装Visual Studio 2019- 点击下载最新的Visual Studio Installer >>> Visual Studio Best-in-class tools for any developer(opens new window)
- 打开安装器并勾选.NET桌面开发
- 安装完毕即可
1.创建项目
#1.1 创建新项目
打开Visual Studio 2019,点击右下角创建新项目
#1.2 选择合适的目标
选择.Net Core类库 值得注意的是,如果您的拓展模块中需要编写WPF控件,请在这一步时选择WPF Custom Control Library或WPF User Control Library
#1.3 填写项目信息
#1.4 完成
此时,我们得到了一个不包含任何实际业务逻辑的空项目。
#2.安装秋之盒SDK
#2.1 打开Nuget管理界面
什么是Nuget?
NuGet是.NET项目的一种包管理器,我们可以通过其在线安装与管理项目的依赖程序集。
NuGet之于C#,就好像npm之于JavaScript,Maven之于Java,PIP之于Python,apt之于Debian
右键项目,点击管理NuGet程序包 便可以打开NuGet包的管理界面了,我们可以在这里搜索,安装,更新,卸载NuGet包。
#2.2 搜索并安装秋之盒SDK
在搜索框搜索AutumnBox.SDK即可找到秋之盒SDK。 点击安装后,秋之盒SDK就会被以依赖的形式引入到你的项目中了。
搜不到秋之盒SDK怎么办? 请在搜索时修改源为nuget
#2.3 检查
在Class1.cs中编写一段简单的代码,这段代码调用了秋之盒SDK的中获取SDK版本的接口,没有任何错误提示。 至此,秋之盒SDK安装完毕,请删除掉自动生成的无用Class1.cs。
#3.第一个拓展模块
万事俱备,是时候创建自己的第一个秋之盒拓展模块了。
#3.1 新建拓展模块类
新建一个名为EHelloAutumnBox,并且使其继承于AutumnBox.OpenFramework.Extension.Leaf.LeafExtensionBase
using AutumnBox.OpenFramework.Extension.Leaf;
namespace AtmbExtDemo
{
class EHelloAutumnBox : LeafExtensionBase
{
}
}
#3.2 添加主要方法
在类中加入一个主要方法,名称与修饰符随意,但需要挂上LMain特性。
using AutumnBox.OpenFramework.Extension.Leaf;
namespace AtmbExtDemo
{
class EHelloAutumnBox : LeafExtensionBase
{
[LMain]
public void Run(){
//业务逻辑
}
}
}
#3.3 编写逻辑
在刚刚创建的主要方法中,填入逻辑。这里,跟随我的步伐,写入以下内容:
using AutumnBox.OpenFramework.Extension;
using AutumnBox.OpenFramework.Extension.Leaf;
using AutumnBox.OpenFramework.Open;
namespace AtmbExtDemo
{
[ExtName("Hello world!")]
[ExtRequiredDeviceStates(AutumnBoxExtension.NoMatter)]
class EHelloAutumnBox : LeafExtensionBase
{
[LMain]
public void Run(IUx ux)
{
ux.Message("你好,秋之盒");
}
}
}
#Q: class上面是啥?
在秋之盒拓展模块的设计中,你的拓展模块信息通过特性(Attribute)来表达。ExtName表明了这个拓展模块的名字,ExtRequiredDeviceStates表明了这个拓展模块执行所需求的安卓设备状态,这里我们使用AutumnBoxExtension.NoMatter表示"管他设备有没有连接,管它设备什么状态,我这模块都能跑!"
C#的特性(Attribute)类似于Java中的注解,JS中的装饰器。
#Q: 主要方法多了个参数?
可以观察到,我们在主要方法的参数列表中加入了一个AutumnBox.OpenFramework.Open.IUx类型的参数,这表明我们向秋之盒请求了IUx编程接口,这个接口提供了一些系列最基础的用户交互方式。 当拓展模块被执行时,秋之盒将自动扫描主方法参数列表,并将请求的接口传入,这就是最基础的依赖注入。
#Q: 主要方法的逻辑?
之后,我们调用IUx接口提供的Message方法以向用户发送一条需要确认的信息。
#Q: 不需要写类似Manifest的东西?
不需要,秋之盒使用反射技术自动查找程序集中的拓展模块。
#Q:类的修饰符和入口修饰符为什么不是public?
秋之盒使用反射技术查找拓展模块类及其主要方法时会忽略其修饰符,即便是private。
如果想要隐藏你的拓展模块,可以在class上添加[ExtHidden]特性
#3.4 构建
右键项目,点击生成。
如果没有语法错误的话,构建将是成功的,在构建输出中我们可以看到构建出来的类库文件在哪里。
1>------ 已启动生成: 项目: AtmbExtDemo, 配置: Debug Any CPU ------
1>AtmbExtDemo -> C:\Users\zsh24\source\repos\AtmbExtDemo\AtmbExtDemo\bin\Debug\netcoreapp3.1\AtmbExtDemo.dll
========== 生成: 成功 1 个,失败 0 个,最新 0 个,跳过 0 个 ==========
#4.你好,秋之盒
#4.1 安装模块
将构建出来的.dll文件放置到秋之盒程序目录下的extensions文件夹中。
#4.2 大功告成
启动秋之盒,点击我们编写的模块即可运行。
开始
在前面的章节中,我们大概了解到秋之盒模块的名字应当class上的特性(Attribute)来声明模块的元信息(Metadata):
[ExtName("Hello world!")]
class EHelloAutumnBox : LeafExtensionBase{
//.....
}
在运行时,秋之盒会通过反射技术获取拓展模块特性中的元信息。
#先导知识: I18N
在开始学习更多知识前,首先了解一下秋之盒中常见的多语言化方法,例如:
ExtName("Happy","zh-cn:开心","zh-tw:開心")
上面的代码中表明了:秋之盒使用简体中文语言时,该拓展模块名为开心,台湾繁体中文时为開心,如果不是以上两种语言,则使用首个参数作为默认值:Happy。
当然,你可以可以选择不使用这个玩法:
//无论如何,都只会是"你好"
[ExtName("你好")]
#主要的特性
秋之盒SDK还提供了许多预置特性以及一些新的可拓展逻辑供你更好地个性化模块信息。
主要的特性均位于源码中的此目录中(在Github浏览) (opens new window)。命名空间是AutumnBox.OpenFramework.Extension。
EmptyExtension (opens new window)包含了默认的特性,建议拓展模块可以继承于其。
#ExtName
支持I18N,接收String类型的变长参数,用于表达拓展模块的人类可读名字。
[ExtName("Example Extension","zh-cn:示例拓展模块")]
#ExtRequiredDeviceStates
接收DeviceState (opens new window)作为参数,用于表明拓展模块运行所必须的设备状态,秋之盒将确保模块不会在设备不满足条件的情况下被用户启动。
[ExtRequiredDeviceStates(DeviceState.Poweron)]
扩展用法
如果想要表明拓展模块运行与设备状态无关(甚至是没有插入设备),请传入AutumnBoxExtension.NoMatter (opens new window)。如果不插入设备不可以的话,则请传入该类中的AllState常量。
想要支持多个状态,可以使用或运算符。(可以观察到DeviceState (opens new window)中的值支持这样的操作)
[ExtRequiredDeviceStates(DeviceState.Poweron | DeviceState.Recovery)]
#ExtAuth(opens new window)
支持I18N,传入一个变长String以表示拓展模块所有者信息。
[ExtAuth("Seymour Zhang","zh-cn:张三"]
#ExtDesc(opens new window)
支持I18N,传入一个变长String以表示拓展模块的简单解释信息。
[ExtDesc("此模块与地球三体组织无关","en-us:This extension have nothing to do with ETO")]
#ExtDeveloperMode(opens new window)
传入布尔值表示该模块是否开启开发者模式。如果是,则该拓展模块只会在秋之盒设置中开启调试模式后才会显示。
[ExtDeveloperMode] //Default value is true
#ExtHidden(opens new window)
传入布尔值表示该模块是否被隐藏。如果隐藏,则用户将无法直接启动该模块,即便开启调试模式。
[ExtHidden] //Default value is true
#ExtIcon(opens new window)
表示一个拓展模块的图标。目前提供两种方式。
第一种方式,嵌入资源:直接传入图标的在项目中的绝对路径即可。 例如:使用这个位置的图标的代码是:
[ExtIcon("Icons.android.png")]
图标文件一定要调整为"嵌入的资源"
第二种方式,base64字符串。声明你的方式,并将图标的base64字符串传入。
[ExtIcon("THE BASE64 STRING OF THE ICON",SourceType =ExtIconAttribute.IconSourceType.Base64Image)]
#ExtRequireRoot(opens new window)
传入布尔值,表明此模块需要设备获取ROOT才能够运行。秋之盒也会在显眼的位置标明该模块需要ROOT权限。
考虑到ROOT检测的复杂情况,秋之盒不会阻止可能没有ROOT的设备执行拓展模块,如有需要,请开发者另行测试,或贡献相关代码 (opens new window)。
#ExtRegions(opens new window)
传入String类型变长参数,表明一个可运行语言地区白名单。
[ExtRegions("zh-cn","zh-tw","en-us")]
不挂此特性则默认无地区限制。
#ExtVersion(opens new window)
传入一个至三个整型数字,表明拓展模块的版本信息。
[ExtVersion(2,1,9)]
//[ExtVersion(1,1)]
//[ExtVersion(2)]
#ExtRunnablePolicy(opens new window)
一个抽象类,开发者可继承并实现该抽象类以创建自定义的运行检测策略,用于限制模块可否被用户运行。
事实上,继承自EmptyExtension (opens new window)的拓展模块默认包含了一个基础的运行检测策略:ExtNormalRunnablePolicy (opens new window),这个默认策略确保了拓展模块只会在设备状态正确时被启动。
此外,还有一些策略由于各种原因,暂且不在此处进行介绍,如果需要请阅读相关源码 (opens new window)注释。
#获取拓展模块本身的信息
我们可以通过LeafExtensionBase.GetExtensionInfo() (opens new window)方法获取到拓展模块所有元信息。 然后使用ExtensionInfoExtension (opens new window)中提供了一系列拓展方法帮助我们获取更加特定的值。
//...
[ExtName("Test","zh-cn:测试")]
class ETest{
[LMain]
void Main(){
var extInf = this.GetExtensionInfo();
var extName = extInf.Name(); //Test 或 测试 取决于具体的语言环境
var reqState = extInf.RequiredDeviceState();
}
}
//....
#自定义的元信息
你可以继承自ExtensionInfoAttribute (opens new window)或ExtensionI18NTextInfoAttribute (opens new window)实现你自己的元信息。
#获取自定义的元信息
获取到ExtensionInfo后,获取对应键的值即可。
//...
void Main(){
var extInf = this.GetExtensionInfo();
var value = extInf["CustomKey"]();//直接获取到的是`ValueReader`函数指针,需要再次执行才能获取到真正的值
}
//...
事实上,秋之盒开放框架里大部分内置的特性都是这个原理。
在秋之盒开放框架中,定义了大量的API接口供第三方开发者调用用于与秋之盒主要程序进行沟通。
详情请看这里的源码 (opens new window)注释。(非常易读,全中文,并且都是仅包含方法声明的Interface) 所有的API实现都在秋之盒启动时被注册。在你的开发中,如果你需要使用哪一款API了,可以通过下面方式获取:
//...var nm = LakeProvider.Get<INotificationManager>();nm.Info("Hello World!");//...
获取设备信息
//如果没有选择设备则返回NULLvar selectedDevice = LakeProvider.Get<IDeviceManager>().Selected;//orselectedDevice = LakeProvider.Get<IDevice>(); |
|
发帖前要善用【论坛搜索】功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。 |
|
|
|
|