Skip to content

haohz1987/Launcher-master

Repository files navigation

Launcher3

apk体验包下载

jni防反编译步骤

  • 创建工程manager -> main下创建*.mk,*.c文件

  • 将原项目中的AndroidManifest.xml文件迁移过来

  • 最外层gradle.properties文件加上旧版代码支持,android.useDeprecatedNdk=true

  • 将服务端地址、非对称加密文件公钥等信息加入到*.c,在build.gradle中添加c编译支撑

    externalNativeBuild { ndkBuild { path 'src/main/jni/Android.mk' } }

  • 配置项目文件,调用C程序,详见NativeEngine,LauncherConfig

  • 测试是否成功调用:进入主程序,显示配置测试服务端参数的弹窗.屏蔽弹窗修改

    // 测试环境-177 ENV = new TestEnv("10.148.181.177", 8080, VERSION, CHANNEL, "", true, true); 调用代码在Launcher.java中的onresume()(配置IPC通讯入口) 或者修改 // 非生产地址,打印log,并设置银联测试地址;生产地址,不打印log,设置银联生产地址 if (!SERVER.contains(ser)) {……}

img

jni使用语法

如果本地代码是C++(.cpp或者.cc),要使用extern "c"{}把本地方法扩进去。 extern "C"{ JNIEXPORT jstring JNICALL Java_scut_carson_1ho_ndk_1demo_MainActivity_getFromJNI(JNIEnv *env, jobject obj ){ // 参数说明 // 1. JNIEnv:代表了VM里面的环境,本地的代码可以通过该参数与Java代码进行操作 // 2. obj:定义JNI方法的类的一个本地引用(this) return env -> NewStringUTF("Hello i am from JNI!"); // 上述代码是返回一个String类型的"Hello i am from JNI!"字符串 } }

JNIEXPORT jstring JNICALL中的JNIEXPORT 和 JNICALL不能省 关于方法名Java_scut_carson_1ho_ndk_1demo_MainActivity_getFromJNI 格式 = Java 包名 _ 类名_Java需要调用的方法名(scut.carson_ho.ndk_demo) Java必须大写 对于包名,包名里的.要改成,_要改成_1 最后,将创建好的test.cpp文件放入到工程文件目录中的src/main/jni文件夹 若无jni文件夹,则手动创建。

Android.mk

LOCAL_PATH := $(call my-dir) // 设置工作目录,而my-dir则会返回Android.mk文件所在的目录 include $(CLEAR_VARS) // 清除几乎所有以LOCAL——PATH开头的变量(不包括LOCAL_PATH) LOCAL_MODULE := hello_jni // 设置模块的名称,即编译出来.so文件名 // 注,要和上述步骤中build.gradle中NDK节点设置的名字相同 LOCAL_SRC_FILES := test.cpp // 指定参与模块编译的C/C++源文件名 include $(BUILD_SHARED_LIBRARY) // 指定生成的静态库或者共享库在运行时依赖的共享库模块列表。

Application.mk(非必须)

APP_ABI := armeabi // 最常用的APP_ABI字段:指定需要基于哪些CPU平台的.so文件 // 常见的平台有armeabi x86 mips,其中移动设备主要是armeabi平台 // 默认情况下,Android平台会生成所有平台的.so文件,即同APP_ABI := armeabi x86 mips // 指定CPU平台类型后,就只会生成该平台的.so文件,即上述语句只会生成armeabi平台的.so文件

// 步骤1:进入该文件夹 cd /Users/Carson_Ho/AndroidStudioProjects/NDK_Demo/app/src/main/jni // 步骤2:运行NDK编译命令 ndk-build 编译成功后,在src/main/会多了两个文件夹libs & obj,其中libs下存放的是.so库文件 步骤7:在src/main/中创建一个名为jniLibs的文件夹,并将上述生成的so文件夹放到该目录下

要把名为 CPU平台的文件夹放进去,而不是把.so文件放进去 如果本来就有.so文件,那么就直接创建名为jniLibs的文件夹并放进去就可以

流程图

1.结构模块

img

img

2.launcher视图

img

3.状态

img

4.启动主流程的加载

img

5.workspace的加载绑定流程

img

6.AlApps和Widget的加载流程

img

类的定义

Launcher:主界面Activity,最核心且唯一的Activity。

LauncherAppState:单例对象,构造方法中初始化对象、注册应用安装、卸载、更新,配置变化等广播。这些广播用来实时更新桌面图标等,其receiver的实现在LauncherModel类中,LauncherModel也在这里初始化。

LauncherModel:数据处理类,保存桌面状态,提供读写数据库的API,内部类LoaderTask用来初始化桌面。

InvariantDeviceProfile:一些不变的设备相关参数管理类,其内部包涵了横竖屏模式的DeviceProfile。

WidgetPreviewLoader:存储Widget信息的数据库,内部创建了数据库widgetpreviews.db。

LauncherAppsCompat:获取已安装App列表信息的兼容抽象基类,子类依据不同版本API进行兼容性处理。

AppWidgetManagerCompat:获取AppWidget列表的兼容抽象基类,子类依据不同版本API进行兼容性处理。

LauncherStateTransitionAnimation:各类动画总管处理执行类,负责各种情况下的各种动画效果处理。

IconCache:图标缓存类,应用程序icon和title的缓存,内部类创建了数据库app_icons.db。

LauncherProvider:核心数据库类,负责launcher.db的创建与维护。

LauncherAppWidgetHost:AppWidgetHost子类,是桌面插件宿主,为了方便托拽等才继承处理的。

LauncherAppWidgetHostView:AppWidgetHostView子类,配合LauncherAppWidgetHost得到HostView。

LauncherRootView:竖屏模式下根布局,继承了InsettableFrameLayout,控制是否显示在状态栏等下面。

DragLayer:一个用来负责分发事件的ViewGroup。

DragController:DragLayer只是一个ViewGroup,具体的拖拽的处理都放到了DragController中。

BubblTextView:图标都基于他,继承自TextView。

DragView:拖动图标时跟随手指移动的View。

Folder:打开文件夹展示的View。

FolderIcon:文件夹图标。

DragSource/DropTarget:拖拽接口,DragSource表示图标从哪开始拖,DropTarget表示图标被拖到哪去。

ItemInfo:桌面上每个Item的信息数据结构,包括在第几屏、第几行、第几列、宽高等信息; 该对象与数据库中记录一一对应;该类有多个子类, 譬如FolderIcon的FolderInfo、BubbleTextView的ShortcutInfo等。

类的加载过程

Launcher3的Activity加载其实和其他应用没啥区别的,也是一样的流程,只是我们需要特别注意上图中红色的两步。 在setContentView之后我们其实又进行了一次依据设备属性的layout操作,接着才进行异步数据加载的, 所以我们的重点会放在LauncherModel的loader方法中。

在启动Launcher时数据加载绑定其实分了两大类,workspace与allApps(widgets)的加载, 他们都是通过异步加载回调UI绑定数据的

读取数据库,获取需要加载的应用快捷方式和AppWidget

整个读取的过程是在一个同步代码块中,在此之前我们先看几个重要的全局变量,

sBgWorkspaceItems--保存ItemInfo sBgAppWidgets--保存AppWidget sBgFolders--存放文件夹 sBgItemsIdMap--保存ItemInfo和其Id sBgDbIconCache--应用图标 sBgWorkspaceScreens--保存Workspace

a)遍历cursor,读取每一个app信息,根据itemType不同类型,分类保存到刚才的几个变量中。分这几种类型:ITEM_TYPE_APPLICATION、ITEM_TYPE_SHORTCUT、ITEM_TYPE_SHORTCUT、ITEM_TYPE_APPWIDGET b)读取完数据库之后,将需要移除和更新的item进行移除和更新; c)读取workspace screen数据库信息,如果有未使用过的则将其从数据库中移除。

内存信息分析

查看内存信息:adb shell dumpsys meminfo com.handpay.launch Memory Tracker也称memtrack,是一个hal层的库,不同平台库的名称不同,实现方式也有差异。 Memory Tracker 主要目标是能够跟踪以任何其他方式无法跟踪的内存,例如由进程分配但未映射到进程地址空间的纹理内存。 第二个目标是能够将进程使用的内存分类为GL,graphics等。所有的内存大小应该在实际的内存使用情况下,考虑到stride,bit depth,page size等。 EGL mtrack/GL mtrack这两项的数据就是通过memtrack获取的。

adb shell dumpsys meminfo 查看总共的EGL mtrack数值。 adb shell dumpsys meminfo surfaceflinger 查看SurfaceFlinger的值 adb shell dumpsys meminfo system_server adb shell dumpsys meminfo com.android.systemui adb shell dumpsys meminfo com.meizu.flyme.launcher adb shell dumpsys meminfo com.android.systemui:recents

分别查看system_server、launcher、systemui、recent的数据,4类加和即为总内存

adb shell dumpsys meminfo实现原理

img

修改页面初始化

修改资源文件default_workspace_4*5.xml **,dw_phone_hotseat.xml,dw_table_hotseat.xml OverviewPanel壁纸选择部分代码

显示允许的apk

设置LauncherModel类中的loadAllApps()方法, for (int i = 0; i < apps.size(); i++) { LauncherActivityInfoCompat app = apps.get(i); // This builds the icon bitmaps. // if("com.lenovo.ideafriend".equals(app.getApplicationInfo().packageName)|| // "com.lenovo.email".equals(app.getApplicationInfo().packageName) // ){//不显示的包名 // continue; // } if(app.getApplicationInfo().packageName.startsWith("com.handpay") || app.getApplicationInfo().packageName.equals("com.android.settings")){ mBgAllAppsList.add(new AppInfo(mContext, app, user, mIconCache)); } }

显示标题和设置

修改类DeleteDropTarget、InfoDropTarget的supportsDrop()方法,及 通用接口DragSource:supportsDeleteDropTarget()返回值。

参考博客地址

Releases

No releases published

Packages

No packages published

Languages