Проект требует поддержки воспроизведения видео высокой четкости 8K (кодировка H265). После получения платы я обнаружил, что могу воспроизводить видео высокой четкости 8K с помощью приложения, но не с помощью браузера, даже если установлена последняя версия Chrome для Android. . Основываясь на прошлом опыте разработки ядра браузера, на платформе Android Chromium WebView в конечном итоге вызывает MediaPlayer уровня системной инфраструктуры для воспроизведения. Теоретически, пока уровень системной инфраструктуры может поддерживать воспроизведение высокой четкости 8K, браузер также должен его поддерживать. Реальная ситуация не так, и предварительно скомпилированный WebView для Android 10 не имеет вывода журнала, поэтому вам необходимо загрузить исходный код для компиляции Chromium WebView, чтобы выяснить проблему.
Обновления исходного кода Chromium очень обыденны, а архитектура часто меняется. В отличие от наших проектов, набор кода можно исправлять и использовать более десяти лет. Предыдущий проект был настроен на основе Chromium V53. На этот раз я не хотел использовать последнюю версию Chromium. Я кратко просмотрел последний исходный код и обнаружил, что он сильно отличается от V53. Переносить предыдущую версию было довольно сложно. работа. Первое, что приходит на ум — использовать исходный код V53 напрямую, но его нельзя применить к Android 10. Основная причина в том, что интерфейс WebView API Android 10 претерпел некоторые изменения. Что окончательно заставило меня сдаться, так это то, что из уровня платформы Android 10 был удален класс HardwareCanvas. Знаете, в Android 5.1 в WebView есть важный метод рисования:
public void callDrawGlFunction(Canvas canvas, long nativeDrawGLFunctor) {
if (!(canvas instanceof HardwareCanvas)) {
// Canvas#isHardwareAccelerated() is only true for subclasses of HardwareCanvas.
throw new IllegalArgumentException(canvas.getClass().getName()
+ " is not hardware accelerated");
}
((HardwareCanvas) canvas).callDrawGLFunction2(nativeDrawGLFunctor);
}
V53 использовать нельзя. Далее рассмотрим предварительно скомпилированную версию Chromium Webview в Android 10. Используйте оболочку WebView, чтобы просмотреть номер версии 74.0.3729.183:
Однако здесь есть огромная дыра. После того, как я потратил немало усилий на загрузку кода, компиляцию Chromium WebView и установку его в систему, браузер вылетел при запуске. Проверив системный журнал, я обнаружил следующее сообщение об ошибке:
03-05 00:41:09.457 3299 4011 W WebViewUpdater: creating relro file timed out
03-05 00:41:09.458 12565 12565 E WebViewFactory: Chromium WebView package does not exist
03-05 00:41:09.458 12565 12565 E WebViewFactory: android.webkit.WebViewFactory$MissingWebViewPackageException: Failed to load WebView provider: No WebView installed
03-05 00:41:09.458 12565 12565 E WebViewFactory: at android.webkit.WebViewFactory.getWebViewContextAndSetProvider(WebViewFactory.java:339)
03-05 00:41:09.458 12565 12565 E WebViewFactory: at android.webkit.WebViewFactory.getProviderClass(WebViewFactory.java:402)
03-05 00:41:09.458 12565 12565 E WebViewFactory: at android.webkit.WebViewFactory.getProvider(WebViewFactory.java:252)
03-05 00:41:09.458 12565 12565 E WebViewFactory: at android.webkit.WebView.getFactory(WebView.java:2551)
03-05 00:41:09.458 12565 12565 E WebViewFactory: at android.webkit.WebView.setWebContentsDebuggingEnabled(WebView.java:1974)
03-05 00:41:09.458 12565 12565 E WebViewFactory: at org.chromium.webview_shell.WebViewBrowserActivity.onCreate(WebViewBrowserActivity.java:230)
03-05 00:41:09.458 12565 12565 E WebViewFactory: at android.app.Activity.performCreate(Activity.java:7802)
03-05 00:41:09.458 12565 12565 E WebViewFactory: at android.app.Activity.performCreate(Activity.java:7791)
03-05 00:41:09.458 12565 12565 E WebViewFactory: at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1306)
03-05 00:41:09.458 12565 12565 E WebViewFactory: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
03-05 00:41:09.458 12565 12565 E WebViewFactory: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
03-05 00:41:09.458 12565 12565 E WebViewFactory: at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
03-05 00:41:09.458 12565 12565 E WebViewFactory: at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
03-05 00:41:09.458 12565 12565 E WebViewFactory: at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
03-05 00:41:09.458 12565 12565 E WebViewFactory: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
03-05 00:41:09.458 12565 12565 E WebViewFactory: at android.os.Handler.dispatchMessage(Handler.java:107)
03-05 00:41:09.458 12565 12565 E WebViewFactory: at android.os.Looper.loop(Looper.java:214)
03-05 00:41:09.458 12565 12565 E WebViewFactory: at android.app.ActivityThread.main(ActivityThread.java:7368)
03-05 00:41:09.458 12565 12565 E WebViewFactory: at java.lang.reflect.Method.invoke(Native Method)
03-05 00:41:09.458 12565 12565 E WebViewFactory: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
03-05 00:41:09.458 12565 12565 E WebViewFactory: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
03-05 00:41:09.459 12565 12565 D AndroidRuntime: Shutting down VM
После проверки кода уровня платформы квалифицированный поставщик WebView сначала должен иметь номер версии targetSdk больше или равный 29, а также проверить файл build/config/android/sdk.gni исходного кода chromium v74:
# The default SDK release used by public builds. Value may differ in
# internal builds.
default_android_sdk_release = "p"
# SDK releases against which public builds are supported.
public_sdk_releases = [ "p" ]
Android 10 имеет кодовое название Q, что означает, что эта версия Chromium WebView на самом деле поддерживает только Android 9. Я не знаю, какую магию использовал Google. Возможно, в процессе разработки Android 10 для сборки использовался внутренний SDK.
В настоящее время я все еще не хочу использовать последнюю версию, поэтому просто используйте самую раннюю версию, которая официально поддерживает Android Q. Метод состоит в том, чтобы проверить запись модификации этого sdk.gni и посмотреть, какой коммит был изменен с «p» на «q». Поскольку в коде очень много ветвей, вы должны проверить git-коммиты всех ветвей:
$ git log -p --all -G 'sdk' sdk.gni
Обнаружено, что идентификатор коммита — c2481863282a401926e0ee479334c68ec362d302. Далее проверьте, какие ветки содержат этот коммит:
$ git branch -a --contains c2481863282a401926e0ee479334c68ec362d302
remotes/branch-heads/3967
remotes/branch-heads/3968
remotes/branch-heads/3969
remotes/branch-heads/3970
remotes/branch-heads/3971
remotes/branch-heads/3972
remotes/branch-heads/3973
remotes/branch-heads/3974
remotes/branch-heads/3975
remotes/branch-heads/3976
remotes/branch-heads/3977
remotes/branch-heads/3978
remotes/branch-heads/3979
remotes/branch-heads/3980
remotes/branch-heads/3981
remotes/branch-heads/3982
remotes/branch-heads/3983
remotes/branch-heads/3984
remotes/branch-heads/3985
remotes/branch-heads/3986
remotes/branch-heads/3987
remotes/branch-heads/3987_100
remotes/branch-heads/3987_137
remotes/branch-heads/3987_158
remotes/branch-heads/3987_87
remotes/branch-heads/3988
remotes/branch-heads/3989
remotes/branch-heads/3990
remotes/branch-heads/3991
remotes/branch-heads/3992
remotes/branch-heads/3993
remotes/branch-heads/3994
remotes/branch-heads/3995
remotes/branch-heads/3996
remotes/branch-heads/3997
remotes/branch-heads/3998
remotes/branch-heads/3999
remotes/branch-heads/4000
remotes/branch-heads/4001
remotes/branch-heads/4002
remotes/branch-heads/4003
remotes/branch-heads/4004
remotes/branch-heads/4005
remotes/branch-heads/4006
remotes/branch-heads/4007
remotes/branch-heads/4008
remotes/branch-heads/4009
remotes/branch-heads/4010
remotes/branch-heads/4011
remotes/branch-heads/4012
Существует множество веток, содержащих эту публикацию. Чем больше число, тем новее код ветки, поэтому просто найдите стабильную версию в середине. Посетите следующую ссылку:
https://chromiumdash.appspot.com/releases?platform=Android
Здесь собраны все выпущенные версии. В итоге я выбрал. V80.0.3987.165 . пробираться через Яма для загрузки кода、компилироватьяма、Монтажная яманазад,Наконец успешно пробежал:
По известным причинам исходный код Chromium невозможно загрузить напрямую. Для его загрузки я использовал прокси. Однако при загрузке часто возникает следующая ошибка:
remote: Counting objects: 867615, done
remote: Finding sources: 100% (10514569/10514569)
error: RPC failed; curl 56 GnuTLS recv error (-9): Error decoding the received TLS packet.
fatal: the remote end hung up unexpectedly
fatal: early EOF
fatal: index-pack failed
В Git нет механизма возобновления точки останова. Если загрузка не удалась, ее нужно перезапустить. При встрече со сверхбольшой библиотекой, такой как Chromium, загрузка прерывается, когда она достигает размера более десяти гигабайт. Я искал много методов в Интернете, но не помогло. Затем я нашел решение в сообщении:
git config --global http.postBuffer 5242880000
git config --global https.postBuffer 5242880000
sudo ifconfig eth0 mtu 9000
В Интернете обычно рекомендуется устанавливать для http.postBuffer относительно большое значение. Для одной библиотеки git, такой как Chromium, размер буфера превышает 30 ГБ, и, наконец, ошибок больше нет. Также есть инструкции по установке размера MTU равным 14000, но его невозможно установить в Ubuntu. Максимальное значение, которое я пробовал, было 9000.
После успешного клонирования исходного кода при выполнении команды gclient runhooks возникает следующая ошибка:
NOTICE: You have PROXY values set in your environment, but gsutilin depot_tools does not (yet) obey them.
Also, --no_auth prevents the normal BOTO_CONFIG environmentvariable from being used.
To use a proxy in this situation, please supply those settingsin a .boto file pointed to by the NO_AUTH_BOTO_CONFIG environmentvariable.
Это причина использования прокси. Решение очень простое. Создайте текстовый файл (например, $HOME/.boto) со следующим содержимым.
[boto]
proxy = IP-адрес прокси
proxy_port=порт прокси
Затем установите переменную среды NO_AUTH_BOTO_CONFIG, чтобы она указывала на этот файл:
export NO_AUTH_BOTO_CONFIG=$HOME/.boto
На этом этапе проблема загрузки исходного кода и загрузки двоичных файлов окончательно решена.
Во время компиляции кода возникает следующая ошибка:
FAILED: gen/build/android/buildhooks/build_hooks_android_java.javac.jar gen/build/android/buildhooks/build_hooks_android_java.javac.jar.info
python ../../build/android/gyp/javac.py --depfile=gen/build/android/buildhooks/build_hooks_android_java__compile_java.d --generated-dir=gen/build/android/buildhooks/build_hooks_android_java/generated_java --jar-path=gen/build/android/buildhooks/build_hooks_android_java.javac.jar --java-srcjars=\[\] --java-version=1.8 --full-classpath=@FileArg\(gen/build/android/buildhooks/build_hooks_android_java.build_config:deps_info:javac_full_classpath\) --interface-classpath=@FileArg\(gen/build/android/buildhooks/build_hooks_android_java.build_config:deps_info:javac_full_interface_classpath\) --processorpath=@FileArg\(gen/build/android/buildhooks/build_hooks_android_java.build_config:javac:processor_classpath\) --processors=@FileArg\(gen/build/android/buildhooks/build_hooks_android_java.build_config:javac:processor_classes\) --java-srcjars=@FileArg\(gen/build/android/buildhooks/build_hooks_android_java.build_config:deps_info:owned_resource_srcjars\) --bootclasspath=@FileArg\(gen/build/android/buildhooks/build_hooks_android_java.build_config:android:sdk_interface_jars\) --chromium-code=1 --errorprone-path bin/errorprone @gen/build/android/buildhooks/build_hooks_android_java.sources
Traceback (most recent call last):
File "../../build/android/gyp/javac.py", line 595, in <module>
sys.exit(main(sys.argv[1:]))
File "../../build/android/gyp/javac.py", line 590, in main
add_pydeps=False)
File "/data/chromium/chromium_v74.0.3729.183/src/build/android/gyp/util/build_utils.py", line 653, in CallAndWriteDepfileIfStale
pass_changes=True)
File "/data/chromium/chromium_v74.0.3729.183/src/build/android/gyp/util/md5_check.py", line 87, in CallAndRecordIfStale
function(*args)
File "/data/chromium/chromium_v74.0.3729.183/src/build/android/gyp/util/build_utils.py", line 638, in on_stale_md5
function(*args)
File "../../build/android/gyp/javac.py", line 584, in <lambda>
lambda: _OnStaleMd5(options, javac_cmd, java_files, classpath),
File "../../build/android/gyp/javac.py", line 350, in _OnStaleMd5
stderr_filter=ProcessJavacOutput)
File "/data/chromium/chromium_v74.0.3729.183/src/build/android/gyp/util/build_utils.py", line 227, in CheckOutput
raise CalledProcessError(cwd, args, stdout + stderr)
util.build_utils.CalledProcessError: Command failed: ( cd /data/chromium/chromium_v74.0.3729.183/src/out/Default; bin/errorprone -g -encoding UTF-8 -sourcepath : -XepDisableAllChecks -source 1.8 -target 1.8 -Xlint:unchecked -Werror -bootclasspath lib.java/third_party/android_tools/android.interface.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/rt.jar -d /tmp/tmpzNZrEr/classes @/tmp/tmpzNZrEr/files_list.txt )
-Xbootclasspath/p is no longer a supported option.
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.
Причина в том, что Ubuntu 20.04 использует JDK версии 11, но для этой версии компиляции Chromium требуется JDK 8. Решение состоит в том, чтобы переключить JDK на JDK:
$ java --version
openjdk 11.0.18 2023-01-17
OpenJDK Runtime Environment (build 11.0.18+10-post-Ubuntu-0ubuntu120.04.1)
OpenJDK 64-Bit Server VM (build 11.0.18+10-post-Ubuntu-0ubuntu120.04.1, mixed mode, sharing)
$ sudo update-alternatives --config java
[sudo] password for alex:
There are 2 choices for the alternative java (providing /usr/bin/java).
Selection Path Priority Status
------------------------------------------------------------
* 0 /usr/lib/jvm/java-11-openjdk-amd64/bin/java 1111 auto mode
1 /usr/lib/jvm/java-11-openjdk-amd64/bin/java 1111 manual mode
2 /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java 1081 manual mode
Press <enter> to keep the current choice[*], or type selection number: 2
update-alternatives: using /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java to provide /usr/bin/java (java) in manual mode
$ java -version
openjdk version "1.8.0_362"
OpenJDK Runtime Environment (build 1.8.0_362-8u362-ga-0ubuntu1~20.04.1-b09)
OpenJDK 64-Bit Server VM (build 25.362-b09, mixed mode)
После переключения JDK system_webview_apk был успешно скомпилирован.
После компиляции system_webview_apk и его установки возникает следующая ошибка:
Failure [INSTALL_FAILED_UPDATE_INCOMPATIBLE: Package com.android.webview signatures do not match previously installed version; ignoring!]
- Performing Streamed Install
Это вызвано несоответствием сертификата, используемого для компиляции Chromium, и сертификата платформы Android 10. Способ решения этой проблемы — сделать сертификаты с обеих сторон одинаковыми.
Первый шаг — проверить информацию подписи weview.apk в Android 10. Используйте инструмент сжатия, чтобы распаковать файл META-INF/WEBVIEW-.RSA в APK, а затем используйте следующую команду для просмотра информации о подписи:
$ keytool -printcert -file META-INF/WEBVIEW-.RSA
Второй шаг — определить сертификат, используемый Android 10. Обычно используется сертификат в папке build/target/product/security/. Некоторые продукты также используют специальные сертификаты, которые обычно размещаются в каталоге продукта под устройством. А что, если ты уверен? Проверьте информацию о подписи сертификата, она должна совпадать.
openssl x509 -in testkey.x509.pem -noout -fingerprint
Третий шаг — импорт хранилища ключей. Chromium использует формат хранилища ключей, который широко используется в Java, поэтому сертификат в Android 10 необходимо импортировать.
# Формат закрытого ключа pkcs8 изменять PEM
$ openssl pkcs8 -inform DER -nocrypt -in $ANDROID_SOURCE/build/target/product/security/testkey.pk8 -out testkey.pem
# Сертификат от PEM изменять pkcs12
$ openssl pkcs12 -export -in $ANDROID_SOURC/build/target/product/security/testkey.x509.pem -inkey testkey.pem -out testkey.p12 -name "android_testkey"
Enter Export Password: (Введите пароль android, по умолчанию — android, если вы делаете свой ключ, введите соответствующий пароль)
Verifying - Enter Export Password: (введите пароль андроид)
# генерировать keystore
$ keytool -importkeystore -deststorepass android -destkeypass android -srckeystore testkey.p12 -srcstoretype pkcs12 -srcstorepass android -destkeystore AOSP.keystore -alias android_testkey
Четвертый шаг — изменить gn args, использовать собственное хранилище ключей, изменить файл out/Default/args.gn и добавить следующие строки:
# гипотеза AOSP.keystore Файл находится по адресу chromium src в каталоге
android_keystore_path = "//AOSP.keystore"
android_keystore_name = "android_testkey"
android_keystore_password = "android"
Пятый шаг — пересобрать system_webview_apk.
autoninja -C out/Default system_webview_apk
Повторная установка может пройти успешно.
Можно ожидать, что и в будущем будут встречаться подводные камни. Нет другого выхода, кроме как засыпать ямы при встрече с ними. Разве это не должностная обязанность программистов?