Sparky


  • 首页

  • 归档

未命名

发表于 2019-05-06

注解及aop小结

主要包括三方面的知识

  • 自定义注解
  • aop
  • gradle插件开发

注解主要是了解如何使用元注解定义注解,如何解析注解

aop的概述及AspectJ的基本用法

gradle插件开发指的是如何利用gradle自定义plugin在项目中引用

我们将利用以上三点知识,模仿hugo做一个实战项目

aop-gradle插件扩展

发表于 2019-05-06

gradle插件扩展

我们已经学会了定义自定义gradle插件,但是我们还需要定义一些gradle插件里的属性,就像logger一样定义一个enable属性控制是否输出日志

logger {
    enable false
}

基础用法

像这样logger就是一个自定义的属性,其实是很简单的

// 首先需要定义一个类,定义好属性和方法
class LoogerExtension {
    def enable = true

    def setMessage(String text) {
        System.out.println(text)
    }
}

class HugoPlugin implements Plugin<Project> {
    @Override
    void apply(Project project) {
        ...

        project.extensions.create("logger", LoggerExtension)
    }
}

// 然后就可以在gradle中使用了
logger {
    enable false 或者 enable = false
    setMessage 'disable' 或者 message 'disable'
}

多个属性

如果要定义多个属性,例如要发布多平台就需要定义多个类似的属性

platforms {
    wandoujia {
        name = 'xxx'
        api_key = 'xxx'
    }

    xiaomi {
        name = 'xxx'
        api_key = 'xxx'
    }
}

首先需要定义属性类

class PlatformExtension {
    def name
    def api_key

    /*
    需要string的构造函数,否则报错:
    A problem occurred evaluating project ':aop'.
    > Could not create an instance of type org.cmdmac.aopplugin.ListExtention.
       > Could not find any public constructor for class org.cmdmac.aopplugin.ListExtention which accepts parameters [java.lang.String].
    public PlatformExtension(String n) {
        this.name = n
    }
}

然后在Plugin中添加

class PlatformPlugin implements Plugin<Project> {
    @Override
    void apply(Project porject) {
        ...

        def platforms = project.container(PlatformExtension)
        project.extensions.platform = platforms
    }
}

使用:

platforms {
        wandoujia {
            name = 'xxx'
            api_key = 'xxx'
        }

        xiaomi {
            name = 'xxx'
            api_key = 'xxx'
        }
    }

属性嵌套

类似这样:

android{
    compileSdkVersion 19
    defaultConfig {
        applicationId 'xxx'
    }
}

首先定义Extension

class AndroidExtension {
    def Integer compileSdkVerion

    def DefaultConfigExtension defaultConfig

    public AndroidExtension (org.gradle.internal.impldep.org.sonatype.maven.polyglot.groovy.builder.factory.ObjectFactory objectFactory){
        defaultConfig = objectFactory.newInstance(DefaultConfigExtension)
    }

    void defaultConfig(Action<? super DefaulConfigExtension> action){
        action.execute(defaultConfig)
    }

    class DefaultConfigExtension {
        def String applicationId
    }
}

在Plugin中创建extension

...
project.extensions.create("android", AndroidExtension, project.objects)

aop-gradle插件

发表于 2019-05-06
  1. variants分两种分别是libraryVariants和applicationVariants

    final def variants = project.android.libraryVariants
    final def variants = project.android.applicationVariants
    
  2. 如果aop的代码在另外一个module中,那么你的app module也需要添加aspectj的相关依赖,并且aop module的依赖和app module的依赖只有variants不同。

  3. 我们要像引用第三方插件那样引用这个包,如果要添加这么多配置的话会很麻烦,所以我们可以开发一个gradle插件,引用插件来配置这些依赖。

创建groovy项目:(如果是idea的话直接创建groovy项目即可)

  1. 创建module,类型为Android library
  2. 修改module下的java目录为groovy目录
  3. 删除res目录下的所有子文件和目录,并修改res目录名为resources
  4. 在resources下创建META-INF/gradle-plugins/$(plugin-name).properties。例如我们要创建的插件名为com.sparky.plugin,那么在app module下引用就是 apply plugin: ‘com.sparky.plugin’,这里需要定义的文件名就是com.sparky.plugin.properties
  5. 在xx.properties文件下注册plugin文件,对应groovy包下的全包路径类名。例如定义plugin的类为com.dou.plugin.TestPlugin.groovy,则这里要添加implementation-class=com.dou.plugin.TestPlugin
  6. 创建plugin文件并编辑,要实现Plugin接口,这些依赖包需要导入

    compile gradleApi()
    compile localGroovy()
    implementation 'com.android.tools.build:gradle:3.1.2'
    //aspectj需要到的类
    implementation 'org.aspectj:aspectjtools:1.8.5'
    

    注意: 如果出错一定要仔细看log,例如我plugin文件用到AppPlugin和LibraryPlugin,没有自动导包,上传到maven仓库的时候不会报错,apply plugin之后编译的时候会报错,有日志

  7. 定义maven仓库的task

    apply plugin: "maven"
    group = 'com.dou.aopplugin'
    version = '1.0.0'
    
    uploadArchives{
        repositories{
            mavenDeployer{
                repository(url:uri("../repo"))
            }
        }
    }
    
  8. 项目中引用,注意添加 mavenLocal

    project build.gradle下:
    buildscript{
        repositories{
            ...
            mavenLocal() // 本地maven需要这行,非本地要删除
            maven{
                url "/home/dou/work/workspace/demos/aopdemo/repo"
            }
        }
    }
    
    dependencies{
        ...
        classpath 'com.dou.aopplugin:aopplugin:1.0.0'
    }
    

Android AOP基础

发表于 2019-05-06

Android AOP基础

AOP和AspectJ

通过预编译方式或者运行期动态代理实现程序功能的统一维护的一种技术。

面向对象编程主要用于为同一对象层面的公用行为建模。弱点是不能将公共行为用在多个无关对象之间。而面向切片编程最大的优点就是将公共行为用在不同的对象模块上。

AspectJ是一种语言来支持aop的,但是他也提供了java的方式使用AspectJ。

AspectJ的基本用法

  • joinpoint
  • pointcut
  • advice

使用aop的步骤

1. 添加配置

在module下的build.gradle文件中添加:

buildscript{

    repositories {
        mavenCentral()
    }

    dependencies{
        classpath 'org.aspectj:aspectjtools:1.8.9'
        classpath 'org.aspectj:aspectjweaver:1.8.9'
    }
}

... // 省略

dependencies {
    ...
    implementation 'org.aspectj:aspectjrt:1.8.9'
}

... // 省略

import org.aspectj.bridge.IMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Main
final def log = project.logger
final def variants = project.android.applicationVariants

variants.all { variant ->
    if (!variant.buildType.isDebuggable()) {
        log.debug("Skipping non-debuggable build type '${variant.buildType.name}'.")
        return;
    }

    JavaCompile javaCompile = variant.javaCompile
    javaCompile.doLast {
        String[] args = ["-showWeaveInfo",
                         "-1.8",
                         "-inpath", javaCompile.destinationDir.toString(),
                         "-aspectpath", javaCompile.classpath.asPath,
                         "-d", javaCompile.destinationDir.toString(),
                         "-classpath", javaCompile.classpath.asPath,
                         "-bootclasspath", project.android.bootClasspath.join(File.pathSeparator)]
        log.debug "ajc args: " + Arrays.toString(args)

        MessageHandler handler = new MessageHandler(true);
        new Main().run(args, handler);
        for (IMessage message : handler.getMessages(null, true)) {
            switch (message.getKind()) {
                case IMessage.ABORT:
                case IMessage.ERROR:
                case IMessage.FAIL:
                    log.error message.message, message.thrown
                    break;
                case IMessage.WARNING:
                    log.warn message.message, message.thrown
                    break;
                case IMessage.INFO:
                    log.info message.message, message.thrown
                    break;
                case IMessage.DEBUG:
                    log.debug message.message, message.thrown
                    break;
            }
        }
    }
}

2. 创建切片类

@Aspect
public class TestAspect {

    @Pointcut("execution(* com.dou.demo.aop_demo.MainActivity.test(..))")
    public void pointcut(){}

    @Around("pointcut()")
    public void test(ProceedingJoinPoint point) throws Throwable{
        System.out.println("@test start");
        point.proceed();
        System.out.println("@test end");
    }
}

实践(对方法进行耗时计算/权限检查)

定义annotation

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.CLASS)
public @interface Hugo {
}

使用注解

@Hugo
 private void time_consumer() {
     for (int i = 0; i < 100; i++){
         try {
             Thread.sleep(10);
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
     }
 }

定义切片

@Aspect
public class HugoAspect {
    @Pointcut("execution(@com.dou.demo.aop_demo.Hugo * *(..))")
    public void hugo(){}

    @Around("hugo()")
    public void timer(ProceedingJoinPoint point) throws Throwable{
        System.out.println("@hugo start");
        MethodSignature signature = (MethodSignature) point.getSignature();
        long starttime = System.currentTimeMillis();
        point.proceed();
        long endtime = System.currentTimeMillis();
        System.out.println(signature.getMethod().getName() + " 方法耗时: " + (endtime - starttime) + " ms");
        System.out.println("@hugo end");
    }
}

重新clean,run

其它一个实例见源码

源码

aop-demo

参考

深入理解Android之AOP

Android AOP-North_2016

Android进阶系列之AOP面向切面编程

AspectJ的基本用法

Android高级进阶(目录结构)

发表于 2019-05-06

Android高级进阶(目录结构)

  • 基础篇。Android View,动画,support library,gradle,ndk,anr,异步技术,注解,数据序列化和hybrid等。
  • 系统架构篇。主要包括UI架构,时间总线,编码规范和技术堆栈等。
  • 经验总结篇。主要包括实际开发中的一些经验总结。64K方法数限制,插件框架,推送原理,app瘦身和crash统计等。
  • 新技术篇。顾名思义,包括函数式编程,依赖注入,Kotlin,react native,hot fix,aop和Facebook buck等知识点。
  • 性能优化篇。常见的性能优化手段,包括代码优化,图片优化,电量优化,布局优化,网络优化。
  • 移动安全篇。主要包括混淆,反编译,秘钥隐藏,加固和如何编译安全的代码。
  • 工具篇。介绍几个工具,Android studio,stetho,leakcanary,redex等
  • 测试篇。包括Android单元测试,UI自动化测试,静态代码分析和自动化构建等

未命名

发表于 2019-05-06

阅读器取词标注

原理

阅读器sdk一般会给出每一个文字的区域,如果要把需要的取词区域取出,需要将这些文字区域整合起来。

  1. 找到所有的点: 每个文字是一个rect,首先需要将要取词的rect集合取出来
  2. 行内合并: 判断如果是一行就把这一行的rect整合为一个大rect,可以得到几个行rect集合columnRect
  3. 求出拐角点的集合: 分两次遍历columnRect,第一次正序,求出右侧的拐角点。第二次倒叙遍历,求出左侧的拐角点。
  4. 绘制路径: 将这些拐角点连接起来就可以得到所有的文字区域。

画下划线的话是要求出行rect的底线即可。

FBReader源码分析

发表于 2019-05-06

FBReader源码分析-menu菜单

1. 点击屏幕中部显示菜单流程

2. 显示菜单内容

在上一节的分析中我们已经知道,菜单的显示在页面的oncreateoptionmenu中完成的。

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    super.onCreateOptionsMenu(menu);

    setupMenu(menu);

    return true;
}

这个方法代码很少,知识简单的调用了setupMenu(menu)方法。

private void setupMenu(Menu menu) {
    final String menuLanguage = ZLResource.getLanguageOption().getValue();
    if (menuLanguage.equals(myMenuLanguage)) {
        return;
    }
    myMenuLanguage = menuLanguage;

    menu.clear();
    fillMenu(menu, MenuData.topLevelNodes());
    synchronized (myPluginActions) {
        int index = 0;
        for (PluginApi.ActionInfo info : myPluginActions) {
            if (info instanceof PluginApi.MenuActionInfo) {
                addMenuItem(
                    menu,
                    PLUGIN_ACTION_PREFIX + index++,
                    ((PluginApi.MenuActionInfo)info).MenuItemName
                );
            }
        }
    }

    refresh();
}

这个方法中,MenuData.getTopLevelNodes()即是获取菜单条目数据的方法,fillMenu()是遍历这些条目,并调用addMenuItem()将条目设置给Android optionmenu

private void addMenuItem(Menu menu, String actionId, Integer iconId, String name) {
    if (name == null) {
        name = ZLResource.resource("menu").getResource(actionId).getValue();
    }
    final MenuItem menuItem = menu.add(name);
    if (iconId != null) {
        menuItem.setIcon(iconId);
    }
    menuItem.setOnMenuItemClickListener(myMenuListener);
    myMenuItemMap.put(menuItem, actionId);
}

包括设置name,icon,以及点击事件。其中name是从assert文件中加载的,用的是sax解析。

回到setmenu方法中,填充完menu会遍历myPluginActions集合,然后将myPluginActions的item添加到menu中。

在addMenuItem中,会给每个条目设置点击事件,然后将item和actionid键值对保存到myMenuItemMap中。这个mymenulistener就是提供actionidid,然后由myIdToActionMap找到对应的actionid响应点击事件。

myIdToActionMap添加数据是在ZLApplication.addAction()方法,这个方法的调用有几个地方,1,fbreader.myPluginInfoReceiver.onreceive 2, fbreader.oncreate 3. fbreaderapp的构造方法中。也就是说基本上这些事件都是在应用初始化的时候都定义好了。

3. 设置相关(以设置翻页方式为例)

在上一节我们分析了菜单条目的加载,主要就是要找到菜单对应的action,我们在fbreader.oncreate方法中发现ActionCode.SHOW_PREFERENCES即为我们要找的阅读设置相关设置

myFBReaderApp.addAction(ActionCode.SHOW_PREFERENCES, new ShowPreferencesAction(this, myFBReaderApp));

在这个action的run方法中我们发现PreferenceActivity即是我们要找的activity文件。

在它的父类的oncreate()方法中

@Override
protected void onCreate(Bundle bundle) {
    super.onCreate(bundle);

    // 异常捕捉
    Thread.setDefaultUncaughtExceptionHandler(new org.geometerplus.zlibrary.ui.android.library.UncaughtExceptionHandler(this));

    // 创建数据库
    SQLiteCookieDatabase.init(this);

    // 创建preferencescreen
    myScreen = getPreferenceManager().createPreferenceScreen(this);

    final Intent intent = getIntent();
    final Uri data = intent.getData();
    final String screenId;
    if (Intent.ACTION_VIEW.equals(intent.getAction())
            && data != null && "fbreader-preferences".equals(data.getScheme())) {
        screenId = data.getEncodedSchemeSpecificPart();
    } else {
        screenId = intent.getStringExtra(SCREEN_KEY);
    }

    Config.Instance().runOnConnect(new Runnable() {
        public void run() {
            // 抽象方法,子类初始化
            init(intent);

            // 获取要显示的screen
            final Screen screen = myScreenMap.get(screenId);

            // 设置preferencescreen
            setPreferenceScreen(screen != null ? screen.myScreen : myScreen);
        }
    });
}

设置页面采用了sharepreference的方式,并且采用过时的方法先获取preferencescreen再设置preferencescreen,这与我们常用的addPreferenceFromResource一样。

init()方法是抽象方法,具体实现就是PreferenceActivity实现的,这个方法中的代码很多,但是主要做的都是创建各种preference,并把preference添加到preferscreen。

FBReader默认参数设置

我们要在项目中使用fbreader的话,必须要对它做自己的处理,例如修改默认字体,默认背景,翻页方式,默认字体大小等等,上一节我们了解了fbreader是如何设置翻页方式的,我们讲到在init方法中会创建很多的preferencescreen,其中翻页的菜单对应的就是scrollingScreen,

scrollingScreen.addOption(pageTurningOptions.Animation, "animation");
scrollingScreen.addPreference(new AnimationSpeedPreference(
    this,
    scrollingScreen.Resource,
    "animationSpeed",
    pageTurningOptions.AnimationSpeed
));
scrollingScreen.addOption(pageTurningOptions.Horizontal, "horizontal");

设置翻页的代码就这么多,一眼就能看出来第一行scrollingScreen.addOption(pageTurningOptions.Animation, “animation”);就是我们要找的翻页方式设置,

public <T extends Enum<T>> Preference addOption(ZLEnumOption<T> option, String key) {
        return addPreference(
            new ZLEnumPreference<T>(ZLPreferenceActivity.this, option, Resource.getResource(key))
        );
    }

ZLEnumPreference是ListPreference的子类,用于显示列表菜单,相当于现在的radiugroup,option用于设置初始值,key用于加载对应的选项列表。

我们知道了这个PageTurningOptions对象是用来设置初始值的,然后我们ctrl+鼠标左键看到,这个类是在FBReaderApp中实例化的,

public class PageTurningOptions {
public static enum FingerScrollingType {
    byTap, byFlick, byTapAndFlick
}
public final ZLEnumOption<FingerScrollingType> FingerScrolling =
    new ZLEnumOption<FingerScrollingType>("Scrolling", "Finger", FingerScrollingType.byTapAndFlick);

// 设置默认翻页无动画
//    public final ZLEnumOption<ZLView.Animation> Animation =
//        new ZLEnumOption<ZLView.Animation>("Scrolling", "Animation", ZLView.Animation.slide);
public final ZLEnumOption<ZLView.Animation> Animation =
    new ZLEnumOption<ZLView.Animation>("Scrolling", "Animation", ZLView.Animation.none);
public final ZLIntegerRangeOption AnimationSpeed =
    new ZLIntegerRangeOption("Scrolling", "AnimationSpeed", 1, 10, 7);

public final ZLBooleanOption Horizontal =
    new ZLBooleanOption("Scrolling", "Horizontal", true);
public final ZLStringOption TapZoneMap =
    new ZLStringOption("Scrolling", "TapZoneMap", "");
}

所以就可以做如上的修改了。
其实打开PageTurningOption所在的目录,这个option目录下还包括ViewOption,ImageOption等,所以很多默认参数修改都可以在这里做。

FBReader学习笔记

发表于 2019-05-06

FBReader项目笔记

项目结构

fbreader项目结构

jni源码结构

assets结构

java代码结构
java代码没有看完,有的类自己也不知道是做什么的

kernel源码目录

发表于 2019-05-06

kernel源码目录

Document

一些说明文档

android
arch

所有与系统架构相关的代码都保存在此目录以及include/asm-xx目录中,每种架构对应的子目录都包括下边的目录

  • kernel, 存放支持系统架构所特有的诸如信号量处理和SMP之类特征的实现。
  • lib,存放体系结构特有的诸如strlen和memcpy之类的通用函数的实现。
  • mm,存放体系结构特有的内存管理程序的实现。

除了上述的3个子目录之外,大多数还有boot目录,存放这种硬件平台上启动内核所使用的部分或者全部平台特有代码。

block

保存了block层的实现代码

crypto

保存了内核本身所使用的加密api信息,实现了常用的加密和散列算法,还有一些压缩和crc校验算法

drivers

显卡,网卡,scsi适配器,pci总线,usb总线和其它linux支持的外围设备或总线的驱动程序都可以在这里找到。

firmware
fs

此目录保存了虚拟文件系统的代码还有各个不同文件系统的代码。linux支持的所有文件系统在fs下都有一个对应的目录。

include

此目录包括内核中大部分的头文件,

init

保存内核的初始化代码,包括main.c、创建早期用户空间的代码以及其它初始化代码。

ipc

包含了共享内存,信号量和其它形式ipc的代码

kernel

内核中最核心的部分,包括了进程的调度,以及进程的创建和销毁等,和系统架构有关的另外一部分代码在arch/../kernel目录下

lib

此目录保存了库代码,这些代码实现了一个标准C库的通用子集,包括字符串和内存操作等函数

mm

包含和与系统架构无关的内存管理的代码,与体系有关的内存管理的代码在arch/../mm目录下

net

保存了和网络相关的代码,实现了常见的网络协议,如TCP/IP,IPX等

samples
scripts

包含了配置内核的脚本文件。如make menuconfig,make xconfig等

security

包含了linux不同的安全模型的代码,比如linux se

sound

保存了声卡驱动以及其它声音相关的代码

tools
usr

实现了用于打包和压缩的cpio

virt

未命名

发表于 2019-05-06

全志B288修改日志

  • 2018.3.2 【修改】隐藏NavigationBar, 步骤: frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar,java文件line 431设置showNav = false;

  • 2018/3/5 【修改】修改lcd_density默认配置为160,步骤:device/softwinner/lark-eink-perf/lark_eink_perf.mk,修改ro.sf.lcd_density=167 –> ro.sf.lcd_density=160 (删除out/target/product/lark-eink-perf1/system/build.prop之后再编译)

  • 2018/3/5 【修改】预置apk,步骤:

    1. 添加lib库。将apk里依赖的so库复制到device/softwinner/lark-common/prebuild/apklib/,修改device/softwinner/lark-common/prebuild/apklib/下的Android.mk文件,

      include $(CLEAR_VARS)
      LOCAL_MODULE_TAGS := optional
      LOCAL_PREBUILT_LIBS := libBugly.so libluajit.so liblzma.so
      include $(BUILD_MULTI_PREBUILT)
      
    2. 添加apk。将apk包复制到device/softwinner/lark-common/prebuild/apk/,修改device/softwinner/lark-common/prebuild/Android.mk文件,

      include $(CLEAR_VARS)
      LOCAL_MODULE := MuPDF
      LOCAL_MODULE_TAGS := optional
      LOCAL_SRC_FILES := MuPDF.apk
      LOCAL_MODULE_CLASS := APPS
      LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
      LOCAL_CERTIFICATE := PRESIGNED
      LOCAL_REQUIRED_MODULES := libmupdf_java
      include $(BUILD_PREBUILT)
      
    3. 添加到配置文件。进入lark-eink-perf1这个我们要编译的设备的目录,修改下边的lark-eink-perf1.mk,

      PRODUCT_PACKAGES += MuPDF
      

      注意:apk需要是系统签名的apk

  • 设置默认launcher,方法:参考android 开机默认进入指定Launcher@闲庭信步_wwd,1. 修改开机启动的默认launcher。在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件下,修改startHomeActivityLocked()方法为如下,

    boolean startHomeActivityLocked(int userId) {
    if (mHeadless) {
    // Added because none of the other calls to ensureBootCompleted seem to fire
    // when running headless.
    ensureBootCompleted();
    return false;
    }
    
    if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
        && mTopAction == null) {
    // We are running in factory test mode, but unable to find
    // the factory test app, so just sit around displaying the
    // error message and don't try to start anything.
    return false;
    

    }
    Intent intent = getHomeIntent();
    ActivityInfo aInfo =

    resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
    if (aInfo != null) {
    //add wwd start
    PackageManager pm = mContext.getPackageManager();
    Intent newintent = new Intent(Intent.ACTION_MAIN);
    newintent.addCategory(Intent.CATEGORY_HOME);
    
    List<ResolveInfo> resolveInfoList = pm.queryIntentActivities(newintent, 0);
    //判断带有Intent.CATEGORY_HOME标签的所有activity中如果有你指定的activity则替换
    if(resolveInfoList != null){
        int size = resolveInfoList.size();
        for(int i = 0; i < size; i++){
            ResolveInfo rInfo = resolveInfoList.get(i);
            if(rInfo.activityInfo.name.equals("com.android.launcher3.Launcher")){
                aInfo = rInfo.activityInfo;
            }
        }
    }
    //add wwd stop
    intent.setComponent(new ComponentName(
            aInfo.applicationInfo.packageName, aInfo.name));
    // Don't do this if the home app is currently being
    // instrumented.
    aInfo = new ActivityInfo(aInfo);
    aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
    ProcessRecord app = getProcessRecordLocked(aInfo.processName,
            aInfo.applicationInfo.uid, true);
    if (app == null || app.instrumentationClass == null) {
        intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
        //这里启动你已替换过的activity
        mStackSupervisor.startHomeActivity(intent, aInfo);
    }
    }
    
    return true;
    }
    

    2.修改按home键强制启动的launcher。在frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java文件中,修改init()为:

    public void init(Context context, IWindowManager windowManager,
        WindowManagerFuncs windowManagerFuncs) {
        ......
        mHomeIntent =  new Intent(Intent.ACTION_MAIN, null);
    mHomeIntent.addCategory(Intent.CATEGORY_HOME);
    //add wwd start
    ComponentName mHomecom = new ComponentName("com.android.launcher3", "com.android.launcher3.Launcher"); 
    mHomeIntent.setComponent(mHomecom);
    //add wwd stop
    mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
            | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
        ......
    }
    
  • 2018/3/8 修改默认参数,

    1. 默认屏幕亮度,在frameworks/base/packages/SettingProvider/res/values/default.xml
        <!-- Default screen brightness, from 0 to 255.  102 is 40%. -->
        <integer name="def_screen_brightness">102</integer>
    2. 默认屏幕关闭时间
        在frameworks/base/packages/SettingProvider/res/values/default.xml,
        <integer name="def_screen_off_timeout">300000</integer>
    3. 默认字体大小,小/普通/大/很大 分别对应 0.85/1/1.15/1.3
        在/b288/android/device/softwinner/lark-eink-perf1/lark_eink_perf1.mk
        PRODUCT_PROPERTY_OVERRIDES += \
        ro.font.scale=1.15 \            
    
  • 2018/3/12,预置文件到sdcard.在device.mk文件中添加

    PRODUCT_COPY_FILES += \
        ${源文件位置}:${内置到的系统位置}
    
    例如
    PRODUCT_COPY_FILES += \
        device/softwinner/lark-eink-perf1/media/testbooks/xx.txt:system/media/testbook/xx.txt \
    
  • 2018/5/14, 显示屏显示异常. 烧入程序之后,由于之前设备烧入过linux程序,系统中存在以下两个文件private/default.bin,private/default_4.bin,在系统启动时默认先使用private路径下的default.bin文件,导致设置vcom电压不对,所以这里删除default.bin和default_4.bin.在串口或者adb中使用命令

    mount -o remount,rw /private
    rm default.bin
    rm default_4.bin, reboot
    
  • 2018/5/15, 更改开机铃声大小, 修改有两种方式. 第一种是直接用软件修改声音文件的大小,这种可以让客户提供合适的声音文件放在/device/softwinner/lark-eink-perf1/media下,命名为boot.wav即可. 第二种方法通过代码修改,在frameworks/base/cmds/bootanimation/BootAnimation.cpp,在playBootMusic方法中,再mp -> prepare之前添加

    set volume level
    float volume = 0.9;
    mp->setVolume(volume, volume);
    
  • 2018/5/15, 关闭开机启动的log.

    echo 0 > /prop/sys/kernel/printk
    
  • 2018/5/15, 修改开机log,开机log是再kernel层修改的.文件是在/lichee/tools/pack/chips/sun8iw10p1/boot-resource/boot-resource下的bootlogo.bmp,直接同名覆盖即可.

  • 2018/5/15, 修改开机动画.开机动画的存放位置是再/device/softwinner/lark-eink-perf1/media下的bootanimation.zip,和开机铃声再同一目录下.
12…10
Sparky

Sparky

我是谁?我在做什么?我为什么要这么做?我想做什么?我要怎么做?

99 日志
© 2019 Sparky
由 Hexo 强力驱动
|
主题 — NexT.Gemini v5.1.4