From 8007dd59281be3e7a58ffee0abfd6cc5fad06186 Mon Sep 17 00:00:00 2001 From: komekh Date: Tue, 10 Sep 2024 09:58:33 +0500 Subject: [PATCH] added firebase notification --- android/app/google-services.json | 29 + android/app/src/main/AndroidManifest.xml | 9 + .../app/src/main/res/drawable/ic_launcher.xml | 3057 +++++++++++++++++ .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 544 -> 2467 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 442 -> 1554 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 721 -> 3968 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 1031 -> 5793 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 1443 -> 9226 bytes android/app/src/main/res/values/strings.xml | 4 + ios/Runner/GoogleService-Info.plist | 30 + ios/firebase_app_id_file.json | 7 + lib/core/utils/download_file.dart | 25 + lib/core/utils/notification_service.dart | 284 ++ lib/core/utils/utils.dart | 1 + lib/firebase_options.dart | 68 + lib/main.dart | 21 + pubspec.lock | 176 + pubspec.yaml | 5 + 18 files changed, 3716 insertions(+) create mode 100644 android/app/google-services.json create mode 100644 android/app/src/main/res/drawable/ic_launcher.xml create mode 100644 android/app/src/main/res/values/strings.xml create mode 100644 ios/Runner/GoogleService-Info.plist create mode 100644 ios/firebase_app_id_file.json create mode 100644 lib/core/utils/download_file.dart create mode 100644 lib/core/utils/notification_service.dart create mode 100644 lib/firebase_options.dart diff --git a/android/app/google-services.json b/android/app/google-services.json new file mode 100644 index 0000000..a265ce5 --- /dev/null +++ b/android/app/google-services.json @@ -0,0 +1,29 @@ +{ + "project_info": { + "project_number": "598107454568", + "project_id": "cargo66", + "storage_bucket": "cargo66.appspot.com" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:598107454568:android:b2b6e38663f71e9e314fdd", + "android_client_info": { + "package_name": "com.cargo66.com" + } + }, + "oauth_client": [], + "api_key": [ + { + "current_key": "AIzaSyB4aGhjQIDs6neCWrrITI6iujKhKm2Y9cg" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [] + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 29fb761..054c2e8 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -4,6 +4,15 @@ android:label="Cargo 66" android:name="${applicationName}" android:icon="@mipmap/launcher_icon"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png index db77bb4b7b0906d62b1847e87f15cdcacf6a4f29..54c5e4725ed7bc5eafbbb6db594289fe1a0450dc 100644 GIT binary patch literal 2467 zcmV;U30(GxP)Px;T}ebiRCr$Pn|V}~Wgf>rcSpSJ2#A20f@3vi%c-$+%sT2g&S)d1Xoia9t|-Ta z6qUp!T#zKo<=}=XN~xq)qnXvHnVIF%%rPw&5CmkA_3n4h`;wk+m$>S^m+YMP`G>na zzvun^KKJ|kKF@st*^@nfvLcP&Bp{OjHLVT_kb~}#07-zHGgwJMl7b`!IY&TJkaPSb z50VrlDabhjl7gJ$CwY*hAW1>a5s(z*96!l}Bn3$da*n|Ls31RWInPFYC8l;R{~<1y zwslzKqixR+9&il{G7fzA0w#;fVT>y#{4O4p8k5T3x*S4pR53JT1Nmj)P1X_?P(b$N zF=##N*m3MdmVYqS6}8{d8qE$UA~2twiLof;R+8RL;n3OV945LdZaQ6~P9psJrBCW^ zDr)^4#<*%ivjXyKSwYUUQTS^sIdS1}CT68OtfPCUBcu&a!D@v`Szm+f!Uw`yH*-Y=EL#Utnv( ztH^-GyAs)bqQAog6aSIP&~EQjt8YQSCArkDd%l28r_qciqK|0jrvfxm+5~u#7CXLvlNy z*dE)M+;^Q=?A9+{V#l#)%BubGQ0a*Zy+F#~C4~5vQd#TGpcUCDNszXN)lUc%7!$|7CEcqXJE0)NZ63Z@e5Dc#Vj70La#?Z<8nzjFQsn*(fZvp+zLpo z)N^!UA2IVuSxfnUGP=X_fEuURx#_v3@#N%FnFaY20+P$j98T$nr$)z|ZF4zr<^{V#G)g^rvxX4h zRmq&~$tYwN7Q`&3tlE$MX*n278oQW2j~-;<&_&efJbC{0eORsXKPDg{>xD53=+os> zE|o+OvvQ-|8D?b9Y$o=}5(|u3xdFM{!nTBX@%dXH#k2YI;Wot!(03$`)V21i)ftt}>8ATs14TNC1u%iw%rd$u1L#QDNVd_Ak^`}hHRcRq}VTF>sU`tin| zM6uYZ{oWQ&(DeolpPcE*ho^c|S?5j1(2ES~mP^#n=cD1P)`>fuJBQl=3CTaz;cMm& zS}JbmzaA#Df=Dt7R;#eMdE8AK}u5RwxVNX!)g0^ zv61O>O1N6k2>pAc<}yINdbVU%Vj!t$rJVmkk5VOL_z)jXpVf(8(80 z*@JPT{rK0g0x|86cSTTLV`26Ba;{u8(!QOFNn`z4y}p7o=X9u5GM??~Nzd+{sMRtN zP-uvfw^oGk?v9&$`E@;3tCdGOd61MC$o$169Qm^T9+B9Fxdf104%;@gA#+VRM~~lG zVjJFW&AdgW6kIcLU{3@K-YDhB@p`mc8F||yNXxjvfkU-6+0LFGNMw5zqbC-z@tsh< zI8sMecBRdn=l|+S+$+AsjxBUaySW5V+i)eB%UjcbNd9krYR^2~f+5k~bnKv^MT-W{ zh?`Kz#h(o1<%BaJrXjXtq?+}ap$s08&-G%n&3b;ma?+OsGks1mySGI!A+d;a|JB=F z^Mf7XOrBoEm3;eC_}$9NC4e4?Q1a%|*0+oNWfFqNq`e-D*<$7WylQTgnM8w5o)O5> zj50ewf4ejZ2ps%v0Fuwr>n$c1npIATO;FQ$wO z5O<@(>kXgWxHw--W{4f?OHxWP$A0#wxZyqwkMU(}LJ=2!v~4jV?x8n);5hlMKHv?i3K`6ZnERwrIhQ1a%rVJt~6<>Q04{&i1uTnR|6 zhQ7VD#6i zF1ByK-daYDFXY;ev$`C3X&A$905r|&he8xNK%lbAm<23 h3UZF0P5D~Wn-+_Wa#27Xc zC?Zj|6r#X(-D3u$NCt}(Ms06KgJ4FxJVv{GM)!I~&n8Bnc94O7-Hd)cjDZswgC;Qs zO=b+9!WcT8F?0rF7!Uys2bs@gozCP?z~o%U|N3vA*22NaGQG zlg@K`O_XuxvZ&Ks^m&R!`&1=spLvfx7oGDKDwpwW`#iqdw@AL`7MR}m`rwr|mZgU`8P7SBkL78fFf!WnuYWm$5Z0 zNXhDbCv&49sM544K|?c)WrFfiZvCi9h0O)B3Pgg&ebxsLQ05GG~ AQ2+n{ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png index 17987b79bb8a35cc66c3c1fd44f5a5526c1b78be..8b8b89a168aa60397d3e58c8889278a21fe763a3 100644 GIT binary patch delta 1548 zcmV+n2J`v41Ck7o8Gi-<00374`G)`i00DDSM?wIu&K&6g00qoRL_t(&L+zP)a1&)1 zho9X|nlwk7v}p_FC?Fz-0#)SjfP#on&Q~`T8%C`wLD3gs~JC* zrvbvB^p)w+?igNw4BwTt$K%t7sXv$QAQOcE(=u0ZYo|jj%A3lkCwu<|pnIDl=8k%i z_lq-FU3ecJUw`bC190;-ht%Xg{kA91Z=Z=Tp#4K~CcT?iCe6SW=j74c97-Ln{>Guu zc`iW@$RwI8n3Mey?NUk@w`>*Fb@6}5L=ppx@4J}^8E=r2H6spdf`MDw$@0HL4EfdeM zLI6RaOj`u~Y@i9Gf1zA1waa1Q#?~lRlF>?6S^{hKEmKu*a zEH}b-VEWKk8PO|`T}K9!cQ_NPsgj8UHjrjJ!<5_{Vl+NhPM*fevsbgGa6Af-hcdfB&!N0UQPg+eY1yCRB|29ZJUYvf|}jZiq(cL_%Z{(EHS8SAgs}M zGy;iM5u;J0syc|XB0wMznm-{sFnFMm4((&G{}LeCCh=ZjE$Q9#>YIOjoP;1k!GT(` zGEI2uWff4b7Z63LstRJUh?q?xJNLNh)60M{R-~fxw^%2>_EPxa`H%=g0?_LO7JogT z%)I#y92EhK27y2j;>;q=Q#4pC665cUXYuk12J|(sd0Q1NTWIOi)4;lom3X`|EmJj& z&W@v`)JL-v4J+5WR7a9*5_6ukF=KW)Uhl>KU>*{HEm30bEE`jwus5irY&>~_l@s51 z`MJ!`gfa2FzS>2njyiVlb8)zD=5yvZW65%71Aqc}&+vHG zZ>prGHb~pnT1E|zN!=2?S*_ZZWC}y4^vwY$OSG>~_=Z##r<^ z5m#kEy{|wO9rs4A2b9Q)3&}|mR*R%gj&pXudToi9u$TMQ$)YG7qZM%11XVS4IzcTR zrH6bznL9Jhyp!jq!WB?~4Sxnvoj^+IgrdHhPo)2$QQ#(yvyk_$8>chC;M+~=sNA%* zieNA#vH$krhyy5&b?z8L|Gq}G#J(u|!i~j`I?$Lx yk-i^wAkqpq7C-7hV+uw3e$;_TE8JN8UjY^|fKL$wUy}d;002ovP6b4+LSTZq0O+g$ literal 442 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 byrn2YW;T*&zq`G&)Br6tJ=IcWn~?tjj@eul literal 721 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD3?#3*wSy!iOI#yLg7ec#$`gxH85~pclTsBt za}(23gHjVyDhp4h+5i=O3-AeX1=1l$e`s#|#^}+&7(N@w0CIr{$Oe+Uk^K-ZP~83C zcc@hG6rikF&NPT(23>y!y&wkt5C($~2D>~)O*cj@FGjOCM)M>_ixfudOh)?xMu#Fs z#}Y=@YDTwOM)x{K_j*Q;dPdJ?Mz0n|pLRx{4n|)f>SXlmV)XB04CrSJn#dS5nK2lM zrZ9#~WelCp7&e13Y$jvaEXHskn$2V!!DN-nWS__6T*l;H&Fopn?A6HZ-6WRLFP=R` zqG+CE#d4|IbyAI+rJJ`&x9*T`+a=p|0O(+s{UBcyZdkhj=yS1>AirP+0R;mf2uMgM zC}@~JfByORAh4SyRgi&!(cja>F(l*O+nd+@4m$|6K6KDn_&uvCpV23&>G9HJp{xgg zoq1^2_p9@|WEo z*X_Uko@K)qYYv~>43eQGMdbiGbo>E~Q& zrYBH{QP^@Sti!`2)uG{irBBq@y*$B zi#&(U-*=fp74j)RyIw49+0MRPMRU)+a2r*PJ$L5roHt2$UjExCTZSbq%V!HeS7J$N zdG@vOZB4v_lF7Plrx+hxo7(fCV&}fHq)$ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png index d5f1c8d34e7a88e3f88bea192c3a370d44689c3c..1b13af5b7c6ffd1750455c87b074c25cf67c72b8 100644 GIT binary patch literal 5793 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 diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png index 4d6372eebdb28e45604e46eeda8dd24651419bc0..6ee03adc60ff40cb1ee428ed8d3b40f69dcc0009 100644 GIT binary patch literal 9226 zcmeI2RaYHN(}riWaSg$p;2Q}R+zB2axVyUt2*C;N&c@w>yIUZ*ySqCC5AgB)hVS$} znC@C@>Y%!&d)3@mSEz!#BpNayG5`Q*(o$kdZ*$jw4zs`NScP)O1r1;&;JJ1FvFK_@>h7Y?T8hSNUmfO6AH1!C0{$4gfc!J6NJ#KcY}I z3fY_mhUnFs=s4O{q;PF;lXiivDny-X@9qV4%`VjcjIbOFzTzHvQrfRUmU>W-7(fqQ z4GG%)YM^yTaN#01#u_k*xZN`;3014+5cdnu?f3Vla7^dol)&R4%i5;f#CCc{1$CVjKr2x5m=j# z8R>T5L5R_-?l|$@FR0RodJXb)gWkk|YnU!%Tx=hHnWbvhs!6lz6+_={WbI|}Fw=F+ zM*mL9&yD4&9YUwOlWDLKe@~H8Ys($AT8xlaZQ%9pN$vUSW)G-Rrs?j8uBuy?!oH4t z7a=R-ELkbeaKW8ZoKd?pzbakQ9m18Iz5S~-TVcoZ$@~as;X<93adjO-i^R>l+%XB< zMHpQ3EYEqDP{BUgviG68ST^H5dt+2@1-tEO%H&H08~$YR)_Tf>r63HyF&x%PD1B7U zuRTioSiX)1hh%UU?#F6Di8e)RAsRO*TJuVZaY8rw@9r;htj@zy`Bp2onUk?mf_9EJ zXp!`p*r-J@`};y)dt-eFdD!Zy`W=7;x?47JJN7ibPZxd$y{pArvJc~{<)E$+h6YD( z?baKsD=heWEx1IbWMf3}EN}iPobWr;9oNqC5h}~s?@avr$0JeQN{2^fLtPhK$s4CF zt#F);YDGP%>pu)`a`YyM65xj7*u;CPttQ?z@u0-p-`^;|%fMF1wtly~Lky@< z$w22`Re6IhGxmP3Q|e7T4Fw?Io7}9xU~skY7Hs_z+*WM;E8a~w@Q_)5qx{dc#L~|^ zlLzSi17i4l-_ma=Gp}i(@RE>iZj_235h(ZjfsX?vfdSj&bjpATzFrRrk5(?qT(QS` z9y+H{XKvsZtcQ{?@M_`I0oE||%qkQz5*|L!Vf$4-No1nYQYkd|a%l%zewI){?eGiD z*w59OT#kV@<6{_y8;wLyJ6uaIzDflm-x>1&S26kz8)+IZll>0L=7=88UhN-g>{ER2 zRkC1a0rR&N)oFIS0@o4D0`6DL+tvFzU+f;a>EO_Pb@2B~<@fi$IJ?&yAg?7R$#a1<-RHW^~87d1$X(A(&0c4mJCoB+*lf$ zA)ED=?g)&_>v)G+^Dwg%S3}jnw3Qb*m9S`}~62Wr)c}+%er9{Zh=)c!>!pCW!noqa5sI7|rnaw+1jLRTR~ zk8tYD?K{=9#VUKmh9GG6?Iq#j@ma=rWR;Z|M9NC1{fYR6v|54QMQYTcZ@VeC>7|L7 z;(eGyXBWJ$Bap&+I9pT1`udFI;5vo8Ao-2+E&ZFbPUhKaW?Cl9iIl{xdKi4;b$zo4 zII$^vmPHhVP|<1hne2bk-RSv)Dw|u+rF47O_~Kp^aGle+f8lus#FpH0;Lvp}f)-5l zEi?>uy3I;#CmNG0P!NPUV`E0!?|)Cyk$Lj1`{&;OYv!A+eh~YS-lT~DAt2=(m4_M~f83xA-BleM1!4a$ag8|p@iTX{o0n_nDvGBRrn7vR-qW-M` z4n3w+Y7=w-*tw57yx>?XYu8seN+&@x(VmW#lq)3k2!N5uLv?Bf(TmgQq_b`0&uG;R z*6uC*b^F1%!0~B5;L0?>?!(D;v{U=0-`)rDxuf(2UbY*0d{n0a6A8K($vUQ^RQlDr zS#8LxNaNm29wwg1#2I8Es-QOqsmo+Z-b@T%xJXxXV`LCz>lzG)-oorE|6*gwds1mr z+tsKT64@L_xhvhYaYxhnu7DK19k4LVfDO9(7Ah-Ro*;Jx=so$YZP4lRDC9;p5AtYY^3bz9C@Jd zl5KP$=Tg=PwzVet86Rk&Dp81ajo|(Ai{0gMLkhf*vTAU+Bl>$$FkLzA zcHd#%n!Dv&>e?Vv4w=BKKwdD|OQbMI!{;ryG~Mb@l1@l27%3=|4_QiAxeio(g8PU_ zD+J4Yo0o&xCFdGGpGh>ZPj(Z03H?OziJuKSK#ftD7##1CwgZ}|8^ZKlw9XX9m zrrU->h-kUPj5MnfOikc>YFHkcmBgxMvRbnLTluim@(@zAnV72*cV8Fc{0tNn?~^ZVM>vnS33 zK9AUbZY_A6cN8oAn!2d**q`iO{E2;~PS#D)fJ*0{Q1;j9Z!pdg6r$zkHuaNbPVPv| zH^S0jU*Zj+4)@OnZt+I4tDkTsD>!SA6-d!b(=gfp)s;LK4)V`60!8d5}v(-q+PP$2LjZMJ@U4H2B=-9D2^7 z!swa-)i4b>L)`Q5xvbe2HSfTCAd@4v1XPflgX%vcAZz#>dQ-#u{+Oh`W=c}y@ctd) z7U+6gX|8QBc8kdf<*ZpX3ilq^LEFAOUYvW-`|Q|>fC_MkRwC{ZR@rP$AM0E_r-<_S z<%1Lo?p4bO*fhwwTa11J7v!9;!E&jp4_MAW}yw?9-sW_ z9n(kNTXbm?z&#`FJ@IxOH*eSV7i4er4lAc!+W&#(68rHKPz}?^8<{=*HH+wj?y~nI z_H`0A4jwSIyYrrt-tZI*V;BM)&d^u?CUtU_K8w0oH>t7=UIi4=VW}S6Sy#i8ebQz= zxE`*KN@)ym4gFWIRq&Aoz`pj1Go}cW;K*vhf)K#{$S{6U)33^-MgzKh1+aKg=!H3; z@+q}m+^!jx@s;mBtZub=Yv_xlB-%L?{=&BOUIOuUv|t(YGGdG6*-0jejR*e99`28H zc7l?g9>0Vsp5ls>4}A~W7m;Oo+j=mS2C8Sfsk&PLQ0VpwQ*KR)E4AAdSeR06nlO8{ z+t#~SHbj=P>RhuyNr?GYBZGOoS~*)?8oeLlPta_=uZdR$K3xSv?~i!{jY+J}#vmy( z-#JrNalD5theI1#tdHsXX>bSW2EiNkLy|1#UWO1@oQOz0KD2&&UL}9Py@|?DdR?&? z+v#&QJ+1w$88Fb&)0T2>{8m=eR2@^fT0AbdRj*@gwnN#jFVPr?`&Tlt;Ou>P*ZEEQ zJk!yA#HmV8@Co7&e51AbTRrlPs?%W5C1_wb@^W@`y0%l%mB~`b zORTs3xco zEVbxn<*WfiZiX{Nk5fDSazF0jSxq_*oTSv7Qt@e%x8-z)aQ>Za{aDLHYVx5#z^91! zR^OAPzoPT8E`n#D2}8wK(v7gb%o~5S^kvX4lBE)+;3`8DQ=N_j3n|!Wrc6X*wH!#dWVCvtqcxr1RKN(y*Iu4jv zVkQc`m3Ds;)4CZ8uA{q0t-rP%b6dpuZ7v@_2==9Uh25x$SyC1J5G|OY7+^qF{i0)9 zG`*6c3>WxKb3BizoVG0Mr*flS_3tt)W^`_#X0SmXT6?0BRH-eRY5wC>6@eG_dj7^E zrNyyq_8f5{BR>H@&;E5vb9<%B&!>N6t^PUrnFknY(r=yl?uy}) z7-QYsA%2Rf5u`TSK_(&3s9S0}ysP3(T759-4(6SCPCR9Ku*H@ya2~Pt_Q7}>YaBUu z$t4^I8PLer_V!94MG`@#`{?IW&r+oJk}Crp_4pmi`MSLfS$6$J>SSBEOMo zC+oY_R2aS!AlG7CFY*$sQn_6yvA?M}Qgt#F{|;fHHQVD-z05bchHGkQq8>3pt-4BR zD;|Cn?A(6X?a2)#bkY7j7jJL4{(u`If91wKC7L5kb_eS!zSSDZm7_Cp%3o#Rfs>fMQr8mMO!Vx6Lm0IjzhaEeTO7OQ+L*^EO~8au-r`dSfLCM!RB* zLvP;NJbh20ao}7yUm3Wc*vdKXRmh~IP6NBbR;8fm%marzZ<Pv-10N{*=VMdunn!yq9W^Teh=qr{f5gGJ{TJ@N*&96SZMm+0$W>&Wp<}I@Ie`4 z19RR-vb^4lsXzJL6w9~Vu7Ju;B0kf|ZRLX(=@N#_2g_4Z802i z@G0D&x}e46UFrDMmnX?9HcbrmZEZ#E`>ax|Bpn%JfRnbpnI~JgV$N)`!xB1UMSyPe ziU-h+7aA`J>rbq2W1%)Ve;t-3&@IG7hO06W=Lb(d3A9aAlq2Zq?nK}oIX@S|Z@Puz z3MgynlflXSELNz9zzTzhPGTC{)zRkJ=Xo%Ag7iIjS+}zEJ-qb8+N@>vo}5T;!)%^X z_xpW@+;3YDf`w&d#^y;*v3G}gsxxx6Ow9}P5zq^ay1A;QzPvUvLzXvJb4Fg9Ty?=@ zWN@|h%(|mpNhE_!9&*1E(h@RVX<#(g1=kK98)(xrf69En%ss7LhOl%ZPAo$)i23ng%e*XzQJGxciqUy znY&n>hfWp9wi>xN;i4qRVHUL`*UbJFrt`C>wzoSwE7YcUAW=S7 zZ_k?$^Fd!mAcc)2?VHhAvgYL&aup2FD8U>?X-(0z#F4; zXZUaH5+YSMfuowmAYuEf-SDtnQ6442ji)O2GR>^} zo)k%pqq#xwXZVx~{s${*#)h+z@6qFX-##E-DA%mdmwo9vV%ZF?J#3V?(M_=wZE)2| zN7w%t)~Da^>_13oNFBy-xjNtN;LLtXz6cT)@o!cR&z85vgJ)TK7}(D)P7ts?0LWZU zclv_Td6J_rw<%8vUZ!rCW&lJ;q1eKe5u+G1rMN#P_N#+Xa?H;49{=JEtT1x2*{Sf3 zto=e9`$-do5!Mg1lTXO95l=f3TR#JTb1jnGC_uo}{}nod;*@Y|8{hww_h4N}0^tJ& zbn+S-vnt<*N_&hv^GZ}{FJ3XSVRl0CV7a*9*x1qBE7vK-#8Lx0ZJ-C#hswpEiCicH zO=Q6@A>Zrdsmq5M3*016z0pCWV!b}7_!qjZt^HpH(j0i^JjyCo*nD?apP<}d)Ot6Q zN0UGoR1{bNLXigYmEWDe#Tx#T^7&-BGh}m#rX62plgQ#}iK1Js=hnAxEXzNL4%9sL zqu&`D&Js0#O5qTKZ#>t4H`W{fkY)WRUs$Emss-{CzNmPAdiO~?=~n3$G6Nhej$(lY zFH9p=edyp&aQ7p6xO*I(R3MZxh68Gqt+lWT-zl*uhPw-O$r&nR@PIRcf!-=sOh$g| zH99siAiG#aBFK+=gidBh>X*hE(l8!0&VCUzQJsMhu7&A7=mO;tf}do)?QBLWqYQe? z{pO5u8-ZiJ_3qYrZIDy)z+KT8nFDz2IFDQtkR@|psOKUGPwxA$Dxb#5mp6!MJ3mLF z%jZ$e58?=06B9qy_?MB(nxCEES8xIG^K}hU&kQ0VffLT|L;^m2^=R=srQ-Acb|NFe zrr7bCbVfdkO355snE^xO|)iu;+Wg> zAn<0M0o*hBfcA%{zZVjXZnCWIL;o@bviyXi3b$Us$}sehK0q!Av}BX?`FPLn-lneP zZP$=+`H9-m_LwHoi<2hXdT7m@s0px?O#*X#fSfxityCuAe>pjrq0@y+6-F16l5fr3|SF_X=a{9r)QhctO5$F=#rp?*m0__~lV}Xmn$m@yCFFV}G4z9@0&&H{1nG_8w?C9;_$LxJ zWXq_hnP{A#Sl!NV>TI|lBWtA#QTE@Y>rvqpSW=Fh@QW!tc2Q9bpY6`^}c*ngb$K3M|HP>;ug37a%ZOy7-IUOnB=_&h(uaLiM5#|sJ&&)b3f{}xhb*cC_k1?X9WraQ4R_F2gT?^=RC)& zh*Ri_)@%l=tr5U4fIXrP;+WHZNk3jx0ZA#Kqt#e zSt})S`a_MM9WNZ{T~Fn@Lvp+=*5_0RWdjXs2c<_SWu@w0*l7{6B{-&+g*t)kOFKI@ z&ui0nLkXOw4e@b*HCos*A7Gm~wCq=x#_(6xlLPHF2XCi|19<=oytfT1r1gn|rwUV% zHzEz&GQLFIAd8#RSG>LW*_#T-8Sf88pG-zvUf4tK9~=)L2IiC9M%Y)O+rabb)HG|Z zx_ehuV!M^88ZOV<&&1eARN^@)-0hPtyc|<96 z3VIrI#j!`u>{ljmFv!em0+?nFgok6D;U)ZRqC<>xl)Dg3z?z zUvl@T%*jEx1K*$g)ClI{*MM+8pko6IO-z_xKcJrPzw|l4{?k;3(Ins)B_pfs&pkJC zJd%Z0S6} zxqS|Fr2T5Xar6z1kHu(0c}{H%ee_e={v+cU8A0OUP)>A~O#gwQw}r|&c4&^WesYC{ z!0u-=plaPC6+YkA_+*J$vogM+MNvQI$It75)|fyU*9kW>0w-UJDSG zB__H?$HP+ieP&Z~Hl=>yBBh}eA*J?GLXKZNLJZ^Roq2twRqke~JRZb{y(Jl`qe#C9)1_}(4z4zt8~HurW1A_Wo<*rC%D z4OF*ks*;LrZ1e~5@@kE{a`9rx-iRlFinyFIw8m^ChelzCIymvn3DVMrs4Ud;%}o=( zncU=!{GHsk9QjJoQBbgG*cr6}0N|$odI8i09@*MYnaagK@%d734Jb0%0?!(tIg^5?&m?wd zRA9Esl4`-Cu&%rfmS5@SVmV%ujm6M>U*oD@XKQQC{mneZIujU&f3>{6IK1?#3&pLW1kpg{nq6H zh|N~7Nu&st-uJ1du#IKS!YEQoCdubae&2G&<6xwcuIEaa$oqu`F_xV#o{)Qw{U@L2 zKv;mpEkAW90CXvXtSDIUw4cC`us*hYC_!JvA^Mo zUPfK{G}Sjep<#-7PHy%er_gLk=lt~_-WZ}-6B+sMd)2z|*sA>(exi6=K+1o>!|c#$ zsq775bkT>qBe4G0=`b?2Tc`OS0#U`iL^s-dGg1nMEo=Xy8^0L0NP0)!4Aw8n(`Ns% x6gACWz7Xh}VU+Z-Xq5gfj{gPJJL2~WPWn!m+cWFa{?^V6wZ}5(X(D_N(?!*n3`|_r0Hc?=PQw&*vnU?QTFY zB_MsH|!j$PP;I}?dppoE_gA(4uc!jV&0!l7_;&p2^pxNo>PEcNJv za5_RT$o2Mf!<+r?&EbHH6nMoTsDOa;mN(wv8RNsHpG)`^ymG-S5By8=l9iVXzN_eG%Xg2@Xeq76tTZ*dGh~Lo9vl;Zfs+W#BydUw zCkZ$o1LqWQO$FC9aKlLl*7x9^0q%0}$OMlp@Kk_jHXOjofdePND+j!A{q!8~Jn+s3 z?~~w@4?egS02}8NuulUA=L~QQfm;MzCGd)XhiftT;+zFO&JVyp2mBww?;QByS_1w! zrQlx%{^cMj0|Bo1FjwY@Q8?Hx0cIPF*@-ZRFpPc#bBw{5@tD(5%sClzIfl8WU~V#u zm5Q;_F!wa$BSpqhN>W@2De?TKWR*!ujY;Yylk_X5#~V!L*Gw~;$%4Q8~Mad z@`-kG?yb$a9cHIApZDVZ^U6Xkp<*4rU82O7%}0jjHlK{id@?-wpN*fCHXyXh(bLt* zPc}H-x0e4E&nQ>y%B-(EL=9}RyC%MyX=upHuFhAk&MLbsF0LP-q`XnH78@fT+pKPW zu72MW`|?8ht^tz$iC}ZwLp4tB;Q49K!QCF3@!iB1qOI=?w z7In!}F~ij(18UYUjnbmC!qKhPo%24?8U1x{7o(+?^Zu0Hx81|FuS?bJ0jgBhEMzf< zCgUq7r2OCB(`XkKcN-TL>u5y#dD6D!)5W?`O5)V^>jb)P)GBdy%t$uUMpf$SNV31$ zb||OojAbvMP?T@$h_ZiFLFVHDmbyMhJF|-_)HX3%m=CDI+ID$0^C>kzxprBW)hw(v zr!Gmda);ICoQyhV_oP5+C%?jcG8v+D@9f?Dk*!BxY}dazmrT@64UrP3hlslANK)bq z$67n83eh}OeW&SV@HG95P|bjfqJ7gw$e+`Hxo!4cx`jdK1bJ>YDSpGKLPZ^1cv$ek zIB?0S<#tX?SJCLWdMd{-ME?$hc7A$zBOdIJ)4!KcAwb=VMov)nK;9z>x~rfT1>dS+ zZ6#`2v@`jgbqq)P22H)Tx2CpmM^o1$B+xT6`(v%5xJ(?j#>Q$+rx_R|7TzDZe{J6q zG1*EcU%tE?!kO%^M;3aM6JN*LAKUVb^xz8-Pxo#jR5(-KBeLJvA@-gxNHx0M-ZJLl z;#JwQoh~9V?`UVo#}{6ka@II>++D@%KqGpMdlQ}?9E*wFcf5(#XQnP$Dk5~%iX^>f z%$y;?M0BLp{O3a(-4A?ewryHrrD%cx#Q^%KY1H zNre$ve+vceSLZcNY4U(RBX&)oZn*Py()h)XkE?PL$!bNb{N5FVI2Y%LKEm%yvpyTP z(1P?z~7YxD~Rf<(a@_y` diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..3132450 --- /dev/null +++ b/android/app/src/main/res/values/strings.xml @@ -0,0 +1,4 @@ + + + default_channel_id + \ No newline at end of file diff --git a/ios/Runner/GoogleService-Info.plist b/ios/Runner/GoogleService-Info.plist new file mode 100644 index 0000000..9efcb3f --- /dev/null +++ b/ios/Runner/GoogleService-Info.plist @@ -0,0 +1,30 @@ + + + + + API_KEY + AIzaSyCMbx3GD8XMCI9vdrQvIy6nTr-kiNx2f9k + GCM_SENDER_ID + 598107454568 + PLIST_VERSION + 1 + BUNDLE_ID + com.example.cargo + PROJECT_ID + cargo66 + STORAGE_BUCKET + cargo66.appspot.com + IS_ADS_ENABLED + + IS_ANALYTICS_ENABLED + + IS_APPINVITE_ENABLED + + IS_GCM_ENABLED + + IS_SIGNIN_ENABLED + + GOOGLE_APP_ID + 1:598107454568:ios:3bbcc27922926fe7314fdd + + \ No newline at end of file diff --git a/ios/firebase_app_id_file.json b/ios/firebase_app_id_file.json new file mode 100644 index 0000000..7a96f5a --- /dev/null +++ b/ios/firebase_app_id_file.json @@ -0,0 +1,7 @@ +{ + "file_generated_by": "FlutterFire CLI", + "purpose": "FirebaseAppID & ProjectID for this Firebase app in this directory", + "GOOGLE_APP_ID": "1:598107454568:ios:3bbcc27922926fe7314fdd", + "FIREBASE_PROJECT_ID": "cargo66", + "GCM_SENDER_ID": "598107454568" +} \ No newline at end of file diff --git a/lib/core/utils/download_file.dart b/lib/core/utils/download_file.dart new file mode 100644 index 0000000..8b5da31 --- /dev/null +++ b/lib/core/utils/download_file.dart @@ -0,0 +1,25 @@ +import 'dart:io'; +import 'package:http/http.dart' as http; +import 'package:path_provider/path_provider.dart'; + +Future downloadFile(String url, String filename) async { + final directory = await getApplicationDocumentsDirectory(); + final filePath = '${directory.path}/$filename'; + + // Perform the GET request + final response = await http.get(Uri.parse(url)); + + // Check if the request was successful + if (response.statusCode == 200) { + final file = File(filePath); + + var raf = file.openSync(mode: FileMode.write); + // response.bodyBytes is a List type + raf.writeFromSync(response.bodyBytes); + await raf.close(); + + return filePath; + } else { + throw Exception('Failed to download file'); + } +} diff --git a/lib/core/utils/notification_service.dart b/lib/core/utils/notification_service.dart new file mode 100644 index 0000000..1727667 --- /dev/null +++ b/lib/core/utils/notification_service.dart @@ -0,0 +1,284 @@ +import 'dart:io'; + +import 'package:cargo/core/constants/colors.dart'; +import 'package:firebase_core/firebase_core.dart'; +import 'package:firebase_messaging/firebase_messaging.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter_local_notifications/flutter_local_notifications.dart'; +import 'package:permission_handler/permission_handler.dart'; + +import '../../../firebase_options.dart'; +import 'download_file.dart'; + +class FCMFunctions { + static final FCMFunctions _singleton = FCMFunctions._internal(); + + FCMFunctions._internal(); + + factory FCMFunctions() { + return _singleton; + } + + late FirebaseMessaging messaging; + + late FlutterLocalNotificationsPlugin flip; + + late InitializationSettings initSettings; +//************************************************************************************************************ */ + /// Create a [AndroidNotificationChannel] for heads up notifications + late AndroidNotificationChannel channel; + + /// Initialize the [FlutterLocalNotificationsPlugin] package. + late FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin; + +//************************************************************************************************************ */ + + Future initApp() async { + debugPrint('init firebase'); + + if (Platform.isAndroid) { + if (await Permission.notification.isDenied) { + await Permission.notification.request(); + } + } + + await Firebase.initializeApp( + options: DefaultFirebaseOptions.currentPlatform, + ); + + messaging = FirebaseMessaging.instance; + + if (!kIsWeb) { + channel = const AndroidNotificationChannel( + 'high_importance_channel', // id + 'High Importance Notifications', // title + importance: Importance.high, + ); + + flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); + + /// Create an Android Notification Channel. + /// + /// We use this channel in the `AndroidManifest.xml` file to override the + /// default FCM channel to enable heads up notifications. + await flutterLocalNotificationsPlugin + .resolvePlatformSpecificImplementation() + ?.createNotificationChannel(channel); + + //for IOS Foreground Notification + await messaging.setForegroundNotificationPresentationOptions( + alert: true, + badge: true, + sound: true, + ); + + flip = FlutterLocalNotificationsPlugin(); + var initializationSettingsAndroid = const AndroidInitializationSettings('@mipmap/launcher_icon'); + var initializationSettingsIOs = const DarwinInitializationSettings(); + initSettings = InitializationSettings(android: initializationSettingsAndroid, iOS: initializationSettingsIOs); + } + } + + Future subscribeToTopics(String topic) async { + await messaging.subscribeToTopic(topic); + } + + ///Expire : https://firebase.google.com/docs/cloud-messaging/manage-tokens + Future getFCMToken() async { + final fcmToken = await messaging.getToken(); + debugPrint('Get FCM Token ------->: $fcmToken'); + return fcmToken; + } + + void tokenListener() { + debugPrint('tokenListener'); + messaging.onTokenRefresh.listen((fcmToken) { + debugPrint('Listen FCM Token ------->: $fcmToken'); + // If necessary send token to application server. + }).onError((err) { + debugPrint('tokenListener err $err'); + }); + } + + /// IOS + Future iosWebPermission() async { + if (Platform.isIOS || kIsWeb) { + NotificationSettings settings = await messaging.requestPermission(); + } + } + + ///Foreground messages + /// + ///To handle messages while your application is in the foreground, listen to the onMessage stream. + void foreGroundMessageListener() { + FirebaseMessaging.onMessage.listen(_onMessageHandler); + FirebaseMessaging.onMessageOpenedApp.listen(_onMessageOpenedApp); + } + + // foreground + Future _onMessageHandler(RemoteMessage message) async { + debugPrint('onMessageHandler'); + _showNotificationViaFBConsole(message); + // fcmFunctions._showNotification(message); + } + + // FLUTTER_NOTIFICATION_CLICK + + // background (app minimized) + Future _onMessageOpenedApp(RemoteMessage message) async => _performClickAction(message); + + Future _showNotification(RemoteMessage message) async { + final RemoteNotification? notification = message.notification; + if (notification == null) return; + + final String? imgUrl = _getImageUrl(notification); + + debugPrint('==> imgUrl: $imgUrl '); + + BigPictureStyleInformation? styleInformation; + if (imgUrl != null) { + final largeIconPath = await downloadFile(imgUrl, 'largeIcon'); + final bigPicturePath = await downloadFile(imgUrl, 'bigPicture'); + + styleInformation = BigPictureStyleInformation( + FilePathAndroidBitmap(bigPicturePath), + largeIcon: FilePathAndroidBitmap(largeIconPath), + ); + } + + try { + var androidPlatformChannelSpecifics = AndroidNotificationDetails( + channel.id, + channel.name, + icon: '@mipmap/launcher_icon', + channelDescription: channel.description, + importance: Importance.max, + priority: Priority.high, + color: AppColors.primary, + styleInformation: styleInformation, + ); + var iOSPlatformChannelSpecifics = const DarwinNotificationDetails(); + + var platformChannelSpecifics = NotificationDetails( + android: androidPlatformChannelSpecifics, + iOS: iOSPlatformChannelSpecifics, + ); + + FlutterLocalNotificationsPlugin flip = FlutterLocalNotificationsPlugin(); + await flip.show(0, notification.title, notification.body, platformChannelSpecifics, payload: 'Default_Sound'); + } catch (e) { + debugPrint('error $e'); + } + } + + Future _showNotificationViaFBConsole(RemoteMessage message) async { + final RemoteNotification? notification = message.notification; + if (notification == null) return; + + final String? imgUrl = _getImageUrl(notification); + + debugPrint('==> imgUrl: $imgUrl '); + + BigPictureStyleInformation? styleInformation; + if (imgUrl != null) { + final largeIconPath = await downloadFile(imgUrl, 'largeIcon'); + final bigPicturePath = await downloadFile(imgUrl, 'bigPicture'); + + styleInformation = BigPictureStyleInformation( + FilePathAndroidBitmap(bigPicturePath), + largeIcon: FilePathAndroidBitmap(largeIconPath), + ); + } + + var androidPlatformChannelSpecifics = AndroidNotificationDetails( + channel.id, + channel.name, + icon: '@mipmap/launcher_icon', + channelDescription: channel.description, + // importance: Importance.max, + priority: Priority.high, + // color: ThemeColor.mainColor, + styleInformation: styleInformation, + ); + var iOSPlatformChannelSpecifics = const DarwinNotificationDetails(); + + var platformChannelSpecifics = NotificationDetails( + android: androidPlatformChannelSpecifics, + iOS: iOSPlatformChannelSpecifics, + ); + + flip.initialize( + initSettings, + // onDidReceiveBackgroundNotificationResponse: (details) { + // debugPrint('==> ${details.payload}'); + // }, + onDidReceiveNotificationResponse: (details) { + debugPrint('onDidReceiveNotificationResponse'); + // _performClickAction(message); + }, + ); + await flip.show(0, notification.title, notification.body, platformChannelSpecifics, payload: 'Default_Sound'); + } + + Future _performClickAction(RemoteMessage message) async { + // if (message.data['type'] == 'product') { + // final int productId = int.parse(message.data['id']); + // final ProductModel? model = await ProductApi.getProductById(productId); + // if (model != null) Get.to(() => ProductDetailsPage(model: model)); + // } else if (message.data['type'] == 'filter') { + // message.data.remove('type'); + // navigateToProductListScreen(message.data, false); + // } else { + // open dialog + // if (message.notification == null) return; + + // Get.to( + // () => NotificationPage(title: message.notification!.title ?? '', data: message.notification!.body ?? ''), + // ); + // } + } + + String? _getImageUrl(RemoteNotification notification) { + if (Platform.isIOS && notification.apple != null) return notification.apple?.imageUrl; + if (Platform.isAndroid && notification.android != null) return notification.android?.imageUrl; + return null; + } +} + +final fcmFunctions = FCMFunctions(); + +// backgroundHandler must be on top and separated +Future onBackgroundHandler(RemoteMessage message) async { + // fcmFunctions._showNotification(message); + fcmFunctions._showNotificationViaFBConsole(message); +} + +Future initFCMFunctions() async { + await fcmFunctions.initApp(); + await fcmFunctions.iosWebPermission(); + + FirebaseMessaging.onBackgroundMessage(onBackgroundHandler); + + await fcmFunctions.getFCMToken(); + fcmFunctions.tokenListener(); + fcmFunctions.foreGroundMessageListener(); + await fcmFunctions.subscribeToTopics('notifications'); +} + +/* final http.Response response = await http.get(Uri.parse(URL)); + BigPictureStyleInformation bigPictureStyleInformation = + BigPictureStyleInformation( + ByteArrayAndroidBitmap.fromBase64String(base64Encode(image)), + largeIcon: ByteArrayAndroidBitmap.fromBase64String(base64Encode(image)), + ); + flutterLocalNotificationsPlugin.show( + Random().nextInt(1000), + title, + description, + NotificationDetails( + android: AndroidNotificationDetails(channel.id, channel.name, + channelDescription: channel.description, + importance: Importance.high, + styleInformation: bigPictureStyleInformation), + ), + ); */ diff --git a/lib/core/utils/utils.dart b/lib/core/utils/utils.dart index fd7bd01..297f108 100644 --- a/lib/core/utils/utils.dart +++ b/lib/core/utils/utils.dart @@ -3,3 +3,4 @@ export 'keyboard.dart'; export 'error_util.dart'; export 'http_override.dart'; export 'date_util.dart'; +export 'notification_service.dart'; diff --git a/lib/firebase_options.dart b/lib/firebase_options.dart new file mode 100644 index 0000000..64426b2 --- /dev/null +++ b/lib/firebase_options.dart @@ -0,0 +1,68 @@ +// File generated by FlutterFire CLI. +// ignore_for_file: lines_longer_than_80_chars, avoid_classes_with_only_static_members +import 'package:firebase_core/firebase_core.dart' show FirebaseOptions; +import 'package:flutter/foundation.dart' + show defaultTargetPlatform, kIsWeb, TargetPlatform; + +/// Default [FirebaseOptions] for use with your Firebase apps. +/// +/// Example: +/// ```dart +/// import 'firebase_options.dart'; +/// // ... +/// await Firebase.initializeApp( +/// options: DefaultFirebaseOptions.currentPlatform, +/// ); +/// ``` +class DefaultFirebaseOptions { + static FirebaseOptions get currentPlatform { + if (kIsWeb) { + throw UnsupportedError( + 'DefaultFirebaseOptions have not been configured for web - ' + 'you can reconfigure this by running the FlutterFire CLI again.', + ); + } + switch (defaultTargetPlatform) { + case TargetPlatform.android: + return android; + case TargetPlatform.iOS: + return ios; + case TargetPlatform.macOS: + throw UnsupportedError( + 'DefaultFirebaseOptions have not been configured for macos - ' + 'you can reconfigure this by running the FlutterFire CLI again.', + ); + case TargetPlatform.windows: + throw UnsupportedError( + 'DefaultFirebaseOptions have not been configured for windows - ' + 'you can reconfigure this by running the FlutterFire CLI again.', + ); + case TargetPlatform.linux: + throw UnsupportedError( + 'DefaultFirebaseOptions have not been configured for linux - ' + 'you can reconfigure this by running the FlutterFire CLI again.', + ); + default: + throw UnsupportedError( + 'DefaultFirebaseOptions are not supported for this platform.', + ); + } + } + + static const FirebaseOptions android = FirebaseOptions( + apiKey: 'AIzaSyB4aGhjQIDs6neCWrrITI6iujKhKm2Y9cg', + appId: '1:598107454568:android:b2b6e38663f71e9e314fdd', + messagingSenderId: '598107454568', + projectId: 'cargo66', + storageBucket: 'cargo66.appspot.com', + ); + + static const FirebaseOptions ios = FirebaseOptions( + apiKey: 'AIzaSyCMbx3GD8XMCI9vdrQvIy6nTr-kiNx2f9k', + appId: '1:598107454568:ios:3bbcc27922926fe7314fdd', + messagingSenderId: '598107454568', + projectId: 'cargo66', + storageBucket: 'cargo66.appspot.com', + iosBundleId: 'com.example.cargo', + ); +} diff --git a/lib/main.dart b/lib/main.dart index f6c2a88..2650f52 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,6 +1,10 @@ +import 'dart:developer'; import 'dart:io'; +import 'package:cargo/firebase_options.dart'; import 'package:easy_localization/easy_localization.dart'; +import 'package:firebase_core/firebase_core.dart'; +import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -10,6 +14,21 @@ import 'package:flutter_phoenix/flutter_phoenix.dart'; import 'core/core.dart'; import 'di/di.dart' as di; +Future _initFBInitials() async { + try { + await initFCMFunctions(); + + // await Firebase.initializeApp( + // options: DefaultFirebaseOptions.currentPlatform, + // ); + // final fcmToken = await FirebaseMessaging.instance.getToken(); + // await FirebaseMessaging.instance.setAutoInitEnabled(true); + // log('FCMToken $fcmToken'); + } catch (e) { + debugPrint('FCM error: $e'); + } +} + Future main() async { // WidgetsFlutterBinding.ensureInitialized(); @@ -18,6 +37,8 @@ Future main() async { await EasyLocalization.ensureInitialized(); + _initFBInitials(); + await di.init(); Bloc.observer = MyBlocObserver(); diff --git a/pubspec.lock b/pubspec.lock index 10abb6c..e1c2928 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,6 +1,14 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + _flutterfire_internals: + dependency: transitive + description: + name: _flutterfire_internals + sha256: f5628cd9c92ed11083f425fd1f8f1bc60ecdda458c81d73b143aeda036c35fe7 + url: "https://pub.dev" + source: hosted + version: "1.3.16" another_stepper: dependency: "direct main" description: @@ -129,6 +137,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.10.1" + dbus: + dependency: transitive + description: + name: dbus + sha256: "365c771ac3b0e58845f39ec6deebc76e3276aa9922b0cc60840712094d9047ac" + url: "https://pub.dev" + source: hosted + version: "0.7.10" easy_localization: dependency: "direct main" description: @@ -177,6 +193,54 @@ packages: url: "https://pub.dev" source: hosted version: "7.0.0" + firebase_core: + dependency: "direct main" + description: + name: firebase_core + sha256: "96607c0e829a581c2a483c658f04e8b159964c3bae2730f73297070bc85d40bb" + url: "https://pub.dev" + source: hosted + version: "2.24.2" + firebase_core_platform_interface: + dependency: transitive + description: + name: firebase_core_platform_interface + sha256: f7d7180c7f99babd4b4c517754d41a09a4943a0f7a69b65c894ca5c68ba66315 + url: "https://pub.dev" + source: hosted + version: "5.2.1" + firebase_core_web: + dependency: transitive + description: + name: firebase_core_web + sha256: d585bdf3c656c3f7821ba1bd44da5f13365d22fcecaf5eb75c4295246aaa83c0 + url: "https://pub.dev" + source: hosted + version: "2.10.0" + firebase_messaging: + dependency: "direct main" + description: + name: firebase_messaging + sha256: "980259425fa5e2afc03e533f33723335731d21a56fd255611083bceebf4373a8" + url: "https://pub.dev" + source: hosted + version: "14.7.10" + firebase_messaging_platform_interface: + dependency: transitive + description: + name: firebase_messaging_platform_interface + sha256: "54e283a0e41d81d854636ad0dad73066adc53407a60a7c3189c9656e2f1b6107" + url: "https://pub.dev" + source: hosted + version: "4.5.18" + firebase_messaging_web: + dependency: transitive + description: + name: firebase_messaging_web + sha256: "90dc7ed885e90a24bb0e56d661d4d2b5f84429697fd2cbb9e5890a0ca370e6f4" + url: "https://pub.dev" + source: hosted + version: "3.5.18" flutter: dependency: "direct main" description: flutter @@ -206,6 +270,30 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.2" + flutter_local_notifications: + dependency: "direct main" + description: + name: flutter_local_notifications + sha256: c500d5d9e7e553f06b61877ca6b9c8b92c570a4c8db371038702e8ce57f8a50f + url: "https://pub.dev" + source: hosted + version: "17.2.2" + flutter_local_notifications_linux: + dependency: transitive + description: + name: flutter_local_notifications_linux + sha256: c49bd06165cad9beeb79090b18cd1eb0296f4bf4b23b84426e37dd7c027fc3af + url: "https://pub.dev" + source: hosted + version: "4.0.1" + flutter_local_notifications_platform_interface: + dependency: transitive + description: + name: flutter_local_notifications_platform_interface + sha256: "85f8d07fe708c1bdcf45037f2c0109753b26ae077e9d9e899d55971711a4ea66" + url: "https://pub.dev" + source: hosted + version: "7.2.0" flutter_localizations: dependency: transitive description: flutter @@ -309,6 +397,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.19.0" + js: + dependency: transitive + description: + name: js + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + url: "https://pub.dev" + source: hosted + version: "0.6.7" json_annotation: dependency: transitive description: @@ -429,6 +525,30 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.1" + path_provider: + dependency: "direct main" + description: + name: path_provider + sha256: fec0d61223fba3154d87759e3cc27fe2c8dc498f6386c6d6fc80d1afdd1bf378 + url: "https://pub.dev" + source: hosted + version: "2.1.4" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + sha256: "6f01f8e37ec30b07bc424b4deabac37cacb1bc7e2e515ad74486039918a37eb7" + url: "https://pub.dev" + source: hosted + version: "2.2.10" + path_provider_foundation: + dependency: transitive + description: + name: path_provider_foundation + sha256: f234384a3fdd67f989b4d54a5d73ca2a6c422fa55ae694381ae0f4375cd1ea16 + url: "https://pub.dev" + source: hosted + version: "2.4.0" path_provider_linux: dependency: transitive description: @@ -453,6 +573,54 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.0" + permission_handler: + dependency: "direct main" + description: + name: permission_handler + sha256: "18bf33f7fefbd812f37e72091a15575e72d5318854877e0e4035a24ac1113ecb" + url: "https://pub.dev" + source: hosted + version: "11.3.1" + permission_handler_android: + dependency: transitive + description: + name: permission_handler_android + sha256: "76e4ab092c1b240d31177bb64d2b0bea43f43d0e23541ec866151b9f7b2490fa" + url: "https://pub.dev" + source: hosted + version: "12.0.12" + permission_handler_apple: + dependency: transitive + description: + name: permission_handler_apple + sha256: e6f6d73b12438ef13e648c4ae56bd106ec60d17e90a59c4545db6781229082a0 + url: "https://pub.dev" + source: hosted + version: "9.4.5" + permission_handler_html: + dependency: transitive + description: + name: permission_handler_html + sha256: af26edbbb1f2674af65a8f4b56e1a6f526156bc273d0e65dd8075fab51c78851 + url: "https://pub.dev" + source: hosted + version: "0.1.3+2" + permission_handler_platform_interface: + dependency: transitive + description: + name: permission_handler_platform_interface + sha256: fe0ffe274d665be8e34f9c59705441a7d248edebbe5d9e3ec2665f88b79358ea + url: "https://pub.dev" + source: hosted + version: "4.2.2" + permission_handler_windows: + dependency: transitive + description: + name: permission_handler_windows + sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e" + url: "https://pub.dev" + source: hosted + version: "0.2.1" petitparser: dependency: transitive description: @@ -610,6 +778,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.7.0" + timezone: + dependency: transitive + description: + name: timezone + sha256: "2236ec079a174ce07434e89fcd3fcda430025eb7692244139a9cf54fdcf1fc7d" + url: "https://pub.dev" + source: hosted + version: "0.9.4" typed_data: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index cdbe00c..071cb2e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -31,6 +31,11 @@ dependencies: flutter_native_splash: ^2.4.1 url_launcher: ^6.3.0 another_stepper: ^1.2.2 + firebase_messaging: ^14.7.10 + firebase_core: ^2.24.2 + flutter_local_notifications: ^17.2.2 + path_provider: ^2.1.4 + permission_handler: ^11.3.1 dev_dependencies: flutter_test: