修改Recovery中的文字提示(一)

需求

默认的升级界面如下图所示,我们要修改的是中间的“正在安装系统更新”这一文字提示。
在这里插入图片描述

实现分析

在Recovery中,这一段文字并不是文本,而是从图片资源文件中截取的。资源文件在bootable\recovery目录下的各种res-hdpi/res-mdpi……文件夹中。打开installing_text.png文件,可以看出这个文件是包含了各种语言的文字提示。

在这里插入图片描述
在Recovery中,将根据传进来的本地化信息,从这个图片中截取正确的行,进行显示。那么,Recovery具体是怎么解析的呢?看下面的代码:

void ScreenRecoveryUI::LoadLocalizedBitmap(const char* filename, GRSurface** surface) {
  int result = res_create_localized_alpha_surface(filename, locale_.c_str(), surface);
  if (result < 0) {
    LOG(ERROR) << "couldn't load bitmap " << filename << " (error " << result << ")";
  }
}

int res_create_localized_alpha_surface(const char* name,
                                       const char* locale,
                                       GRSurface** pSurface) {
    GRSurface* surface = NULL;
    int result = 0;
    png_structp png_ptr = NULL;
    png_infop info_ptr = NULL;
    png_uint_32 width, height;
    png_byte channels;
    png_uint_32 y;
    std::vector<unsigned char> row;

    *pSurface = NULL;

    if (locale == NULL) {
        return result;
    }

    result = open_png(name, &png_ptr, &info_ptr, &width, &height, &channels);
    if (result < 0) return result;

    if (channels != 1) {
        result = -7;
        goto exit;
    }

    row.resize(width);
    for (y = 0; y < height; ++y) {
        png_read_row(png_ptr, row.data(), NULL);
        int w = (row[1] << 8) | row[0]; // 解析宽度
        int h = (row[3] << 8) | row[2]; // 解析高度
        __unused int len = row[4];
        char* loc = reinterpret_cast<char*>(&row[5]); // 解析语言

        if (y+1+h >= height || matches_locale(loc, locale)) {
            printf("  %20s: %s (%d x %d @ %d)\n", name, loc, w, h, y);

            surface = malloc_surface(w*h);
            if (surface == NULL) {
                result = -8;
                goto exit;
            }
            surface->width = w;
            surface->height = h;
            surface->row_bytes = w;
            surface->pixel_bytes = 1;

            int i;
            for (i = 0; i < h; ++i, ++y) {
                png_read_row(png_ptr, row.data(), NULL);
                memcpy(surface->data + i*w, row.data(), w);
            }

            *pSurface = surface;
            break;
        } else {
            int i;
            for (i = 0; i < h; ++i, ++y) {
                png_read_row(png_ptr, row.data(), NULL);
            }
        }
    }

exit:
    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
    if (result < 0 && surface != NULL) free(surface);
    return result;
}

在res_create_localized_alpha_surface()函数中,首先调用open_png()函数打开资源文件,然后遍历每一行文字,解析出宽度、高度和语言。如果语言和传进来的本地化信息匹配,就命中行。命中之后会打印日志:

printf("  %20s: %s (%d x %d @ %d)\n", name, loc, w, h, y);

从升级后的/cache/recovery/last_log中我们可以看到如下打印:

[ 0.340314] erasing_text: zh-CN (55 x 19 @ 2500)
[ 0.350683] no_command_text: zh-CN (42 x 19 @ 2500)
[ 0.359514] error_text: zh-CN (46 x 19 @ 2500)
[ 0.631050] installing_text: zh-CN (266 x 19 @ 2500)

所以传入的本地化信息字符串是zh-CN,命中的行所在位置是2500像素处。用画图工具打开原始图片,果然,简体中文的起始位置是2500像素处。
所以,要修改这个文字,只要重新制作这个素材文件即可。

制作图片素材

正常的PNG图片肯定解析不出来每一行文字的长、宽和语言信息,那么,这个素材文件是怎么生成的呢?答案是Recovery_l10n。这是一个apk,在设备上运行之后,能生成符合设备配置的多语言的素材文件。这个工具的源码的位置,因Android版本的不同而不同。在比较老的版本中,例如Android6.0,是在development/tools下面,在Android8.0以及之后的9.0中,已经移到了bootable/recovery/tools下面。
在recovery_l10n/res/values-xx的xml文件中修改文字,然后使用mmm指令进行局部编译,将生成RecoveryLocalizer.apk,将这个app安装到设备中,启动之后界面如下图所示:

在这里插入图片描述在下拉菜单中选择要制作的资源文件,点击go,等待一会,就会在/data/data/com.android.recovery_l10n/files下生成text-out.png。

转换文件格式

在上一步中生成的文件并不能直接使用。打开生成的文件和原始的文件的属性,可见两处不同:在这里插入图片描述
因为Recovery只能解析特定格式的png,所以就需要用到linux下的一个工具pngcrush。这个工具的使用命令如下:

pngcrush -c0 input.png output.png

将生成的文件替换掉原来的文件,你会有惊奇的发现。
(未完待续)

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值