forked from eatvio/eatvio_app
feat(hp): Issue-660
This commit is contained in:
1
android/app/agconnect-services.json
Normal file
1
android/app/agconnect-services.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"agcgw":{"url":"connect-drru.hispace.dbankcloud.ru","backurl":"connect-drru.hispace.dbankcloud.cn","websocketurl":"connect-ws-drru.hispace.dbankcloud.ru","websocketbackurl":"connect-ws-drru.hispace.dbankcloud.cn"},"agcgw_all":{"SG":"connect-dra.dbankcloud.cn","SG_back":"connect-dra.hispace.hicloud.com","CN":"connect-drcn.dbankcloud.cn","CN_back":"connect-drcn.hispace.hicloud.com","RU":"connect-drru.hispace.dbankcloud.ru","RU_back":"connect-drru.hispace.dbankcloud.cn","DE":"connect-dre.dbankcloud.cn","DE_back":"connect-dre.hispace.hicloud.com"},"websocketgw_all":{"SG":"connect-ws-dra.hispace.dbankcloud.cn","SG_back":"connect-ws-dra.hispace.dbankcloud.com","CN":"connect-ws-drcn.hispace.dbankcloud.cn","CN_back":"connect-ws-drcn.hispace.dbankcloud.com","RU":"connect-ws-drru.hispace.dbankcloud.ru","RU_back":"connect-ws-drru.hispace.dbankcloud.cn","DE":"connect-ws-dre.hispace.dbankcloud.cn","DE_back":"connect-ws-dre.hispace.dbankcloud.com"},"client":{"cp_id":"20007000036693451","product_id":"461323198429446894","client_id":"1595824543740483264","client_secret":"2A1727B0D31AA9BE1F5D9E8A5CDA1A67B9EF084AC9FB68D6C633A3CCB08ECDEE","project_id":"461323198429446894","app_id":"113238569","api_key":"DQEDAJNRITp9M3uc1rPHyT8PzLc7bnVcKJAeavZZk0TQNMx9ifvBebr+JOmZe9tEvjnLwv7c1hAHXmPGR/gWG86iABDrCVotq+NGnw==","package_name":"com.eatvioapp.app"},"oauth_client":{"client_id":"113238569","client_type":1},"app_info":{"app_id":"113238569","package_name":"com.eatvioapp.app"},"service":{"analytics":{"collector_url":"datacollector-drru.dt.dbankcloud.ru,datacollector-drru.dt.hicloud.com","collector_url_cn":"datacollector-drcn.dt.hicloud.com,datacollector-drcn.dt.dbankcloud.cn","collector_url_de":"datacollector-dre.dt.hicloud.com,datacollector-dre.dt.dbankcloud.cn","collector_url_ru":"datacollector-drru.dt.dbankcloud.ru,datacollector-drru.dt.hicloud.com","collector_url_sg":"datacollector-dra.dt.hicloud.com,datacollector-dra.dt.dbankcloud.cn","resource_id":"p1","channel_id":""},"ml":{"mlservice_url":"ml-api-drru.ai.dbankcloud.ru,ml-api-drru.ai.dbankcloud.cn"},"cloudstorage":{"storage_url":"https://agc-storage-drcn.platform.dbankcloud.cn","storage_url_ru":"https://agc-storage-drru.cloud.huawei.ru","storage_url_sg":"https://ops-dra.agcstorage.link","storage_url_de":"https://ops-dre.agcstorage.link","storage_url_cn":"https://agc-storage-drcn.platform.dbankcloud.cn","storage_url_ru_back":"https://agc-storage-drru.cloud.huawei.ru","storage_url_sg_back":"https://agc-storage-dra.cloud.huawei.asia","storage_url_de_back":"https://agc-storage-dre.cloud.huawei.eu","storage_url_cn_back":"https://agc-storage-drcn.cloud.huawei.com.cn"},"search":{"url":"https://search-drru.cloud.huawei.ru"},"edukit":{"edu_url":"edukit.cloud.huawei.com.cn","dh_url":"edukit.cloud.huawei.com.cn"}},"region":"RU","configuration_version":"3.0","appInfos":[{"package_name":"com.eatvioapp.app","client":{"app_id":"113238569"},"app_info":{"package_name":"com.eatvioapp.app","app_id":"113238569"},"oauth_client":{"client_type":1,"client_id":"113238569"}}]}
|
||||||
@@ -5,6 +5,7 @@ plugins {
|
|||||||
// END: FlutterFire Configuration
|
// END: FlutterFire Configuration
|
||||||
id "kotlin-android"
|
id "kotlin-android"
|
||||||
id "dev.flutter.flutter-gradle-plugin"
|
id "dev.flutter.flutter-gradle-plugin"
|
||||||
|
id 'com.huawei.agconnect'
|
||||||
}
|
}
|
||||||
|
|
||||||
def keystoreProperties = new Properties()
|
def keystoreProperties = new Properties()
|
||||||
@@ -35,7 +36,10 @@ android {
|
|||||||
targetSdk = flutter.targetSdkVersion
|
targetSdk = flutter.targetSdkVersion
|
||||||
versionCode = flutter.versionCode
|
versionCode = flutter.versionCode
|
||||||
versionName = flutter.versionName
|
versionName = flutter.versionName
|
||||||
manifestPlaceholders = [YANDEX_CLIENT_ID: yandexClientId]
|
manifestPlaceholders = [
|
||||||
|
YANDEX_CLIENT_ID: yandexClientId,
|
||||||
|
applicationName: "io.flutter.app.FlutterApplication"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
signingConfigs {
|
signingConfigs {
|
||||||
@@ -50,6 +54,9 @@ android {
|
|||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
signingConfig signingConfigs.release
|
signingConfig signingConfigs.release
|
||||||
|
minifyEnabled true
|
||||||
|
shrinkResources true
|
||||||
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||||
}
|
}
|
||||||
debug {
|
debug {
|
||||||
signingConfig signingConfigs.debug
|
signingConfig signingConfigs.debug
|
||||||
@@ -60,6 +67,14 @@ android {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation 'com.huawei.hms:push:6.13.0.300'
|
||||||
|
// Huawei Analytics dependency to satisfy com.huawei.hianalytics.* references during R8
|
||||||
|
implementation 'com.huawei.hms:hianalytics:6.13.0.300'
|
||||||
|
// BouncyCastle provider required by Huawei secure utils used transitively by HMS
|
||||||
|
implementation 'org.bouncycastle:bcprov-jdk15to18:1.78.1'
|
||||||
|
}
|
||||||
|
|
||||||
flutter {
|
flutter {
|
||||||
source = "../.."
|
source = "../.."
|
||||||
}
|
}
|
||||||
|
|||||||
21
android/app/proguard-rules.pro
vendored
Normal file
21
android/app/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
-keep class com.huawei.** { *; }
|
||||||
|
-dontwarn com.huawei.**
|
||||||
|
|
||||||
|
-keep class org.bouncycastle.** { *; }
|
||||||
|
-dontwarn org.bouncycastle.**
|
||||||
|
|
||||||
|
-keep class io.flutter.** { *; }
|
||||||
|
-dontwarn io.flutter.**
|
||||||
|
|
||||||
|
-keep class kotlinx.coroutines.** { *; }
|
||||||
|
-dontwarn kotlinx.coroutines.**
|
||||||
|
|
||||||
|
-keep class **.R$* { *; }
|
||||||
|
-keepclassmembers class ** { @androidx.annotation.Keep *; }
|
||||||
|
-keep @androidx.annotation.Keep class * { *; }
|
||||||
|
|
||||||
|
-keep public class * extends android.app.Application
|
||||||
|
-keep public class * extends android.content.ContentProvider
|
||||||
|
|
||||||
|
-keep class * implements android.os.Parcelable { *; }
|
||||||
|
-keepclassmembers enum * { *; }
|
||||||
@@ -11,6 +11,16 @@
|
|||||||
android:usesCleartextTraffic="true"
|
android:usesCleartextTraffic="true"
|
||||||
android:name="${applicationName}"
|
android:name="${applicationName}"
|
||||||
android:icon="@mipmap/ic_launcher">
|
android:icon="@mipmap/ic_launcher">
|
||||||
|
<service
|
||||||
|
android:name=".HmsPushService"
|
||||||
|
android:exported="false">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="com.huawei.push.action.MESSAGING_EVENT" />
|
||||||
|
</intent-filter>
|
||||||
|
</service>
|
||||||
|
<meta-data
|
||||||
|
android:name="push_kit_auto_init_enabled"
|
||||||
|
android:value="true" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package com.eatvioapp.app
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import com.huawei.hms.push.HmsMessageService
|
||||||
|
import com.huawei.hms.push.RemoteMessage
|
||||||
|
|
||||||
|
class HmsPushService : HmsMessageService() {
|
||||||
|
override fun onNewToken(token: String?) {
|
||||||
|
super.onNewToken(token)
|
||||||
|
Log.i("HMS", "onNewToken: ${token ?: "null"}")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onMessageReceived(message: RemoteMessage?) {
|
||||||
|
super.onMessageReceived(message)
|
||||||
|
Log.i("HMS", "onMessageReceived: ${message?.data}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1,6 +1,71 @@
|
|||||||
package com.eatvioapp.app
|
package com.eatvioapp.app
|
||||||
|
|
||||||
|
import android.content.pm.ApplicationInfo
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.os.Bundle
|
||||||
import io.flutter.embedding.android.FlutterActivity
|
import io.flutter.embedding.android.FlutterActivity
|
||||||
|
import io.flutter.embedding.engine.FlutterEngine
|
||||||
|
import io.flutter.plugin.common.MethodChannel
|
||||||
|
import com.huawei.agconnect.config.AGConnectServicesConfig
|
||||||
|
import com.huawei.hms.aaid.HmsInstanceId
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class MainActivity: FlutterActivity() {
|
class MainActivity: FlutterActivity() {
|
||||||
|
private val channelName = "com.eatvioapp/hms_push"
|
||||||
|
|
||||||
|
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
|
||||||
|
super.configureFlutterEngine(flutterEngine)
|
||||||
|
|
||||||
|
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, channelName)
|
||||||
|
.setMethodCallHandler { call, result ->
|
||||||
|
when (call.method) {
|
||||||
|
"getHuaweiToken" -> {
|
||||||
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
try {
|
||||||
|
// Try to read appId from agconnect-services.json
|
||||||
|
var appId: String? = try {
|
||||||
|
AGConnectServicesConfig.fromContext(applicationContext)
|
||||||
|
.getString("client/app_id")
|
||||||
|
} catch (_: Exception) {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback to manifest meta-data if needed
|
||||||
|
if (appId.isNullOrBlank()) {
|
||||||
|
try {
|
||||||
|
val pm: PackageManager = applicationContext.packageManager
|
||||||
|
val ai: ApplicationInfo = pm.getApplicationInfo(applicationContext.packageName, PackageManager.GET_META_DATA)
|
||||||
|
val raw = ai.metaData?.getString("com.huawei.hms.client.appid")
|
||||||
|
if (!raw.isNullOrBlank()) {
|
||||||
|
appId = raw.removePrefix("appid=")
|
||||||
|
}
|
||||||
|
} catch (_: Exception) {
|
||||||
|
// ignore and handle below
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (appId.isNullOrBlank()) {
|
||||||
|
runOnUiThread {
|
||||||
|
result.error("HMS_TOKEN_ERROR", "Missing Huawei appId. Ensure agconnect-services.json or manifest meta-data is configured.", null)
|
||||||
|
}
|
||||||
|
return@launch
|
||||||
|
}
|
||||||
|
val token = HmsInstanceId.getInstance(applicationContext)
|
||||||
|
.getToken(appId, "HCM")
|
||||||
|
runOnUiThread {
|
||||||
|
result.success(token)
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
runOnUiThread {
|
||||||
|
result.error("HMS_TOKEN_ERROR", e.message, null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> result.notImplemented()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,16 @@
|
|||||||
|
buildscript {
|
||||||
|
repositories {
|
||||||
|
google()
|
||||||
|
mavenCentral()
|
||||||
|
maven { url 'https://developer.huawei.com/repo/' }
|
||||||
|
gradlePluginPortal()
|
||||||
|
}
|
||||||
|
dependencies {
|
||||||
|
classpath 'com.android.tools.build:gradle:8.12.0'
|
||||||
|
classpath 'com.huawei.agconnect:agcp:1.9.1.301'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
@@ -14,6 +27,32 @@ subprojects {
|
|||||||
project.evaluationDependsOn(":app")
|
project.evaluationDependsOn(":app")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Temporary safeguard: set missing namespaces for Android library modules based on their manifest package
|
||||||
|
subprojects { Project subproject ->
|
||||||
|
subproject.pluginManager.withPlugin('com.android.library') {
|
||||||
|
def androidExt = subproject.extensions.findByName('android')
|
||||||
|
if (androidExt != null) {
|
||||||
|
def hasNamespaceProp = androidExt.hasProperty('namespace')
|
||||||
|
def currentNamespace = hasNamespaceProp ? androidExt.namespace : null
|
||||||
|
if (hasNamespaceProp && !currentNamespace) {
|
||||||
|
def manifestFile = file("${subproject.projectDir}/src/main/AndroidManifest.xml")
|
||||||
|
if (manifestFile.exists()) {
|
||||||
|
try {
|
||||||
|
def manifest = new groovy.xml.XmlSlurper().parse(manifestFile)
|
||||||
|
def manifestPackage = manifest.@package?.text()
|
||||||
|
if (manifestPackage) {
|
||||||
|
androidExt.namespace = manifestPackage
|
||||||
|
subproject.logger.lifecycle("[namespace-fix] Set namespace for ${subproject.path} to '${manifestPackage}' from AndroidManifest.xml")
|
||||||
|
}
|
||||||
|
} catch (Throwable t) {
|
||||||
|
subproject.logger.warn("[namespace-fix] Failed to read manifest for ${subproject.path}: ${t.message}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
tasks.register("clean", Delete) {
|
tasks.register("clean", Delete) {
|
||||||
delete rootProject.buildDir
|
delete rootProject.buildDir
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -12,6 +12,7 @@ pluginManagement {
|
|||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
maven { url 'https://developer.huawei.com/repo/' }
|
||||||
gradlePluginPortal()
|
gradlePluginPortal()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,28 +1,27 @@
|
|||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
import 'package:eatvio_app/core/utils/toasts.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
import 'package:device_info_plus/device_info_plus.dart';
|
import 'package:device_info_plus/device_info_plus.dart';
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:eatvio_app/core/locator_service.dart';
|
import 'package:eatvio_app/core/locator_service.dart';
|
||||||
import 'package:eatvio_app/core/token_storage.dart';
|
import 'package:eatvio_app/core/token_storage.dart';
|
||||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||||
import 'package:huawei_push/huawei_push.dart';
|
import 'package:flutter/services.dart' show MethodChannel, PlatformException;
|
||||||
|
|
||||||
class FirebaseApi {
|
class FirebaseApi {
|
||||||
final _firebaseMessaging = FirebaseMessaging.instance;
|
final _firebaseMessaging = FirebaseMessaging.instance;
|
||||||
|
|
||||||
Future<String?> getToken() async {
|
Future<String?> getToken() async {
|
||||||
await _firebaseMessaging.requestPermission();
|
String? token;
|
||||||
|
|
||||||
String? token = await _firebaseMessaging.getToken();
|
if (await _isHuaweiDevice()) {
|
||||||
|
token = await _getHuaweiPushTokenNative();
|
||||||
if (token == null && Platform.isAndroid) {
|
} else {
|
||||||
final isHuawei = await _isHuaweiDevice();
|
await _firebaseMessaging.requestPermission();
|
||||||
if (isHuawei) {
|
token = await _firebaseMessaging.getToken();
|
||||||
token = await _getHuaweiPushToken();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,10 +29,11 @@ class FirebaseApi {
|
|||||||
if (await TokenStorage.haveTokenInStorage()) {
|
if (await TokenStorage.haveTokenInStorage()) {
|
||||||
try {
|
try {
|
||||||
final deviceInfo = DeviceInfoPlugin();
|
final deviceInfo = DeviceInfoPlugin();
|
||||||
|
final isHuawei = Platform.isAndroid ? await _isHuaweiDevice() : false;
|
||||||
await sl<Dio>().post(
|
await sl<Dio>().post(
|
||||||
'/api/profile/notification/token/register',
|
'/api/profile/notification/token/register',
|
||||||
data: {
|
data: {
|
||||||
'platform': Platform.isIOS ? 'ios' : 'android',
|
'platform': Platform.isIOS ? 'ios' : (isHuawei ? 'huawei' : 'android'),
|
||||||
'hw_id': Platform.isIOS ? (await deviceInfo.iosInfo).identifierForVendor : (await deviceInfo.androidInfo).id,
|
'hw_id': Platform.isIOS ? (await deviceInfo.iosInfo).identifierForVendor : (await deviceInfo.androidInfo).id,
|
||||||
'token': await getToken(),
|
'token': await getToken(),
|
||||||
},
|
},
|
||||||
@@ -47,33 +47,27 @@ class FirebaseApi {
|
|||||||
Future<bool> _isHuaweiDevice() async {
|
Future<bool> _isHuaweiDevice() async {
|
||||||
if (!Platform.isAndroid) return false;
|
if (!Platform.isAndroid) return false;
|
||||||
try {
|
try {
|
||||||
final android = await DeviceInfoPlugin().androidInfo;
|
final info = await DeviceInfoPlugin().androidInfo;
|
||||||
final brand = android.brand.toLowerCase();
|
final brand = info.brand.toLowerCase();
|
||||||
final manufacturer = android.manufacturer.toLowerCase();
|
final manufacturer = info.manufacturer.toLowerCase();
|
||||||
return brand.contains('huawei') || manufacturer.contains('huawei') || brand.contains('honor') || manufacturer.contains('honor');
|
return brand.contains('huawei') || brand.contains('honor') || manufacturer.contains('huawei') || manufacturer.contains('honor');
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String?> _getHuaweiPushToken() async {
|
Future<String?> _getHuaweiPushTokenNative() async {
|
||||||
try {
|
try {
|
||||||
await Push.turnOnPush();
|
const channel = MethodChannel('com.eatvioapp/hms_push');
|
||||||
|
final String? token = await channel.invokeMethod<String>('getHuaweiToken');
|
||||||
String? resolvedToken;
|
return token;
|
||||||
final sub = Push.getTokenStream.listen((t) => resolvedToken ??= t, onError: (_) {});
|
} on PlatformException catch (e, st) {
|
||||||
|
showErrorToast('$e $st');
|
||||||
Push.getToken('');
|
log(e.toString(), stackTrace: st);
|
||||||
|
return null;
|
||||||
final started = DateTime.now();
|
|
||||||
while (resolvedToken == null && DateTime.now().difference(started).inSeconds < 5) {
|
|
||||||
await Future<void>.delayed(const Duration(milliseconds: 100));
|
|
||||||
}
|
|
||||||
|
|
||||||
await sub.cancel();
|
|
||||||
return resolvedToken;
|
|
||||||
} catch (e, st) {
|
} catch (e, st) {
|
||||||
log('Huawei Push token error: $e', stackTrace: st);
|
showErrorToast('$e $st');
|
||||||
|
log(e.toString(), stackTrace: st);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,7 +74,6 @@ dependencies:
|
|||||||
flutter_dotenv: ^5.2.1
|
flutter_dotenv: ^5.2.1
|
||||||
uuid: ^4.5.1
|
uuid: ^4.5.1
|
||||||
appmetrica_plugin: ^3.3.0
|
appmetrica_plugin: ^3.3.0
|
||||||
huawei_push: ^6.11.0+300
|
|
||||||
vk_id: ^1.0.3
|
vk_id: ^1.0.3
|
||||||
flutter_login_yandex: ^0.0.5
|
flutter_login_yandex: ^0.0.5
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user