lineageos 21/aosp14环境搭建小米,nubia手机差异补充

Raspberry Pi5安装LineageOS21 android14系统到SSD硬盘 使用有线网络连接后,不能通过主机名访问内部系统,与DNS有关,目前解决方案,可修改/system/etc/hosts文件,操作复杂。安装完成后,系统还是会有些问题,比如存储空间默认只使用到了8GB,没有GooglePlay等,需要进行设置。返回刷机界面,点击install,选择lineage-21.0-rpi-magisk-v25.2.zip包。先点击lineage-21.0-rpi-resize.zip,然后拖动安装,安装完成后。拖动安装,安装完成后,点击wipe dalvik,再次拖动安装。 阅读详情
AI摘要

本文讲述了从Android14的AOSP更新到LineageOS时遇到的问题,包括GitHubfetch失败,以及如何通过覆盖旧版本的roomservice.py文件和处理webview.apk错误来解决。作者提供了详细步骤和解决方案链接供读者参考。,

背景

目前各个厂商的手机已经开始慢慢变成aosp14即android 14进行发货了,在2024将全部变成是android 14的天下。马哥这边也是一直密切关注着lineageos这边是否有及时升级到最新的android 14,今天去官网一看已经确实升级了,马哥这边也第一时间进行环境搭建编译,但是期间也发现了有一些差异相比原来的版本,这里就需要进行一些记录补充方便各位学员们参考,不至于无法搭建成功,有马哥在前面给大家采坑搭建就可以节省很多时间。
这里只讲解差异部分,详细参考如下链接:
https://blog.youkuaiyun.com/learnframework/article/details/128438325

相关差异分享:

1 breakfast nx563j

直接报错无法从GitHub进行fetch
Failed to fetch data from GitHub
出现该报错可以去看相关源码:
vendor/lineage/build/tools/roomservice.py

githubreq = urllib.request.Request("https://raw.githubusercontent.com/LineageOS/mirror/main/default.xml")

其实就是这个路径无法网络访问,所以导致没办法fetch,归根到底还是我们网络问题导致,那么如何有效解决呢?

这里我记得aosp13时候lineage是不会有问题的,查看老版本的这个文件,发现其代码如下:

githubreq = urllib.request.Request("https://api.github.com/search/repositories?q=%s+user:LineageOS+in:name+fork:true" % device)

访问的地址还是有比较大差别,那么这里尝试用老版本的vendor/lineage/build/tools/roomservice.py
直接覆盖方式
cp ~/nx563j_xiaomi/vendor/lineage/build/tools/roomservice.py vendor/lineage/build/tools/roomservice.py

没有的就直接拷贝这里吧:
vendor/lineage/build/tools/roomservice.py

#!/usr/bin/env python
# Copyright (C) 2012-2013, The CyanogenMod Project
#           (C) 2017-2018,2020-2021, The LineageOS Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from __future__ import print_function

import base64
import json
import netrc
import os
import re
import sys
try:
  # For python3
  import urllib.error
  import urllib.parse
  import urllib.request
except ImportError:
  # For python2
  import imp
  import urllib2
  import urlparse
  urllib = imp.new_module('urllib')
  urllib.error = urllib2
  urllib.parse = urlparse
  urllib.request = urllib2

from xml.etree import ElementTree

product = sys.argv[1]

if len(sys.argv) > 2:
    depsonly = sys.argv[2]
else:
    depsonly = None

try:
    device = product[product.index("_") + 1:]
except:
    device = product

if not depsonly:
    print("Device %s not found. Attempting to retrieve device repository from LineageOS Github (http://github.com/LineageOS)." % device)

repositories = []

try:
    authtuple = netrc.netrc().authenticators("api.github.com")

    if authtuple:
        auth_string = ('%s:%s' % (authtuple[0], authtuple[2])).encode()
        githubauth = base64.encodestring(auth_string).decode().replace('\n', '')
    else:
        githubauth = None
except:
    githubauth = None

def add_auth(githubreq):
    if githubauth:
        githubreq.add_header("Authorization","Basic %s" % githubauth)

if not depsonly:
    githubreq = urllib.request.Request("https://api.github.com/search/repositories?q=%s+user:LineageOS+in:name+fork:true" % device)
    add_auth(githubreq)
    try:
        result = json.loads(urllib.request.urlopen(githubreq).read().decode())
    except urllib.error.URLError:
        print("Failed to search GitHub")
        sys.exit(1)
    except ValueError:
        print("Failed to parse return data from GitHub")
        sys.exit(1)
    for res in result.get('items', []):
        repositories.append(res)

local_manifests = r'.repo/local_manifests'
if not os.path.exists(local_manifests): os.makedirs(local_manifests)

def exists_in_tree(lm, path):
    for child in lm.getchildren():
        if child.attrib['path'] == path:
            return True
    return False

# in-place prettyprint formatter
def indent(elem, level=0):
    i = "\n" + level*"  "
    if len(elem):
        if not elem.text or not elem.text.strip():
            elem.text = i + "  "
        if not elem.tail or not elem.tail.strip():
            elem.tail = i
        for elem in elem:
            indent(elem, level+1)
        if not elem.tail or not elem.tail.strip():
            elem.tail = i
    else:
        if level and (not elem.tail or not elem.tail.strip()):
            elem.tail = i

def get_manifest_path():
    '''Find the current manifest path
    In old versions of repo this is at .repo/manifest.xml
    In new versions, .repo/manifest.xml includes an include
    to some arbitrary file in .repo/manifests'''

    m = ElementTree.parse(".repo/manifest.xml")
    try:
        m.findall('default')[0]
        return '.repo/manifest.xml'
    except IndexError:
        return ".repo/manifests/{}".format(m.find("include").get("name"))

def get_default_revision():
    m = ElementTree.parse(get_manifest_path())
    d = m.findall('default')[0]
    r = d.get('revision')
    return r.replace('refs/heads/', '').replace('refs/tags/', '')

def get_from_manifest(devicename):
    try:
        lm = ElementTree.parse(".repo/local_manifests/roomservice.xml")
        lm = lm.getroot()
    except:
        lm = ElementTree.Element("manifest")

    for localpath in lm.findall("project"):
        if re.search("android_device_.*_%s$" % device, localpath.get("name")):
            return localpath.get("path")

    return None

def is_in_manifest(projectpath):
    try:
        lm = ElementTree.parse(".repo/local_manifests/roomservice.xml")
        lm = lm.getroot()
    except:
        lm = ElementTree.Element("manifest")

    for localpath in lm.findall("project"):
        if localpath.get("path") == projectpath:
            return True

    # Search in main manifest, too
    try:
        lm = ElementTree.parse(get_manifest_path())
        lm = lm.getroot()
    except:
        lm = ElementTree.Element("manifest")

    for localpath in lm.findall("project"):
        if localpath.get("path") == projectpath:
            return True

    # ... and don't forget the lineage snippet
    try:
        lm = ElementTree.parse(".repo/manifests/snippets/lineage.xml")
        lm = lm.getroot()
    except:
        lm = ElementTree.Element("manifest")

    for localpath in lm.findall("project"):
        if localpath.get("path") == projectpath:
            return True

    return False

def add_to_manifest(repositories):
    try:
        lm = ElementTree.parse(".repo/local_manifests/roomservice.xml")
        lm = lm.getroot()
    except:
        lm = ElementTree.Element("manifest")

    for repository in repositories:
        repo_name = repository['repository']
        repo_target = repository['target_path']
        repo_revision = repository['branch']
        print('Checking if %s is fetched from %s' % (repo_target, repo_name))
        if is_in_manifest(repo_target):
            print('LineageOS/%s already fetched to %s' % (repo_name, repo_target))
            continue

        print('Adding dependency: LineageOS/%s -> %s' % (repo_name, repo_target))
        project = ElementTree.Element("project", attrib = {
            "path": repo_target,
            "remote": "github",
            "name": "LineageOS/%s" % repo_name,
            "revision": repo_revision })
        lm.append(project)

    indent(lm, 0)
    raw_xml = ElementTree.tostring(lm).decode()
    raw_xml = '<?xml version="1.0" encoding="UTF-8"?>\n' + raw_xml

    f = open('.repo/local_manifests/roomservice.xml', 'w')
    f.write(raw_xml)
    f.close()

def fetch_dependencies(repo_path):
    print('Looking for dependencies in %s' % repo_path)
    dependencies_path = repo_path + '/lineage.dependencies'
    syncable_repos = []
    verify_repos = []

    if os.path.exists(dependencies_path):
        dependencies_file = open(dependencies_path, 'r')
        dependencies = json.loads(dependencies_file.read())
        fetch_list = []

        for dependency in dependencies:
            if not is_in_manifest(dependency['target_path']):
                fetch_list.append(dependency)
                syncable_repos.append(dependency['target_path'])
                if 'branch' not in dependency:
                    dependency['branch'] = get_default_or_fallback_revision(dependency['repository'])
            verify_repos.append(dependency['target_path'])

            if not os.path.isdir(dependency['target_path']):
                syncable_repos.append(dependency['target_path'])

        dependencies_file.close()

        if len(fetch_list) > 0:
            print('Adding dependencies to manifest')
            add_to_manifest(fetch_list)
    else:
        print('%s has no additional dependencies.' % repo_path)

    if len(syncable_repos) > 0:
        print('Syncing dependencies')
        os.system('repo sync --force-sync %s' % ' '.join(syncable_repos))

    for deprepo in verify_repos:
        fetch_dependencies(deprepo)

def has_branch(branches, revision):
    return revision in [branch['name'] for branch in branches]

def get_default_revision_no_minor():
    return get_default_revision().rsplit('.', 1)[0]

def get_default_or_fallback_revision(repo_name):
    default_revision = get_default_revision()
    print("Default revision: %s" % default_revision)
    print("Checking branch info")

    githubreq = urllib.request.Request("https://api.github.com/repos/LineageOS/" + repo_name + "/branches")
    add_auth(githubreq)
    result = json.loads(urllib.request.urlopen(githubreq).read().decode())
    if has_branch(result, default_revision):
        return default_revision

    fallbacks = [ get_default_revision_no_minor() ]
    if os.getenv('ROOMSERVICE_BRANCHES'):
        fallbacks += list(filter(bool, os.getenv('ROOMSERVICE_BRANCHES').split(' ')))

    for fallback in fallbacks:
        if has_branch(result, fallback):
            print("Using fallback branch: %s" % fallback)
            return fallback

    print("Default revision %s not found in %s. Bailing." % (default_revision, repo_name))
    print("Branches found:")
    for branch in [branch['name'] for branch in result]:
        print(branch)
    print("Use the ROOMSERVICE_BRANCHES environment variable to specify a list of fallback branches.")
    sys.exit()

if depsonly:
    repo_path = get_from_manifest(device)
    if repo_path:
        fetch_dependencies(repo_path)
    else:
        print("Trying dependencies-only mode on a non-existing device tree?")

    sys.exit()

else:
    for repository in repositories:
        repo_name = repository['name']
        if re.match(r"^android_device_[^_]*_" + device + "$", repo_name):
            print("Found repository: %s" % repository['name'])
            
            manufacturer = repo_name.replace("android_device_", "").replace("_" + device, "")
            repo_path = "device/%s/%s" % (manufacturer, device)
            revision = get_default_or_fallback_revision(repo_name)

            device_repository = {'repository':repo_name,'target_path':repo_path,'branch':revision}
            add_to_manifest([device_repository])

            print("Syncing repository to retrieve project.")
            os.system('repo sync --force-sync %s' % repo_path)
            print("Repository synced!")

            fetch_dependencies(repo_path)
            print("Done")
            sys.exit()

print("Repository for %s not found in the LineageOS Github repository list. If this is in error, you may need to manually add it to your local_manifests/roomservice.xml." % device)

2 ./extract-files.sh 有少量报错

这个解决方法就是把手机刷成lineage的最新版本
版本下载地址:
https://download.lineageos.org/devices/nx563j/builds

刷成最新版本后再进行./extract-files.sh的执行就没有错误

3 编译过程中webview.apk有报错

解决方法:
1、可以从刷机手机上寻找webview.apk,然后拷贝到报错apk的路径
2、从上一套编译通过的代码吧webview.apk拷贝
如下处理:

 cp ~/nx563j_xiaomi/external/chromium-webview/prebuilt/arm64/webview.apk external/chromium-webview/prebuilt/arm64/webview.apk

最后成功能如下:
在这里插入图片描述
在这里插入图片描述

更多framework干货请关注“千里马学框架”

避坑指南:Raspberry Pi5安装LineageOS21常见问题全解(SSD启动/存储扩容/Play商店报错) 本文详细解析了在Raspberry Pi5上安装LineageOS 21的完整流程,重点解决了SSD启动、存储扩容和Play商店报错等常见问题。通过实测数据对比不同存储介质的性能差异,并提供NVMe配置、Magisk集成及Google服务认证的实用解决方案,帮助用户高效完成Android 14系统的部署与优化。 阅读详情

相关推荐

如何编译lineageOS并刷机

高版本会有更多的镜像,作者也没办法去具体判断需要挂在哪些,但是作者能够给到一个技巧,就是如果这里你挂载的不够,那么在 编译 部分会出现文件找不到的问题,如果你确认了报错的文件在项目中没有,那说明这里少挂载了。运行这个命令的时候也会出现错误,原因是./extract-files.sh脚本中记录的文件路径有问题,需要自己修改,按照错误提示的文件,然后去找到文件的正确路径修改好就可以了,我是用find命令找的错误路径的文件,改好之后运行上面的内容就能够成功提取到了。作者的核心数量是10,所以指定20线程。

2503_90751789的博客 1775

一加七Pro刷Lineageos21(kernelsu+MicroG)

前几天我已经刷了Lineageos21(一加七Pro刷lineageos21(kernelsu+gapps)),但是体验下来有两个很严重的bug:无法接打电话,没有声音。收短信倒是很正常,但电话打进来只会显示号码,不会显示接听界面(对方那边显示正在通话中,也就是挂断了),拨打电话会显示已结束。测试发现是刷了kernelsu内核导致的,如果只是刷gapps使用正常,所以想自己编译一个kernelsu试试。

Qwertyuiop2016的博客 8286

编译LineageOS

参考: https://wiki.lineageos.org/devices/lemonadep/install https://wiki.lineageos.org/devices/lemonadep/install 写在前面 做Android的伙伴往往都需要编译Android的源码,之前使用过编译过AOSP源码,搭配 Hikey 系列开发板 和 Pixel系列手机使用,编译AOSP源码和刷镜像的过程太过繁杂,经常会出现各处error,而且新版本的编译方式变化较大。 最近接触LIneageOS,编译烧录都

qq_36059308的博客 4283

树莓派4B安装安卓系统LineageOS 21(Android14)

1:系统下载2:下载好镜像后,准备写入SD卡,我这边使用的是 balenaetcher3:插入树莓派,按照指示一步一步进行配置,可以配置时区,语言。注意点1》:想返回的时候按F22》:进入系统,多次点击系统版本后进入开发模式;3》:选择开发者模式。打开USB调试,ADB调试(具体ADB使用请查看其他教程,使用它的目的就相当于通过远程访问,修改树莓派配置,一般可以设置时区(因为lineage的默认一般不符合国内,会导致链接网络受限))

u011788214的专栏 8934

LineageOs-21.0系统编译问题

ok,以上就是我这期的Bug修复内容啦,如果还想查找更多解决方案,你可以看看我专门收集Bug及提供解决方案的专栏「Bug调优」,都是实战中碰到的Bug,希望对你有所帮助。到此,咱们下期拜拜。码字不易,如果这篇文章对你有所帮助,帮忙给bug菌来个,您的支持就是我坚持写作分享知识点传播技术的最大动力。「猿圈奇妙屋」;以第一手学习bug菌的首发干货,不仅能学习更多技术硬货,还可白嫖最新BAT大厂面试真题、4000G Pdf技术书籍、万份简历/PPT模板、技术文章Markdown文档等海量资料,你想要的我都有。

**My Coding Family** 1480

玩转Android10源码开发定制(16)LineageOS中编译user模式的系统

玩转Android10源码开发定制(16)LineageOS中编译user模式的系统 一、安卓系统编译选项简介 android编译的时候可以选择编译选项 eng、user 和 userdebug。 1.eng编译选项 (1). 系统编译的时候安装标签LOCAL_MODULE_TAGS为 user、debug、eng 的模块 (2). 设定属性 ro.secure=0,关闭安全检查功能 (3). 设定属性 ro.debuggable=1,启用应用调试功能 (4). 默认打开 adb 功能,adb拥有root权

xiaomaNo01的专栏 1641

系统签名客制化——基于LineageOS21

由于AOSP中自带了一个公开的秘钥,LineageOS没有针对签名做任何定制(即便是做了定制我们也需要重新生成,因为这个签名必须随源码发布才能使用),所以我们利用LineageOS编译出来的系统固件是默认使用公版签名的,一些APP厂商为了防止一些不法分子使用自定义的系统来做灰黑产业定制了一些反制策略,其中一项就有检测系统签名是否为公版签名,当我们使用这台机器来登录一些网络账号可能会导致被封号。通过这些不同类型的系统签名,Android 能够为系统中的不同组件和服务提供适当的权限和安全性。

周真真 1898

PX4无人机PID调参实战:从零到稳定飞行的关键步骤

本文详细介绍了PX4无人机PID调参的实战步骤,从理解双环控制结构到实战调参三部曲,帮助飞手解决飞行抖动、电机发热等常见问题。通过分析飞行日志、调整速率环P值、引入积分I和微调角度环与微分D,实现从零到稳定飞行的关键跨越,是无人机飞控调试的必修课。

weixin_29269441的博客 527

编译LineageOS 21 user release版本

Android版本:14编译环境:VMware17 + Ubuntu24.04处理器:AMD 7600X 6核心12线程RAM内存:32GB + SWAP:30GB。

qq809081128的博客 1285

SPSS中的数据分析—信度效度检验【1】

前一段时间跟大家分享了好几篇关于EXCEL方面的数据分析知识,不知道大家都掌握得怎么样了。今天咱们换个口味,给大家讲一下关于SPSS中的数据分析——信度效度检验。 现阶段正处在毕业季阶段,很多同学可能都正在忙着去弄自己的论文和答辩(不知道大家在翟天临上热搜这个事情上有没有做出过一定贡献),很多时候我们在写论文答辩甚至于其他课题研究的时候都会选择用问卷这种形式来收集数据。最后我们只需要针对问卷所取...

小白数据营的博客 6万+

Xtract or Ucfyber的最条理的整理入门级教程

XTRACT可以对任意截面进行全过程截面分析。工程中常用来分析各种截面(如异形柱、组合截面等)的非线性特征点及承载力校核。 xtract主要思路也是根据各种材料本构关系,基于平截面假定,用fiber划分截面进行全过程非线性分析。......

→★佐佑思维★← 8399

lineageOS刷机注意事项汇总

大版本更新是指从Lineage x.0更新至Lineage x+1.0,lineage官方对不同手机型号的适配是不同步的,例如一加5去年就已经有lineage20.0版本(对应android13)了,而红米K40到最近才放出来,我的红米K40从lineage19.1(对应android12)到20.0的升级就属于大版本更新,大版本更新不能通过OTA进行,需要自行下载系统包然后手动刷入。2 进入 Magisk Manager,找到位于主界面的“卸载 Magisk”,然后点击“还原原厂镜像”

qq_27753389的博客 7339

Simulink+Simscape多体仿真:六自由度Stewart平台动力学建模全流程

本文详细介绍了使用Simulink和Simscape Multibody进行六自由度Stewart平台动力学建模的全流程,涵盖从CAD模型导入、运动学逆解计算到实时控制系统的设计。通过MATLAB/Simulink与Simscape的协同工作,实现高保真度的并联机器人仿真,适用于飞行模拟器、精密加工等高精度领域。

r2s3t4的博客 486

LineageOS编译

目录准备下载并解压SDK安装adb和fastboot安装Repo和python安装依赖设置 git清华源源代码镜像过程摘录异常处理下载机型配置拉取vendor开启缓存开始编译还原代码遇到的错误error: RPC failed; curl 56 GnuTLS recv error (-110): The TLS connection was non-properly terminated.buil...

yusakul的博客 5054

(代码可运行)半导体器件和工艺模拟 使用Silvaco设计构建NMOS并提取各项工艺及器件参数

win10。

qq_20388971的博客 110

模糊控制 (Fuzzy Control) 算法详解及案例分析

模糊控制是一种基于模糊逻辑的控制策略,其核心思想是通过模糊规则和模糊推理实现对复杂系统的控制。模糊控制不依赖于精确的数学模型,而是通过模拟人类的决策过程来处理不确定性和非线性问题。

闲人编程的博客 3657

cm13编译中的local manifest写法

转载注明出处:背景cm13官方支持小米3W,最近就想自己做rom编译,刷到小米3W上,参考网上的编译教程。 ps: CyanogenMod的官网www.cyanogenmod.org已经关闭了,新的官网地址为https://www.lineageos.org/问题同步完cm-13的代码后,执行source build/envsetup.sh breakfast cancro发现报错buildbo

高飞的专栏 3173

孔雀优化算法(POA)详解:从孔雀智能到优化引擎

孔雀优化算法(POA)是一种新型元启发式优化算法,灵感来源于孔雀的社会行为和智能狩猎策略。该算法将孔雀群体分为雄孔雀、雌孔雀和幼孔雀三个阶层,分别对应全局探索、平衡搜索和局部开发三种搜索策略。通过模拟孔雀的求偶展示、自适应接近和Levy飞行等行为,POA实现了探索与开发的动态平衡。算法采用角色分配机制和位置更新方程,结合参数自适应调整,展现出优于传统算法的全局搜索能力和收敛性能。POA已成功应用于多个优化问题,其生物启发机制为解决复杂优化问题提供了新思路。

qq_42212808的博客 135

LineageOS-21 编译大作战!—— 一个萌新的心路历程 ☆

手把手指导您编译LineageOS-21.0

滚滚长江,却只留有过去,不知未来 2513

Open3D 使用RANSAC分割平面【2026最新版】

使用RANSAC从点云中分割平面,用segement_plane函数。博客长期更新,本文最新更新时间为:2026年2月28日。

点云侠的博客 37万+

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

为红米2 redmi 2 (wt88047) 编译Lineage 15.1时遇到供应商文件缺失

在Lineage 官网上下载Lineage OS 15.1 源码后,通过breakfast wt88047切换到设备下,下一步使用brunch wt88047命令开始完全构建时出现文件缺失。 编译Lineage 15.1时遇到供应商vendor文件缺失 ninja: no work to do. [1/2] glob device/*/*/Android.bp ninja: no work to do. Environment variable BUILD_NUMBER was modified (763

時を越える笑顔 1182

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

编译Android14 AOSP记录

编译android14 aosp

吃肉会瘦 3476

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

How to Build LineageOS rom for any android device Easily ! {Full guide}

How to Build LineageOS rom for any android device Easily ! {Full guide}

张同光 (Tongguang Zhang):Hello everyone ! 2176

LineageOS源码下载和编译(Xiaomi Mi 6X,wayne)

路径 /devices/soc/800f000.qcom,spmi/spmi-0/spmi0-00/800f000.qcom,spmi:qcom,pm660@0:qcom,pm660_rtc/rtc 被定义了两次。Device Tree:设备树是一种硬件描述文件,用来告诉操作系统设备的硬件布局,避免内核代码与具体硬件的紧耦合。在 device/xiaomi/sdm660-common/sepolicy/vendor/genfs_contexts 文件中找到并移除重复定义的那一行。

4319
上一篇: SurfaceFlinger实战dump获取单个Layer图像方案及成果展示-千里马学框架
下一篇: 安卓14/aosp14相比安卓13录屏多了MirrorRoot深入剖析解密-千里马android framework实战开发
千里马学框架
博客等级 码龄6年 1万+粉丝 650原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千里马学框架

帮助你了,就请我喝杯咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值