【Android】AGP を 8.3+ にすると AD_SERVICES_CONFIG プロパティが衝突する

バージョンアップ作業。

はい、またエラー出ました。


Error:
	Attribute property#android.adservices.AD_SERVICES_CONFIG@resource value=(@xml/ga_ad_services_config) from [com.google.android.gms:play-services-measurement-api:21.5.1] AndroidManifest.xml:32:13-58
	is also present at [com.google.android.gms:play-services-ads-lite:22.6.0] AndroidManifest.xml:92:13-59 value=(@xml/gma_ad_services_config).
	Suggestion: add 'tools:replace="android:resource"' to <property> element at AndroidManifest.xml to override.

Google Issue Tracker で以下。

From the Android Studio team:
This is a known issue of the AdMob and Google Services libraries
(AGP before 8.3 would have not surfaced the conflicts between the property definitions, which is why you see this during upgrade of AGP)

The solution suggested from the error message is the right one
Until the libraries are fixed: just override the property yourself in your AndroidManifest.xml

Android Studio チームからのコメント:
これは AdMob および Google Services ライブラリに関する既知の問題です。
(AGP 8.3 より前のバージョンでは、プロパティの定義間の競合が表面化しなかったため、AGP をアップグレードした際にこの問題が発生します)

エラーメッセージで提案されている解決策が正しい方法です。
ライブラリが修正されるまでの間は、AndroidManifest.xml 内でプロパティを自分で上書きしてください。


<property
    android:name="android.adservices.AD_SERVICES_CONFIG"
    android:resource="@xml/gma_ad_services_config"
    tools:replace="android:resource" />

DESCRIBE THE ISSUE IN DETAIL: I am not sure where can I report this issue as it seems it is more related to AdMob and Google Services manifest conflict. However this issue appears after updating to Iguana and AGP from 8.2.2 to 8.3 and Gradle 8.2 to 8.4.

この問題の報告先が分からず困っています。問題の原因は、AdMob と Google Services の AndroidManifest.xml における競合に関連しているように見えます。しかし、この問題は Iguana にアップデートし、Android Gradle Plugin (AGP) を 8.2.2 から 8.3 に、また Gradle を 8.2 から 8.4 に更新した後に発生するようになりました。

Status は Assigned のままで、まだ最近でも出ている模様。

[email protected] #50Nov 20, 2024 05:40PM
I upgraded from com.google.android.gms:play-services-ads:22.3.0' to com.google.android.gms:play-services-ads:23.5.0 and this error came.

<application> タグ内に書けばいいのか。

👉 Merge conflict with AndroidManifest in Android Studio Iguana [327696048] - Issue Tracker


ポリシーステータス「アプリは Android 14(API レベル 34) 以降を対象とする必要があります。」が消えない

かなり遅れて、今さらなのですが。

このポリシーステータスのメッセージ。


アプリは Android 14(API レベル 34) 以降を対象とする必要があります。

アプリ自体は、

SDKのターゲットバージョン35にして

公開完了してるにこのメッセージが消えない。

なんでかな。

 

🧑🏻‍💻 すぐには消えない?

Check that all tracks are updated (even paused tracks). If they are then give it a few days for the message to disappear.

すべてのトラックが更新されていることを確認してください(一時停止したトラックも)。もしそうなら、メッセージが消えるまで数日待ってください。

👉 How can I clear this message because now my target API is 34 - Google Play Developer Community

It turned out that I need to wait for 24 hours for the message to disappear. I don't know why it's not instant even though the target api is clearly within the policy requirements. Maybe they check these manually. Anyway it's solved.

メッセージが消えるまで24時間待つ必要があることが判明しました。ターゲットAPIが明らかにポリシー要件の範囲内であるにもかかわらず、なぜそれが即時ではないのかわかりません。おそらく彼らはこれらを手動でチェックします。とにかく解決しました。

👉 i still get this warning (App must target Android 14 (API level 34) or higher) even though iupdated - Google Play Developer Community

 

🧑🏻‍💻 結果

大体6時間後に確認すると消えてました!


Android のアーキテクチャで何が Google に「強く推奨」されているか図で理解する

👉 Recommendations for Android architecture  |  Android Developers

分かりやすいドキュメントなのでさらに分かりやすくなるように図にしてみます。

 

🤔 Layered Architecture


UI Layer
  |
Coroutine
  |
DataL Layer
  |
Repository

👉 Layered architecture - Recommendations for Android architecture  |  Android Developers

 

🤔 UI Layer


UI Layer
  UDF
  AAC ViewModel
  Lifecycle
  User Event

👉 UI layer - Recommendations for Android architecture  |  Android Developers

 

🤔 ViewModel


ViewModel
  Depencencies
  Coroutine Flow
  State Holder

👉 ViewModel - Recommendations for Android architecture  |  Android Developers

 

🤔 Lifecycle


Lifecycle
  LifecycleObserver

👉 Lifecycle - Recommendations for Android architecture  |  Android Developers


 

🤔 Handle dependencies


Constructor Injection
Container

👉 Handle dependencies - Recommendations for Android architecture  |  Android Developers

 

🤔 Test


ViewModel
Data Entity (Repository + DataSource)
FakeData
StateFlow

👉 Test - Recommendations for Android architecture  |  Android Developers

 

🤔 まとめ

しれっと、公式リファレンスも分かりやすく更新されていて驚きました。

👉 【Android】アーキテクチャーとして Google が推奨していること #Kotlin - Qiita


【Swift】公証された(またはアーカイブコピー)アプリで VideoPlayer が クラッシュする

公証されたアプリやアーカイブされたアプリで VideoPlayer がクラッシュする。


Crashed Thread:        0  Dispatch queue: com.apple.main-thread

Exception Type:        EXC_CRASH (SIGABRT)
Exception Codes:       0x0000000000000000, 0x0000000000000000

Termination Reason:    Namespace SIGNAL, Code 6 Abort trap: 6

 

🤔 原因

公証されたアプリで AVKit フレームワークが正しくリンクされていないことが原因。

 

🧑🏻‍💻 解決方法

AVKit.framework を手動でリンクする必要がある。

Xcode のアプリターゲットで「Build Phases」に移動し、「Link Binary With Libraries」に AVKit.framework を追加する。

 

🧑🏻‍💻 参考

The answer is to add AVKit.framework manually to Link Binary With Libraries in the app target's Build Phases in Xcode.

👉 video player - SwiftUI macOS VideoPlayer View Only Crashes In Notarized (Distributed) App - Stack Overflow


【Swift】画像 生 Data は UIImage や NSImage で変更されることを知る

例えば、WEB上の下のような

「imgur で削除された」ことを表す PNG 画像 のデータは、

以下のようにして Data を取得できますよね。


let data = try! Data(
  contentsOf: URL(string: "https://i.imgur.com/removed.png")!
)

それを一度、UIKit UIImage に適用した、としても、

それは再び同じ Data 型 として同じものが抽出できるイメージでいました。


👉 UIImage | Apple Developer Documentation
👉 Data | Apple Developer Documentation

しかし、同じものが抽出できません。

適用前と後で抽出したものが違うようです。


let data = try! Data(
  contentsOf: URL(string: "https://i.imgur.com/removed.png")!
)
let uiImage = UIImage(data: data)!
let data2 = uiImage.pngData()!

print(data == data2) // false
print(data, data2)   // 503 bytes 1134 bytes

なんでや、何が違うんや。

 

🤔 Base64Encoding

テキスト化して見てみます。

違いの量は分かります。


let data = try! Data(
  contentsOf: URL(string: "https://i.imgur.com/removed.png")!
)
let uiImage = UIImage(data: data)!
let data2 = uiImage.pngData()!

print(
  data,
  data.base64EncodedString()
)
print(
  data2,
  data2.base64EncodedString()
)

// 503 bytes 
// iVBORw0KGgoAAAANSUhEUgAAAKEAAABRAQMAAACADVTsAAAABlBMVEUiIiL///9ehyAxAAABrElEQVR4Xu3QL2/bQBgG8NdRlrnMNqxu1eVAahCQVAEF03STbsuBSFVZYEBBoJ2RjZ0Hljuy6IZaUlUlpfsKRUmZP4JTNJixkEm7nJu/Mxlot0l7JJOfXj06P/D3xvkBQH/lqoEC7WVvzqM0k/f4+Gat2nt7ppqeCjCbiJX6HmN7vnca4LLc0BljH/yZ0ZejDQXGlA9GmYSthoumVw1wZ6PByxjrpxmeZq0hbMcDXPCHGVB4hHCAkgUKrrNSulawelPRCH37mu4fR1EdZYPwnTA6UZoQfteoMSmPCFVcgYmUmmCuPMKkIAtNFjqS+hWyOo+MzmVsb12NS1aFazThe1Ztr2qYBklWvcPKCKG+TA/MGwjqDcI4n1Pko+1E5KM9TRz75fGB0qWv1Vlq/Bo9Gzqo3oqu7g991G1bVQmp8IQcdeRtEGpyxoVVB5eNLob0qS6xpaJc5+J7Wx+wkwct5SoSn2vCOORKrHZk0lC69tAbm4a2g0grEuknvd9tb61XhqK8hz+d/xG/cft5fD0dvxA7qsLrj+EXWqBugRbeHl6qcbCr4Ba+7Tn88/kJk4CIztd1IrIAAAAASUVORK5CYII=

// 1134 bytes 
// iVBORw0KGgoAAAANSUhEUgAAAKEAAABRCAMAAACNHTadAAAABlBMVEUiIiL///9ehyAxAAAAhGVYSWZNTQAqAAAACAAFARIAAwAAAAEAAQAAARoABQAAAAEAAABKARsABQAAAAEAAABSASgAAwAAAAEAAgAAh2kABAAAAAEAAABaAAAAAAAAAEgAAAABAAAASAAAAAEAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAoaADAAQAAAABAAAAUQAAAACmJMYkAAAACXBIWXMAAAsTAAALEwEAmpwYAAADfklEQVRoBe1Xi3bqMAyD///pa1mS4zTAxh6s200Oi21ZftQtYb1c9toT2BPYE3jlBK5cl+tSdEUWyquAbOVE/azXrQ6vbDJmSgrE9QKLiBxhJME80kAqTSWMZIaMWWu/D8ng7CR7Ql9Y2BMNhR+JuZWkiV2i4pVC6QB/ZKEG+2nyFtIaLT54arK71ce4siQJfVrMHca9SaDXpZ6O6qbxChuXhSbISGeRn24uA7KhVkVZOhK6zI6SeG+Gh4CP9eYSIXtl6AsSoJ7V+Tkk0fFOw3gF2JlpP7JlQ5U67yXSGCmpYR2+y+pQ32Xd2mwj+otYhNuZ8Cu2LDoKHczh+BltfeZP1uDPjGVXfdkE4nm7/8jd9yz93aA2qKlL5FvAw9iHzjnzY+oNLw+tPIVxbvkIA9NHY0psCYKUzhqpPXawiqODRgfzDRioMjIhbFEBeA1e8pvJaGdBskQoscOMJRUWVIqS5DUU6uDMI2E4CbW3WGcV1D1M2RCrvdbSIYuYKgkRq6xQpBtO/9jSG8M1awQABKrRDwcywpHOUoUcokQzPaSjlN2eUQUl+ypGgNKbMDMgfg4c+BtdnBY1/J0nNEWLaapT3IgXa4iWOcBuwZwQOBsn9QU5Rs0x8jIz94R0O/Hww/YN0HeBXvvcE6lIMtNHLlXLjOIlG3pGufvWg0qScntX2tvOGX2COgd+znpnWc3tc7V29J7Ar53AW1+Ut/yPLhyxI96a5aPIZ3yfzTfirVne70Lncf8BqGPT/zj5FNYRS/9w+phHER/kTpshk1G/wE4TlKp4o09cQvyZApUIuEAPyPAPpzRGIrxIzMXdiW2FtKqAjFy2RoJPYaI1J9RY8svRzIaQ6fpr4JLGsQ6cpbzKw6vyQGm5VMYFz/laJFAs1ibRZoJp2E1mWSN27syWiBBYkk2ECmsgtiSbOCSgJ/ZGWSw44b+/WjRII4OsFVFE5iV9eg5ZCg4Qi0WmsmXAhCSPocvuu0EHshKBndaKTLXRSYuCiiWUlWmMbEDrKEiyfRn7DZvb+obUX5CSz/0XJNop9gT2BPYE9gT2BPYE9gT2BPYE/sYEzv0P/O+Ycb5k4V1Mil7c/MKnN0F7SXvtlWVj+d5ZvUUD1BOWHrz6nK1D93neDj3bM3SIhw+3Ervvfj2BP3aX+zOlrjp0Nj1HeLamdj97AnsCewL/+QT+AeEGA83c9VTUAAAAAElFTkSuQmCC

全然違いますね。

「PNGフォーマット」を表す先頭部分は同じなことも分かります。

さらに、

Xcode ウインドウからデスクトップ上や好きな位置に、

コピペで画像ファイルを簡単に作成できるので便利です。


# コピーして
❯ pbpaste | base64 --decode > 503.png

# さらにコピーして
❯ pbpaste | base64 --decode > 1134.png

❯ ls -al
-rw-r--r--@  1 chanzmao  staff    503 Oct 11 10:50 503.png
-rw-r--r--@  1 chanzmao  staff   1134 Oct 11 10:51 1134.png

これで2つの処理のタイミングでの Data を利用した画像ファイルが作成できました。

また、xxd でも16進数を使って似たようなことができそうです。


❯ xxd 503.png | head
00000000: 8950 4e47 0d0a 1a0a 0000 000d 4948 4452  .PNG........IHDR
00000010: 0000 00a1 0000 0051 0103 0000 0080 0d54  .......Q.......T
00000020: ec00 0000 0650 4c54 4522 2222 ffff ff5e  .....PLTE"""...^
00000030: 8720 3100 0001 ac49 4441 5478 5eed d02f  . 1....IDATx^../
00000040: 6fdb 4018 06f0 d751 96b9 cc36 ac6e d5e5  [email protected]..
00000050: 406a 1090 5401 05d3 7493 6ecb 8148 5559  @j..T...t.n..HUY
00000060: 6040 41a0 9d91 8d9d 0796 3bb2 e886 5a52  `@A.......;...ZR
00000070: 5525 a5fb 0a45 4999 3f82 5334 98b1 9049  U%...EI.?.S4...I
00000080: bb9c 9bbf 3319 68b7 497b 2493 9f5e 3d3a  ....3.h.I{$..^=:
00000090: 3ff0 f7c6 f901 407f e5aa 8102 ed65 6fce  [email protected].


❯ xxd original.png > original.hex
❯ xxd -r original.hex > revert.png

👉️ xxdコマンドで画像データを16進数変換してiOSライブラリ内に画像データを内包する

 

🤔 file コマンド

先に作成した2つのファイルを file コマンドで見てみます。


❯ file 503.png 1134.png
503.png:  PNG image data, 161 x 81, 1-bit colormap, non-interlaced
1134.png: PNG image data, 161 x 81, 8-bit colormap, non-interlaced

少し違うことが分かります。


1-bit colormap
8-bit colormap

PNGファイルのプロファイル的な何かでしょうか。

 

🤔 sips コマンド

macOS 標準のコマンドらしいです。

2つの実行結果を diff に入力します。


❯ diff --side-by-side <(sips -g all 503.png) <(sips -g all 1134.png)
~/Desktop/503.png            | ~/Desktop/1134.png
  pixelWidth: 161                pixelWidth: 161
  pixelHeight: 81                pixelHeight: 81
  typeIdentifier: public.png     typeIdentifier: public.png
  format: png                    format: png
  formatOptions: default         formatOptions: default
  dpiWidth: 72.000               dpiWidth: 72.000
  dpiHeight: 72.000              dpiHeight: 72.000
  samplesPerPixel: 3             samplesPerPixel: 3
  bitsPerSample: 1           |   bitsPerSample: 8
  hasAlpha: no                   hasAlpha: no
  space: RGB                     space: RGB

以下の部分が違います。


bitsPerSample: 1	           |	   bitsPerSample: 8

( 現在、記事更新中 ... )