Save
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- The INTERNET permission is required for development. Specifically,
|
||||
the Flutter tool needs it to communicate with the running application
|
||||
to allow setting breakpoints, to provide hot reload, etc.
|
||||
-->
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
</manifest>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- The INTERNET permission is required for development. Specifically,
|
||||
the Flutter tool needs it to communicate with the running application
|
||||
to allow setting breakpoints, to provide hot reload, etc.
|
||||
-->
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
</manifest>
|
||||
|
||||
@@ -1,55 +1,55 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
|
||||
|
||||
<application
|
||||
android:label="CESIZen"
|
||||
android:name="${applicationName}"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:usesCleartextTraffic="true">
|
||||
<activity
|
||||
android:name="com.cesizen.app.MainActivity"
|
||||
android:exported="true"
|
||||
android:launchMode="singleTop"
|
||||
android:taskAffinity=""
|
||||
android:theme="@style/LaunchTheme"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
||||
android:hardwareAccelerated="true"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<!-- Specifies an Android theme to apply to this Activity as soon as
|
||||
the Android process has started. This theme is visible to the user
|
||||
while the Flutter UI initializes. After that, this theme continues
|
||||
to determine the Window background behind the Flutter UI. -->
|
||||
<meta-data
|
||||
android:name="io.flutter.embedding.android.NormalTheme"
|
||||
android:resource="@style/NormalTheme"
|
||||
/>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<meta-data
|
||||
android:name="com.google.android.gms.wearable.capabilities"
|
||||
android:resource="@xml/wearable_app_values" />
|
||||
|
||||
<meta-data
|
||||
android:name="flutterEmbedding"
|
||||
android:value="2" />
|
||||
</application>
|
||||
<!-- Required to query activities that can process text, see:
|
||||
https://developer.android.com/training/package-visibility and
|
||||
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
|
||||
|
||||
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
|
||||
<queries>
|
||||
<package android:name="com.google.android.wearable.app" />
|
||||
<package android:name="com.cesizen.app" />
|
||||
<intent>
|
||||
<action android:name="android.intent.action.PROCESS_TEXT"/>
|
||||
<data android:mimeType="text/plain"/>
|
||||
</intent>
|
||||
</queries>
|
||||
</manifest>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
|
||||
|
||||
<application
|
||||
android:label="CESIZen"
|
||||
android:name="${applicationName}"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:usesCleartextTraffic="true">
|
||||
<activity
|
||||
android:name="com.cesizen.app.MainActivity"
|
||||
android:exported="true"
|
||||
android:launchMode="singleTop"
|
||||
android:taskAffinity=""
|
||||
android:theme="@style/LaunchTheme"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
||||
android:hardwareAccelerated="true"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<!-- Specifies an Android theme to apply to this Activity as soon as
|
||||
the Android process has started. This theme is visible to the user
|
||||
while the Flutter UI initializes. After that, this theme continues
|
||||
to determine the Window background behind the Flutter UI. -->
|
||||
<meta-data
|
||||
android:name="io.flutter.embedding.android.NormalTheme"
|
||||
android:resource="@style/NormalTheme"
|
||||
/>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<meta-data
|
||||
android:name="com.google.android.gms.wearable.capabilities"
|
||||
android:resource="@xml/wearable_app_values" />
|
||||
|
||||
<meta-data
|
||||
android:name="flutterEmbedding"
|
||||
android:value="2" />
|
||||
</application>
|
||||
<!-- Required to query activities that can process text, see:
|
||||
https://developer.android.com/training/package-visibility and
|
||||
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
|
||||
|
||||
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
|
||||
<queries>
|
||||
<package android:name="com.google.android.wearable.app" />
|
||||
<package android:name="com.cesizen.app" />
|
||||
<intent>
|
||||
<action android:name="android.intent.action.PROCESS_TEXT"/>
|
||||
<data android:mimeType="text/plain"/>
|
||||
</intent>
|
||||
</queries>
|
||||
</manifest>
|
||||
|
||||
@@ -1,108 +1,108 @@
|
||||
package com.cesizen.app
|
||||
|
||||
import android.util.Log
|
||||
import io.flutter.embedding.android.FlutterActivity
|
||||
import io.flutter.embedding.engine.FlutterEngine
|
||||
import io.flutter.plugin.common.MethodChannel
|
||||
import com.google.android.gms.wearable.Wearable
|
||||
import com.google.android.gms.wearable.PutDataMapRequest
|
||||
import com.google.android.gms.wearable.CapabilityClient
|
||||
import com.google.android.gms.tasks.Tasks
|
||||
import org.json.JSONObject
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class MainActivity : FlutterActivity() {
|
||||
private val CHANNEL = "com.cesizen/wearable"
|
||||
private val TAG = "CESIZen_Mobile_Native"
|
||||
|
||||
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
|
||||
super.configureFlutterEngine(flutterEngine)
|
||||
|
||||
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
|
||||
when (call.method) {
|
||||
"sendAuthStatus" -> {
|
||||
val status = call.argument<String>("status")
|
||||
val userName = call.argument<String>("userName")
|
||||
updateWearDataLayer(status, userName)
|
||||
result.success(true)
|
||||
}
|
||||
"syncMood" -> {
|
||||
val mood = call.argument<String>("mood")
|
||||
updateMoodDataLayer(mood)
|
||||
result.success(true)
|
||||
}
|
||||
"isWatchNearby" -> {
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
try {
|
||||
val capabilityInfo = Tasks.await(
|
||||
Wearable.getCapabilityClient(this@MainActivity)
|
||||
.getCapability("cesizen_wear_app", CapabilityClient.FILTER_ALL)
|
||||
)
|
||||
val isNearby = capabilityInfo.nodes.isNotEmpty()
|
||||
runOnUiThread { result.success(isNearby) }
|
||||
} catch (e: Exception) {
|
||||
runOnUiThread { result.success(false) }
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
result.notImplemented()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Écouter les messages de la montre
|
||||
Wearable.getMessageClient(this).addListener { messageEvent ->
|
||||
Log.d(TAG, "Message received from watch: ${messageEvent.path}")
|
||||
if (messageEvent.path == "/wearable_communication") {
|
||||
try {
|
||||
val dataString = String(messageEvent.data)
|
||||
Log.d(TAG, "Payload: $dataString")
|
||||
val json = JSONObject(dataString)
|
||||
val command = json.optString("command")
|
||||
|
||||
runOnUiThread {
|
||||
val messenger = flutterEngine.dartExecutor.binaryMessenger
|
||||
when (command) {
|
||||
"get_sync_data" -> {
|
||||
Log.d(TAG, "Command: get_sync_data -> calling requestStatusUpdate")
|
||||
MethodChannel(messenger, CHANNEL).invokeMethod("requestStatusUpdate", null)
|
||||
}
|
||||
"save_mood" -> {
|
||||
val mood = json.optString("mood")
|
||||
Log.d(TAG, "Command: save_mood ($mood) -> calling saveMoodFromWear")
|
||||
MethodChannel(messenger, CHANNEL).invokeMethod("saveMoodFromWear", mapOf("mood" to mood))
|
||||
updateMoodDataLayer(mood)
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Error processing message", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateWearDataLayer(status: String?, userName: String?) {
|
||||
val request = PutDataMapRequest.create("/auth_status")
|
||||
request.dataMap.putString("status", status ?: "unauthenticated")
|
||||
request.dataMap.putString("userName", userName ?: "")
|
||||
request.dataMap.putLong("timestamp", System.currentTimeMillis())
|
||||
val putDataRequest = request.asPutDataRequest().setUrgent()
|
||||
Wearable.getDataClient(this).putDataItem(putDataRequest)
|
||||
}
|
||||
|
||||
private fun updateMoodDataLayer(mood: String?) {
|
||||
val request = PutDataMapRequest.create("/daily_mood")
|
||||
val today = java.text.SimpleDateFormat("yyyy-MM-dd", java.util.Locale.getDefault()).format(java.util.Date())
|
||||
|
||||
request.dataMap.putString("mood", mood ?: "")
|
||||
request.dataMap.putString("date", today)
|
||||
request.dataMap.putLong("timestamp", System.currentTimeMillis())
|
||||
|
||||
val putDataRequest = request.asPutDataRequest().setUrgent()
|
||||
Wearable.getDataClient(this).putDataItem(putDataRequest)
|
||||
}
|
||||
}
|
||||
package com.cesizen.app
|
||||
|
||||
import android.util.Log
|
||||
import io.flutter.embedding.android.FlutterActivity
|
||||
import io.flutter.embedding.engine.FlutterEngine
|
||||
import io.flutter.plugin.common.MethodChannel
|
||||
import com.google.android.gms.wearable.Wearable
|
||||
import com.google.android.gms.wearable.PutDataMapRequest
|
||||
import com.google.android.gms.wearable.CapabilityClient
|
||||
import com.google.android.gms.tasks.Tasks
|
||||
import org.json.JSONObject
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class MainActivity : FlutterActivity() {
|
||||
private val CHANNEL = "com.cesizen/wearable"
|
||||
private val TAG = "CESIZen_Mobile_Native"
|
||||
|
||||
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
|
||||
super.configureFlutterEngine(flutterEngine)
|
||||
|
||||
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
|
||||
when (call.method) {
|
||||
"sendAuthStatus" -> {
|
||||
val status = call.argument<String>("status")
|
||||
val userName = call.argument<String>("userName")
|
||||
updateWearDataLayer(status, userName)
|
||||
result.success(true)
|
||||
}
|
||||
"syncMood" -> {
|
||||
val mood = call.argument<String>("mood")
|
||||
updateMoodDataLayer(mood)
|
||||
result.success(true)
|
||||
}
|
||||
"isWatchNearby" -> {
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
try {
|
||||
val capabilityInfo = Tasks.await(
|
||||
Wearable.getCapabilityClient(this@MainActivity)
|
||||
.getCapability("cesizen_wear_app", CapabilityClient.FILTER_ALL)
|
||||
)
|
||||
val isNearby = capabilityInfo.nodes.isNotEmpty()
|
||||
runOnUiThread { result.success(isNearby) }
|
||||
} catch (e: Exception) {
|
||||
runOnUiThread { result.success(false) }
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
result.notImplemented()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Écouter les messages de la montre
|
||||
Wearable.getMessageClient(this).addListener { messageEvent ->
|
||||
Log.d(TAG, "Message received from watch: ${messageEvent.path}")
|
||||
if (messageEvent.path == "/wearable_communication") {
|
||||
try {
|
||||
val dataString = String(messageEvent.data)
|
||||
Log.d(TAG, "Payload: $dataString")
|
||||
val json = JSONObject(dataString)
|
||||
val command = json.optString("command")
|
||||
|
||||
runOnUiThread {
|
||||
val messenger = flutterEngine.dartExecutor.binaryMessenger
|
||||
when (command) {
|
||||
"get_sync_data" -> {
|
||||
Log.d(TAG, "Command: get_sync_data -> calling requestStatusUpdate")
|
||||
MethodChannel(messenger, CHANNEL).invokeMethod("requestStatusUpdate", null)
|
||||
}
|
||||
"save_mood" -> {
|
||||
val mood = json.optString("mood")
|
||||
Log.d(TAG, "Command: save_mood ($mood) -> calling saveMoodFromWear")
|
||||
MethodChannel(messenger, CHANNEL).invokeMethod("saveMoodFromWear", mapOf("mood" to mood))
|
||||
updateMoodDataLayer(mood)
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Error processing message", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateWearDataLayer(status: String?, userName: String?) {
|
||||
val request = PutDataMapRequest.create("/auth_status")
|
||||
request.dataMap.putString("status", status ?: "unauthenticated")
|
||||
request.dataMap.putString("userName", userName ?: "")
|
||||
request.dataMap.putLong("timestamp", System.currentTimeMillis())
|
||||
val putDataRequest = request.asPutDataRequest().setUrgent()
|
||||
Wearable.getDataClient(this).putDataItem(putDataRequest)
|
||||
}
|
||||
|
||||
private fun updateMoodDataLayer(mood: String?) {
|
||||
val request = PutDataMapRequest.create("/daily_mood")
|
||||
val today = java.text.SimpleDateFormat("yyyy-MM-dd", java.util.Locale.getDefault()).format(java.util.Date())
|
||||
|
||||
request.dataMap.putString("mood", mood ?: "")
|
||||
request.dataMap.putString("date", today)
|
||||
request.dataMap.putLong("timestamp", System.currentTimeMillis())
|
||||
|
||||
val putDataRequest = request.asPutDataRequest().setUrgent()
|
||||
Wearable.getDataClient(this).putDataItem(putDataRequest)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Modify this file to customize your launch splash screen -->
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="?android:colorBackground" />
|
||||
|
||||
<!-- You can insert your own image assets here -->
|
||||
<!-- <item>
|
||||
<bitmap
|
||||
android:gravity="center"
|
||||
android:src="@mipmap/launch_image" />
|
||||
</item> -->
|
||||
</layer-list>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Modify this file to customize your launch splash screen -->
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="?android:colorBackground" />
|
||||
|
||||
<!-- You can insert your own image assets here -->
|
||||
<!-- <item>
|
||||
<bitmap
|
||||
android:gravity="center"
|
||||
android:src="@mipmap/launch_image" />
|
||||
</item> -->
|
||||
</layer-list>
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Modify this file to customize your launch splash screen -->
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@android:color/white" />
|
||||
|
||||
<!-- You can insert your own image assets here -->
|
||||
<!-- <item>
|
||||
<bitmap
|
||||
android:gravity="center"
|
||||
android:src="@mipmap/launch_image" />
|
||||
</item> -->
|
||||
</layer-list>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Modify this file to customize your launch splash screen -->
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@android:color/white" />
|
||||
|
||||
<!-- You can insert your own image assets here -->
|
||||
<!-- <item>
|
||||
<bitmap
|
||||
android:gravity="center"
|
||||
android:src="@mipmap/launch_image" />
|
||||
</item> -->
|
||||
</layer-list>
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
|
||||
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||
<!-- Show a splash screen on the activity. Automatically removed when
|
||||
the Flutter engine draws its first frame -->
|
||||
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||
</style>
|
||||
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||
This theme determines the color of the Android Window while your
|
||||
Flutter UI initializes, as well as behind your Flutter UI while its
|
||||
running.
|
||||
|
||||
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
||||
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||
<item name="android:windowBackground">?android:colorBackground</item>
|
||||
</style>
|
||||
</resources>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
|
||||
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||
<!-- Show a splash screen on the activity. Automatically removed when
|
||||
the Flutter engine draws its first frame -->
|
||||
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||
</style>
|
||||
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||
This theme determines the color of the Android Window while your
|
||||
Flutter UI initializes, as well as behind your Flutter UI while its
|
||||
running.
|
||||
|
||||
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
||||
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||
<item name="android:windowBackground">?android:colorBackground</item>
|
||||
</style>
|
||||
</resources>
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
|
||||
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||
<!-- Show a splash screen on the activity. Automatically removed when
|
||||
the Flutter engine draws its first frame -->
|
||||
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||
</style>
|
||||
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||
This theme determines the color of the Android Window while your
|
||||
Flutter UI initializes, as well as behind your Flutter UI while its
|
||||
running.
|
||||
|
||||
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
||||
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||
<item name="android:windowBackground">?android:colorBackground</item>
|
||||
</style>
|
||||
</resources>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
|
||||
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||
<!-- Show a splash screen on the activity. Automatically removed when
|
||||
the Flutter engine draws its first frame -->
|
||||
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||
</style>
|
||||
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||
This theme determines the color of the Android Window while your
|
||||
Flutter UI initializes, as well as behind your Flutter UI while its
|
||||
running.
|
||||
|
||||
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
||||
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||
<item name="android:windowBackground">?android:colorBackground</item>
|
||||
</style>
|
||||
</resources>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<capability name="cesizen_handheld_app" />
|
||||
</resources>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<capability name="cesizen_handheld_app" />
|
||||
</resources>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- The INTERNET permission is required for development. Specifically,
|
||||
the Flutter tool needs it to communicate with the running application
|
||||
to allow setting breakpoints, to provide hot reload, etc.
|
||||
-->
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
</manifest>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- The INTERNET permission is required for development. Specifically,
|
||||
the Flutter tool needs it to communicate with the running application
|
||||
to allow setting breakpoints, to provide hot reload, etc.
|
||||
-->
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
</manifest>
|
||||
|
||||
Reference in New Issue
Block a user