์๋ ํ์ธ์ ์ฌ๋ฌ๋ถ,
Cordova 8+์ ํจ๊ป ์ด ํ๋ฌ๊ทธ์ธ์ ์ฌ์ฉํ๋ ์ฌ๋๋ค์ ๊ฒฝ์ฐ ์๋ฆผ ์์ด์ฝ ๋ณ๊ฒฝ์ด ์๋ํ์ง ์๊ณ Android์์ ์ด์ '์๋ฆผ ์์ด์ฝ์ด ๋น ์ฌ๊ฐํ์ ๋๋ค' ๋ฌธ์ ๊ฐ ๋ฐ์ํ์์ ์ ์ ์์ต๋๋ค. ์ด๊ฒ์ ์๋๋ก์ด๋ ์๋ฆผ ์์ด์ฝ์ด ํฌ๋ช ํ ๋ฐฐ๊ฒฝ์ ๋จ์ํ 1์ ๋ชจ์์ด์ด์ผ ํ๊ณ ์ด๋ฌํ ์์ด์ฝ์ ์ ๊ณตํ์ง ์์ ๊ฒฝ์ฐ ์๋๋ก์ด๋๊ฐ ๋์ ์ ํ๋ฆฌ์ผ์ด์ ์์ด์ฝ์ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ ๋ฐ์ํฉ๋๋ค. ํฌ๋ช ํ ๋ฐฐ๊ฒฝ์ด ์๋ ์์ ํ๊ณ ๋ค์ฑ๋ก์ด ์ฌ๊ฐํ์ผ ๊ฐ๋ฅ์ฑ์ด ํฝ๋๋ค.
์ด๊ฒ์ ์๋ก์ด Ionic 3 ํ๋ก์ ํธ๋ฅผ ์ค์ ํ๊ณ ์ด ํ๋ฌ๊ทธ์ธ์ ์ฌ์ฉํ๋ ค๊ณ ํ ๋ ๋งค์ฐ ์ฑ๊ฐ์ญ๋๋ค.
Readme here atm์ ์์ด์ฝ์ ์ฌ๋ฐ๋ฅด๊ฒ ๋ณ๊ฒฝํ๋ ๊ณผ์ ์ ์ค๋ช ํ์ง ์์ต๋๋ค. ๋ค์์ ์์ด์ฝ์ ๋ณ๊ฒฝํ๊ธฐ ์ํด ์ํํด์ผ ํ๋ ๋จ๊ณ์ ๋๋ค.
0) ์ธํฐ๋ท ๊ฒ์์ ๋ฉ์ถ๊ณ ๋จธ๋ฆฌ์นด๋ฝ์ ๋ฝ์ผ์ญ์์ค. ์ด ์ง์นจ์ ๋จ๊ณ๋ณ๋ก ์ํํ๋ฉด ์๋ํ๊ฒ ๋ ๊ฒ์
๋๋ค. ์ ๋ฅผ ๋ฏฟ์ผ์ญ์์ค.
1) ํฌ๋ช
ํ ๋ฐฐ๊ฒฝ์ 1์ ๋ชจ์๋ง ์๋ ์์ฉ ํ๋ก๊ทธ๋จ ์์ด์ฝ ๋ฒ์ ์ ์ค๋นํฉ๋๋ค.
2) ์ฌ๊ธฐ๋ก ์ด๋: http://romannurik.github.io/AndroidAssetStudio/icons-notification.html#source.type=clipart&source.clipart=ac_unit&source.space.trim=1&source.space.pad=0&name=notification_icon "์ด๋ฏธ์ง" ๋๋ฅด๊ธฐ ์ผ์ชฝ ์๋จ์์ ์์ด์ฝ์ ์
๋ก๋ํ๊ณ ํ์ํ ๊ฒฝ์ฐ ์๋ผ๋ด๊ฑฐ๋ ํจ๋ฉ์ ์ถ๊ฐํฉ๋๋ค.
3) ์ ๋ณด์ด๋ฉด ์ค๋ฅธ์ชฝ ์๋จ์ ํ์ดํ๋ฅผ ๋๋ฌ 'drawable' ํด๋๋ฅผ ๋ค์ด๋ก๋ํฉ๋๋ค. ๋ด๋ถ์ res
ํด๋๊ฐ ์๊ณ ์์ด์ฝ ํฌ๊ธฐ๊ฐ ๋ค๋ฅธ 5๊ฐ์ drawable-xxx
ํด๋๊ฐ ์๋ zip ํ์ผ์ด ์ ๊ณต๋ฉ๋๋ค.
4) ํด๋น ๋๋ก์ด๋ธ ํด๋๋ฅผ ํ๋ก์ ํธ ์ด๋๊ฐ์ ๋ณต์ฌํฉ๋๋ค. ๋๋ฅผ ์ํด ์์ด์ฝ ๋ฐ ์คํ๋์ ํ๋ฉด ๋ฆฌ์์ค ์์ ๋ณต์ฌํ์ต๋๋ค. project-root/resources/android/notification_icon
5) <resource-file />
์ง์๋ฌธ์ ์ฌ์ฉํ์ฌ Android ์ฑ ๋ด๋ถ์ ํด๋น ํ์ผ์ ๋ณต์ฌํ๋๋ก config.xml ํ์ผ์ ๊ตฌ์ฑํฉ๋๋ค. crodova 8.x ์ดํ ์ฌ๋ฐ๋ฅธ ๋์ ๊ฒฝ๋ก๋ app/src/main/res
์
๋๋ค. ์ฝ๋ฅด๋๋ฐ < 8์์๋ res
์ ๋ถ๊ณผํ์ต๋๋ค (์ด์ ์ ๋ฆฌ์์ค ํ์ผ์ platforms/android/res
๋๋ ํ ๋ฆฌ์ ๋ณด๊ด๋์์ผ๋ฉฐ ์ง๊ธ์ platforms/android/app/main/res
). ๋น ์๋๋ก์ด๋ ์๋ฆผ ์์ด์ฝ์์ ์จ๋ผ์ธ์ผ๋ก 'ํด๊ฒฐ๋' ๋ฌธ์ ์ ๋๋ถ๋ถ์ ์ด์ ๋ํด ์ธ๊ธํ์ง ์์ต๋๋ค.
<platform name="android">
(...)
<resource-file src="resources/android/notification_icon/drawable-mdpi/notification_icon.png" target="app/src/main/res/drawable-mdpi/notification_icon.png" />
<resource-file src="resources/android/notification_icon/drawable-hdpi/notification_icon.png" target="app/src/main/res/drawable-hdpi/notification_icon.png" />
<resource-file src="resources/android/notification_icon/drawable-xhdpi/notification_icon.png" target="app/src/main/res/drawable-xhdpi/notification_icon.png" />
<resource-file src="resources/android/notification_icon/drawable-xxhdpi/notification_icon.png" target="app/src/main/res/drawable-xxhdpi/notification_icon.png" />
<resource-file src="resources/android/notification_icon/drawable-xxxhdpi/notification_icon.png" target="app/src/main/res/drawable-xxxhdpi/notification_icon.png" />
</platform>
6) ์ด์ ์์ฉ ํ๋ก๊ทธ๋จ์ ์์ด์ฝ์ด ๋๋ก์ด๋ธ ๋ฆฌ์์ค๋ก ์์ผ๋ฏ๋ก ์์ฉ ํ๋ก๊ทธ๋จ์์ ์ด ์์ด์ฝ์ ์ฌ์ฉํ๋๋ก ๊ฐ์ ํด์ผ ํฉ๋๋ค. ์ฌ๊ธฐ readme์ ์์ฑ๋ ๋ด์ฉ์ ๊ด๊ณ์์ด 'notification_icon'์ด๋ผ๋ ๋๋ก์ด๋ธ ๋ฆฌ์์ค์ ์๋ ๊ฒ์์ด ์๋ํ์ง ์์์ต๋๋ค. https://github.com/arnesson/cordova-plugin-firebase/blob/master/src/android/FirebasePluginMessagingService.java#L140์ ์ฝ๋๋ฒ ์ด์ค์ ์๋ ๊ฒ ๊ฐ์์ ๊ทธ ์ด์ ๋ฅผ ์ ํํ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค. ํ์ง๋ง ์ ๋ ์ต์ ๋ฒ์ ์ Android์์ ๋ฆฌ์์ค ๊ฒ์์ผ๋ก ๋ณ๊ฒฝ๋ ์ฌํญ์ด ์๋ค๊ณ ์ถ์ธกํฉ๋๋ค.
7) ๊ทธ ๋๋ฌธ์ ๋ด๊ฐ ์ฌ์ฉํ ์ ์๋ ์ ์ผํ ๋ค๋ฅธ ์๋ฃจ์
์ Firebase์ ํธ์ ์๋ฆผ์ ๋ณด๋ผ ๋ ๋ฐฑ์๋์์ icon
๋งค๊ฐ๋ณ์๋ฅผ ๋ณด๋ด๋ ๊ฒ๋ฟ์ด์์ต๋๋ค. ํ์ด๋ก๋์ notification
๋ฐ android
๋ถ๋ถ์ โโ์ฌ๋ฐ๋ฅด๊ฒ ๋ณํฉํ๋ ๋ฐ ๋ฌธ์ ๊ฐ ์๊ธฐ ๋๋ฌธ์ ํด๋น API๊ฐ ์ผ๋ถ ๋ณ๊ฒฝ๋ ์ ์์ต๋๋ค. ๊ทธ๋ฐ ์ด์ ๋ก json์ notification
๋ถ๋ถ์ icon ๋งค๊ฐ๋ณ์๋ฅผ ์ถ๊ฐํด์ผ ํฉ๋๋ค. Android ์ ์ฉ ๋งค๊ฐ๋ณ์๋ฅผ ์ฌ์ฉํ๋ฉด ์๋ํ์ง ์์ต๋๋ค.
๋ฐ๋ผ์ ๋ฐฑ์๋์์ Firebase๋ก ๋ณด๋ด๋ ์๋ฆผ ํ์ด๋ก๋๋ ๋ค์๊ณผ ๊ฐ์์ผ ํฉ๋๋ค. ์๋ํ๋ ์ ์ผํ ๋ฒ์ ์ ๋๋ค.
{
notification: {
body: 'Imma push your notification if you know what i mean!',
icon: 'notification_icon',
},
data: { someExtraData: 'goes_here' }
}
๋ค์ ๋ง์ ๋๋ฆฌ์ง๋ง - 2018๋ 7์ ๊ธฐ์ค์ผ๋ก Android ํน์ ๋งค๊ฐ๋ณ์๋ฅผ ์ฌ์ฉํ๋ฉด Firebase์์ ์๋ํ์ง ์์ต๋๋ค .
{
notification: {
body: 'Imma push your notification if you know what i mean!'
},
data: { someExtraData: 'goes_here_if_you_need_it' },
android: {
icon: 'notification_icon'
}
}
8) ๋ชจ๋ ๋จ๊ณ๊ฐ ์๋ฃ๋๋ฉด ์ด์ ์ ์์ด์ฝ์ ํ ์คํธํ ์ค๋น๊ฐ ๋์์ต๋๋ค. Android ์๋ฎฌ๋ ์ดํฐ ๋ด์์ ํ ์คํธํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ์ผ๋ถ Android ์คํจ์ ์ค์ ํ ํญ๋ชฉ(์: xiaomi์ MIUI)์ ๊ด๊ณ์์ด ์๋ฆผ ํ์์ค์ ์ธ์ํ๊ณ ์ ํ๋ฆฌ์ผ์ด์ ์์ด์ฝ์ ์ฌ์ฉํฉ๋๋ค. ์์ด์ฝ์ด ์บ์๋๋ ๊ฒฝ์ฐ๋ ์์ต๋๋ค. ๊ทธ๋ฐ ์ด์ ๋ก ์๋ก ์์ฑ๋ AVD์ ์๋ฎฌ๋ ์ดํฐ์์ ํ ์คํธํ๋ ๊ฒ์ด ๊ฐ์ฅ ์์ ํ ๋ฐฉ๋ฒ์ ๋๋ค. ์บ์ฑ ๋ฌธ์ ๋ฅผ ํผํ๊ธฐ ์ํด ํ ์คํธ ์คํ ์ฌ์ด์ ์ฑ์ ์๋์ผ๋ก ์ ๊ฑฐํ๊ณ ์๋ฎฌ๋ ์ดํฐ/์ฅ์น๋ฅผ ๋ค์ ์์ํ์ญ์์ค.
์์ 10x10 ์์ด์ฝ์ ๋ณ๊ฒฝํ๊ธฐ ์ํด ๊ฑฐ์ณ์ผ ํ๋ ์ฅ์ ๋ฌผ์ ์์ด ๋๋ฌด ๋ง๊ธฐ ๋๋ฌธ์ ์ด ๊ธด ๊ธ์ด ๋ฏธ๋์ ๋ค๋ฅธ ์ฌ๋๋ค์๊ฒ ๋์์ด ๋๊ธฐ๋ฅผ ๋ฐ๋๋๋ค.
config.xml <platform name="android">
ํ๊ทธ์ ์ถ๊ฐ๋ ์ด ์ฝ๋๊ฐ ์์ด์ฝ์ ๊ธฐ๋ณธ ์๋ฆผ ์์ด์ฝ์ผ๋ก ์ถ๊ฐํ๋์ง ํ
์คํธํ์ญ์์ค.
<config-file parent="/manifest/application/" target="app/src/main/AndroidManifest.xml">
<meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@drawable/notification_icon" />
</config-file>
์ด๊ฒ์ ํ์ด๋ก๋์ ์์ด์ฝ์ด ์๋ Firebase ํด๋ผ์ฐ๋ ๋ฉ์์ง ํจ๋ ๋๋ ๋ฐฑ์๋๋ก ์ ์กํ๋ ๋ฐ ํจ๊ณผ์ ์
๋๋ค.
์ฌ๊ธฐ์ ํผ๋๋ฐฑ์ ๊ฒ์ํ์ญ์์ค.
์๋ํ๋ค๋ฉด ์ด ์ฝ๋์ ์ถ๊ฐ๋ ํํ ๋ฆฌ์ผ์ด ๋ง์ ์ฌ๋๋ค์๊ฒ ๋์์ด ๋ ๊ฒ์ด๋ฉฐ README์ ์ถ๊ฐํ๊ธฐ ์ํด PR์ ์ด์ด์ผ ํฉ๋๋ค.
@madsheep ๊ฐ์ฌํฉ๋๋ค!! ๋น์ ์ ๋ด ์๋ช ์ ๊ตฌํ๋ค !!
์๋ ํ์ธ์. ๋๋์ ์ง์์ ๊ฐ์ฌ๋๋ฆฌ๋ฉฐ ์ด ํผ๋์ ๋น ์ง ์ฌ๋์ ์ ํผ์๊ฐ ์๋๋ผ๋ ๋๋์ ๋ฐ์์ต๋๋ค. ํ์ง๋ง ์ํ๊น๊ฒ๋ 0๋จ๊ณ ์ ์ผ๋ก ๋๋์๊ฐ๋ ๋์ค์ ๋จธ๋ฆฌ์นด๋ฝ์ด ๋น ์ง๊ณ ๋ง์์ต๋๋ค.
http/post ๋ฉ์๋๋ฅผ ํตํด ์๋ฆผ์ ๋ณด๋ด๋ ค๊ณ ํ๋ฉด Firebase API์์ json์ด ์ ํจํ์ง ์๋ค๋ ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค. ๋๋ ๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ ๋ชจ๋ ์๋ํ์ต๋๋ค.
์ด๊ฒ์ ์์ด์ฝ์ message: { notification: { icon: 'notification_icon', ... }, ... }
๋ก ํฌํจํ ๋ ์ป๋ ๊ฒ์
๋๋ค.
Error code=400, message=Invalid JSON payload received. Unknown name "icon" at 'message.notification': Cannot find field., status=INVALID_ARGUMENT, details=[@type=type.googleapis.com/google.rpc.BadRequest, fieldViolations=[field=message.notification, description=Invalid JSON payload received. Unknown name "icon" at 'message.notification': Cannot find field.]]
message: { android: { icon: 'notification_icon' }, ... }
๋ก ์์ด์ฝ์ ํฌํจํ ๋ ๋ฐ๋ ๋ฉ์์ง์
๋๋ค.
Error code=400, message=Invalid JSON payload received. Unknown name "icon" at 'message.android': Cannot find field., status=INVALID_ARGUMENT, details=[@type=type.googleapis.com/google.rpc.BadRequest, fieldViolations=[field=message.android, description=Invalid JSON payload received. Unknown name "icon" at 'message.android': Cannot find field.]]
ํ์ง๋ง ์๋ง๋ ์๋ชป๋ ์ปจํ ์คํธ์์ ์ด๊ฒ์ ์ฌ์ฉํ๊ณ ์์ต๋๋ค(firebase ํด๋ผ์ฐ๋ ๋ฉ์์ง์ ์ฌ์ฉํ์ฌ ํด๋ผ์ด์ธํธ ์ฑ์ ์๋ฆผ์ ๋ณด๋ด๋ ๋ฐฑ์๋ ํด๋ผ์ฐ๋ ์ฝ๋).
์ด๊ฒ์ ๋๋ฅผ ์ํด ์ ์๋ํ์ต๋๋ค (Firebase ๊ธฐ๋ฅ์ ์ฌ์ฉํ์ฌ ์๋ฆผ์ ๋ณด๋
๋๋ค).
const payload = {
notification: {
title: ........,
body: .........,
icon: 'notification_icon'
}
};
๋๋ถ์ ๋ ๊ฐ์ง ์ค๋ฅ ์ค ์ฒซ ๋ฒ์งธ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค. javascript/request ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํตํด REST ์๋น์ค๋ฅผ ์ฌ์ฉํ๊ณ ์์ผ๋ฉฐ https://firebase.google.com/docs/cloud-messaging/js/first-message ํ์์ ๋ฐ๋ผ ๋ณด๋ ๋๋ค. ๋ฉ์์ง/์๋ฆผ ํ์์ด https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages#Notification ์ ์ค๋ช ๋์ด ์๋ค๊ณ ๊ฐ์ ํฉ๋๋ค.
์ฌ์ค, ๋ด๊ฐ ์ด๊ฒ์ ์ฝ์ ๋, ์ด๊ฒ์ ์์ด์ฝ์ด message.android.notification.icon
, ์ฆ, ํ ๋จ๊ณ ๋ ๊น์ด์ผ ํ๋ค๋ ๊ฒ์ ์์ํฉ๋๋ค.
๋๋ ๋ฐฉ๊ธ ์๋ํ๊ณ ์ด๊ฒ์ ์ค์ ๋ก ๋๋ฅผ ์ํด ์๋ํฉ๋๋ค! ๊ทธ๋์ ํ์ด๋ก๋๊ฐ ์ด๋ป๊ฒ ๊ตฌ์ฑ๋์ด์ผํ๋์ง serverprotocol์ ๋ฌ๋ ค ์๋ค๊ณ ๊ฐ์ ํฉ๋๋ค ...
ํ ๋ก ์ ์ฐธ์ฌํด ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค. ๊ฒฐ๊ตญ ๋จธ๋ฆฌ์นด๋ฝ ๋ฝ๋๊ฑฐ ๋ฉ์ท๋ค...
ํด๊ฒฐ๋ ๋๋ก ์ข ๋ฃ
@madsheep ์๋ํ์ง ์์ต๋๋ค. ํด๋ผ์ฐ๋ ๊ธฐ๋ฅ์ ์๋ฆผ ์๋์ '์์ด์ฝ'์ ์ถ๊ฐํ๋ฉด ๋ค์ ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค.
{ Error: Invalid JSON payload received. Unknown name "icon" at 'message.notification': Cannot find field
์ค๋ฅ ์ ๋ณด:
{ ์ฝ๋: '๋ฉ์์ง/์๋ชป๋ ์ธ์',
๋ฉ์์ง: '์๋ชป๋ JSON ํ์ด๋ก๋๊ฐ ์์ ๋์์ต๋๋ค. 'message.notification'์์ ์ ์ ์๋ ์ด๋ฆ "icon": ํ๋๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค.' },
codePrefix: '๋ฉ์์ง' }
์๋ message.android.notification.icon
๋์ message.notification.icon
.
@madsheep @guilhermehtk ๊ทธ๊ฒ์ ๋๋ฅผ ์ํด ์ผํ์ต๋๋ค! ๊ณ ๋ง์.
config.xml
<platform name="android">
ํ๊ทธ์ ์ถ๊ฐ๋ ์ด ์ฝ๋๊ฐ ์์ด์ฝ์ ๊ธฐ๋ณธ ์๋ฆผ ์์ด์ฝ์ผ๋ก ์ถ๊ฐํ๋์ง ํ ์คํธํ์ญ์์ค.<config-file parent="/manifest/application/" target="app/src/main/AndroidManifest.xml"> <meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@drawable/notification_icon" /> </config-file>
์ด๊ฒ์ ํ์ด๋ก๋์ ์์ด์ฝ์ด ์๋ Firebase ํด๋ผ์ฐ๋ ๋ฉ์์ง ํจ๋ ๋๋ ๋ฐฑ์๋๋ก ์ ์กํ๋ ๋ฐ ํจ๊ณผ์ ์ ๋๋ค.
์ฌ๊ธฐ์ ํผ๋๋ฐฑ์ ๊ฒ์ํ์ญ์์ค.
์๋ํ๋ค๋ฉด ์ด ์ฝ๋์ ์ถ๊ฐ๋ ํํ ๋ฆฌ์ผ์ด ๋ง์ ์ฌ๋๋ค์๊ฒ ๋์์ด ๋ ๊ฒ์ด๋ฉฐ README์ ์ถ๊ฐํ๊ธฐ ์ํด PR์ ์ด์ด์ผ ํฉ๋๋ค.
์ค๋์ ์ง์ง ๋ ๋๋ถ์ด๋ค,
๋๊ตฐ๊ฐ ๋น๋์์ ๋ฌธ์ ์ ์ง๋ฉดํ๋ฉด
AAPT: ์ค๋ฅ: ์ธ๋ฐ์ด๋ ์ ๋์ฌ.
๊ทธ๋ฐ ๋ค์ ์ถ๊ฐํ๋ ค๊ณ
xmlns:android= " http://schemas.android.com/apk/res/android "
์์ฑ์ ๋ฃจํธ์ ์ถ๊ฐํด์ผ ํฉ๋๋ค.
๋น์ ์ ๋ด ํ๋ฃจ๋ฅผ ๊ตฌํ๋ค!
2019๋ Android ๋น๋ 7.1.1์์ ์ด ๋ฌธ์ ์ ์ง๋ฉดํ ์ฌ๋์ด๋ผ๋ฉด ๋ฆฌ์์ค ํด๋๊ฐ ๋ณ๊ฒฝ๋ ๊ฒ ๊ฐ์ต๋๋ค!!
Android ์คํ๋์ค์ ์์ฑ๋ ํ์ผ์ ํ์ธํ๋ฉด ๋ค์๊ณผ ๊ฐ์ด ๋์๊ฒ ๋์์ด ๋ฉ๋๋ค.
<resource-file src="resources/android/notification/notification_icon.png" target="app/src/main/res/drawable/notification_icon.png" />
<config-file parent="/manifest/application/" target="app/src/main/AndroidManifest.xml">
<meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@drawable/notification_icon" />
</config-file>
์ฒซ ๋ฒ์งธ ์ค์ ๋์๊ฒ ์๋ชป๋์๊ธฐ ๋๋ฌธ์ ์ค์ํ ๋ถ๋ถ์ ๋๋ค.
@alarv ์ผ๋ถ Android ํด๋์ ํ์์๋ ์์ด์ฝ์ด ํ์๋์ง ์์ต๋๋ค. ์ด์ ๋ํ ๋์์ ๋ถํ๋๋ฆฝ๋๋ค.
@bioyeneye ์ด๋ค ๋ชจ๋ธ์ธ๊ฐ์? ์ด๋ค ๋ฒ์ ์ Android๋ฅผ ์คํํ๊ณ ์๋์? ์ฃผ์ ๋๋ ๊ธฐํ?
@bioyeneye ๋ชจ๋ ์๋๋ก์ด๋ ์ฅ์น์์ ์์ด์ฝ์ด ์๋ํ๋๋ก ํ๋ Ionic 4์ ๋ํ ๋ ๋ค๋ฅธ ์๋ฃจ์
์ด ์์ต๋๋ค.
์์ด์ฝ์ png๊ฐ ์๋๋ผ XML์ ์ฌ์ฉํ๊ณ ์์ต๋๋ค. ๋ค์ ๋๋ ํ ๋ฆฌ์ ์ด๊ฒ์ ํฌํจํ๊ธฐ ์ํด ํํฌ๋ฅผ ์ฌ์ฉํ๊ณ ์์ต๋๋ค.
'res/drawable-hdpi',
'res/drawable-mdpi',
'res/drawable-xhdpi',
'res/drawable-xxhdpi',
'res/drawable-xxxhdpi',
'res/mipmap-hdpi',
'res/mipmap-mdpi',
'res/mipmap-xhdpi',
'res/mipmap-xxhdpi',
'res/mipmap-xxxhdpi'
ํ์ผ ์์ ๋ง๋ค๊ธฐ:
android_notification_resources.js
์ด ์ ํํฌ ํ์ผ์ ๋ค์์ ์ถ๊ฐํฉ๋๋ค.
// ์์ํ๋ค
const fs = ์๊ตฌ("fs");
const ๊ฒฝ๋ก = ์๊ตฌ("๊ฒฝ๋ก");
const Q = ์๊ตฌ("q");
var sourceDir = '๋ฆฌ์์ค/์๋๋ก์ด๋/์๋ฆผ_์์ด์ฝ'; // ์ด๊ฒ์ ๋น์ ์ ์์ด์ฝ์ด ์๋ ๊ณณ์
๋๋ค
var platformDir = 'ํ๋ซํผ/์๋๋ก์ด๋/์ฑ/src/๋ฉ์ธ/';
var ๋ฆฌ์์ค ๋๋ ํ ๋ฆฌ = [
'ํด์๋/๋๋ก์ด๋ธ-HDPI',
'res/drawable-mdpi',
'res/drawable-xhdpi',
'res/drawable-xxhdpi',
'res/drawable-xxxhdpi',
'res/mipmap-hdpi',
'res/mipmap-mdpi',
'res/mipmap-xhdpi',
'res/mipmap-xxhdpi',
'res/mipmap-xxxhdpi'
];
module.exports = ํจ์(ctx) {
if (ctx.opts.platforms.indexOf('์๋๋ก์ด๋') < 0) {
๋ฐํ;
}
var ์ง์ฐ = Q.defer();
var androidPlatformDir = path.join(ctx.opts.projectRoot, platformDir);
var customResourcesDir = path.join(ctx.opts.projectRoot, sourceDir);
ํจ์ ๋ณต์ฌ(src, ๋์) {
var ์ง์ฐ = Q.defer();
fs.stat(src, function(err, stats) {
if (err || !stats.isFile()) {
return deferred.reject(err);
}
fs.stat(path.dirname(dest), function(err, stats) {
if (err || !stats.isDirectory()) {
return deferred.reject(err);
}
var rs = fs.createReadStream(src);
rs.on('error', function(err) {
console.error(err.stack);
deferred.reject(err);
});
var ws = fs.createWriteStream(dest);
ws.on('error', function(err) {
console.error(err.stack);
deferred.reject(err);
});
ws.on('close', function() {
deferred.resolve();
});
rs.pipe(ws);
});
});
return deferred.promise;
}
fs.stat(customResourcesDir, ํจ์(์ค๋ฅ, ํต๊ณ) {
if (err || !stats.isDirectory()) {
๋ฐํ deferred.resolve();
}
fs.readdir(customResourcesDir, function(err, files) {
var copies = [];
for (var i in files) {
for (var j in resourceDirs) {
var filePath = path.join(ctx.opts.projectRoot, sourceDir, files[i]);
var destPath = path.join(androidPlatformDir, resourceDirs[j], files[i]);
copies.push([filePath, destPath]);
}
}
copies.map(function(args) {
return copy.apply(copy, args);
});
Q.all(copies).then(function(r) {
deferred.resolve();
}, function(err) {
console.error(err.stack);
deferred.reject(err);
});
});
});
deferred.promise๋ฅผ ๋ฐํํฉ๋๋ค.
}
// ๋
config.xml์ ๋ค์ ์ค์ ์ถ๊ฐํ์ฌ ํํฌ๋ฅผ ํฌํจํฉ๋๋ค.
ํํฌ๊ฐ ํ๋ ์ผ์ ๋ฆฌ์์ค ํด๋์์ ์์ด์ฝ์ ๋ณต์ฌํ์ฌ ๋ค๋ฅธ ๋๋ก์ด๋ธ ํด๋์ ์ถ๊ฐํ๋ ๊ฒ์ ๋๋ค. ๋ชจ๋ ์ฅ์น์์ ์๋ํ๋์ง ํ์ธํ๊ธฐ ์ํด ์ด ์์ ์ ์ํํ์ต๋๋ค. ์ฌํ๊น์ง๋ ๊ทธ๋ฐ๋๋ก ์๋๋ค.
๊ทธ๊ฒ์ด ๋น์ ์ ์ํด ์ผํ๋์ง ์๋ ค์ฃผ์ญ์์ค! ๊ฑด๋ฐฐ
@RobinGiel ๊ฐ์ฌํฉ๋๋ค, ์ ๋ ionic 3๋ฅผ ์ฌ์ฉํ๊ณ ์์ต๋๋ค. ์๋ํ ๊น์?
์๋
ํ์ธ์ @Flucadetena
์๋๋ก์ด๋ 9
์ฝ๋ฅด๋๋ฐ ํ๋ซํผ: ์๋๋ก์ด๋ 7.1.1
@bioyeneye ์ ๋ ionic 3๋ฅผ ์ฌ์ฉํ๊ณ ์์ต๋๋ค. ๋ค ํ์ธํด๋ณด๊ณ ์๋ ค๋๋ฆฌ๊ฒ ์ต๋๋ค. ;)
@bioyeneye ์, ํํฌ์์ ๋ช ์ค์ ์์ ํด์ผ ํฉ๋๋ค.
var sourceDir = '๋ฆฌ์์ค/์๋๋ก์ด๋/์๋ฆผ_์์ด์ฝ';
var platformDir = 'ํ๋ซํผ/์๋๋ก์ด๋';
const Q = require("q"); ํด๋น ์ค์ ์ ๊ฑฐํ๊ณ ์ฌ๊ธฐ์ ์ฌ์ฉํ์ญ์์ค. ์:
module.exports = ํจ์(ctx) {
if (ctx.opts.platforms.indexOf('์๋๋ก์ด๋') < 0) {
๋ฐํ;
}
var Q = ctx.requireCordovaModule('q'); // ์ฌ๊ธฐ์ ์ฌ์ฉ
var ์ง์ฐ = Q.defer();
var androidPlatformDir = path.join(ctx.opts.projectRoot, platformDir);
var customResourcesDir = path.join(ctx.opts.projectRoot, sourceDir);
๋์ผํ ํํฌ before_build ๋ฐ before_run ์์ ๋ฅผ ํธ์ถํ๋ config.xml์ ์ถ๊ฐํฉ๋๋ค.
<hook type="before_run" src="hooks/android_notification_resources.js" />
<hook type="before_build" src="hooks/android_notification_resources.js" />
config.xml
<platform name="android">
ํ๊ทธ์ ์ถ๊ฐ๋ ์ด ์ฝ๋๊ฐ ์์ด์ฝ์ ๊ธฐ๋ณธ ์๋ฆผ ์์ด์ฝ์ผ๋ก ์ถ๊ฐํ๋์ง ํ ์คํธํ์ญ์์ค.<config-file parent="/manifest/application/" target="app/src/main/AndroidManifest.xml"> <meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@drawable/notification_icon" /> </config-file>
์ด๊ฒ์ ํ์ด๋ก๋์ ์์ด์ฝ์ด ์๋ Firebase ํด๋ผ์ฐ๋ ๋ฉ์์ง ํจ๋ ๋๋ ๋ฐฑ์๋๋ก ์ ์กํ๋ ๋ฐ ํจ๊ณผ์ ์ ๋๋ค.
์ฌ๊ธฐ์ ํผ๋๋ฐฑ์ ๊ฒ์ํ์ญ์์ค.
์๋ํ๋ค๋ฉด ์ด ์ฝ๋์ ์ถ๊ฐ๋ ํํ ๋ฆฌ์ผ์ด ๋ง์ ์ฌ๋๋ค์๊ฒ ๋์์ด ๋ ๊ฒ์ด๋ฉฐ README์ ์ถ๊ฐํ๊ธฐ ์ํด PR์ ์ด์ด์ผ ํฉ๋๋ค.์ค๋์ ์ง์ง ๋ ๋๋ถ์ด๋ค,
๋๊ตฐ๊ฐ ๋น๋์์ ๋ฌธ์ ์ ์ง๋ฉดํ๋ฉด
AAPT: ์ค๋ฅ: ์ธ๋ฐ์ด๋ ์ ๋์ฌ.
๊ทธ๋ฐ ๋ค์ ์ถ๊ฐํ๋ ค๊ณ
xmlns:android= " http://schemas.android.com/apk/res/android "
์์ฑ์ config.xml ๋ด๋ถ์ ๋ฃจํธ ํ๊ทธ์ ์ถ๊ฐ๋์ด์ผ ํฉ๋๋ค.
์ด๊ฒ์ ๋๋ฅผ ์ํด ์๋ํ์ง๋ง ์์ด์ฝ์ด ์์ฒญ๋๊ฒ ์์ ๊ฒ ๊ฐ์ต๋๋ค. ์ฌ์ฉํด์ผ ํ๋ ํ์ผ์ ์ ์ ํ ํฌ๊ธฐ๋ ์ผ๋ง์ ๋๊น?
ํธ์ง: 256x256์ ์ถ๊ฐํ์ง๋ง ์ฌ์ ํ ์ํ ํ์์ค์ ์์ ์ ์ด ํ์๋ฉ๋๋ค. ์ํ ํ์์ค์ ์๋์ชฝ์ผ๋ก ๋๋๊ทธํ๋ฉด ์ฝ๊ฐ ๋ ํฐ ํ์์ค์ด ํ์๋ฉ๋๋ค.
๊ทธ๊ฒ์
๋น์ ์ ๋ด ์๋ช
์ ์์ธ์
๋๋ค!! ๊ฐ์ฌํฉ๋๋ค!!!
๋
ธํธ:
์๋ฆผ ์น์
์ color: '#e50012'๋ฅผ ์ถ๊ฐํ์ฌ ์์ด์ฝ์ ์์์ผ๋ก ๋ณ๊ฒฝํฉ๋๋ค.(์์์ด ๋ฌด์์ด๋ ๋ณ๊ฒฝ).
์ :
{
"์ด๋ฆ": "my_notification",
"์๋ฆผ": {
"๋ณธ๋ฌธ": "ํต์ง ๋ณธ๋ฌธ",
"์ ๋ชฉ": "์๋ฆผ ์ ๋ชฉ",
"์์": "#e50012"
},
"๋ฐ์ดํฐ":{ ... }
}
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
config.xml
<platform name="android">
ํ๊ทธ์ ์ถ๊ฐ๋ ์ด ์ฝ๋๊ฐ ์์ด์ฝ์ ๊ธฐ๋ณธ ์๋ฆผ ์์ด์ฝ์ผ๋ก ์ถ๊ฐํ๋์ง ํ ์คํธํ์ญ์์ค.์ด๊ฒ์ ํ์ด๋ก๋์ ์์ด์ฝ์ด ์๋ Firebase ํด๋ผ์ฐ๋ ๋ฉ์์ง ํจ๋ ๋๋ ๋ฐฑ์๋๋ก ์ ์กํ๋ ๋ฐ ํจ๊ณผ์ ์ ๋๋ค.
์ฌ๊ธฐ์ ํผ๋๋ฐฑ์ ๊ฒ์ํ์ญ์์ค.
์๋ํ๋ค๋ฉด ์ด ์ฝ๋์ ์ถ๊ฐ๋ ํํ ๋ฆฌ์ผ์ด ๋ง์ ์ฌ๋๋ค์๊ฒ ๋์์ด ๋ ๊ฒ์ด๋ฉฐ README์ ์ถ๊ฐํ๊ธฐ ์ํด PR์ ์ด์ด์ผ ํฉ๋๋ค.