Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .gitignore

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should be in the examples gitignore file

Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
# macOS
.DS_Store
.DS_Store
/watch_connectivity_garmin/example/android/.gradle
/watch_connectivity_garmin/example/android/app/.cxx
watch_connectivity_garmin/example/android/local.properties
watch_connectivity_garmin/example/.flutter-plugins
watch_connectivity_garmin/example/.flutter-plugins-dependencies
3 changes: 3 additions & 0 deletions watch_connectivity_garmin/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
## 0.1.7
- added a basic example for how to run `watch_connectivity_garmin` and included `proguard` rules for creating a working release build for android devices

## 0.1.6
- Upgrades `watch_connectivity_platform_interface`

Expand Down
39 changes: 39 additions & 0 deletions watch_connectivity_garmin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,45 @@ void example() {

```

As of this moment you will have to develop your own Garmin watch app to send and receive messages, but here's a little start
```cpp
public function onMessageReceived(message) as Void {
if (message != null && message.isValid()) {
// this is a good message to use show this received data (the message is a map)
var messageFromPhone = message.content();
// and update our view for this message data
WatchUi.requestUpdate();
}
}

public function onTap(event as ClickEvent) as Void {
var listener = new $.CommListener();
var app = $.getApp();
Communications.transmit({
"clickX" => event.getCoordinates()[0],
"clickY" => event.getCoordinates()[1],
"content" => "Hello from the watch!",
}, null, listener);
}
```

## Releasing (Android release build)
The app communicates with the Garmin classes via its namespace. So when released these can be minified
making them uncontactable. To prevent this from happening you will need to include the exclusions in your
`proguard-rules.pro` file as in the example:

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't need to be in the readme. The plugin can provide these rules to consumer applications.

```yaml
-keep class com.garmin.** { *; }
-keep class com.garmin.android.connectiq.** { *; }
-keep class com.garmin.android.apps.connectmobile.** { *; }
```

OR in your `build.gradle` you can set
```yaml
shrinkResources false
minifyEnabled false
```
* but this is not recommended as your code will be larger than it needs to be

## Unsupported Features

The following features are not supported by Garmin watches:
Expand Down
70 changes: 70 additions & 0 deletions watch_connectivity_garmin/example/android/app/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
plugins {
id "com.android.application"
id "kotlin-android"
id "dev.flutter.flutter-gradle-plugin"
}

def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader -> localProperties.load(reader)
}
}

def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}

def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}

android {
compileSdkVersion flutter.compileSdkVersion

compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}

kotlinOptions {
jvmTarget = '1.8'
}

sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}

defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "dev.rexios.watch_connectivity_garmin"
minSdkVersion 23
targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}

buildTypes {
debug {
signingConfig signingConfigs.debug
}
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.debug
shrinkResources true
minifyEnabled true
// because we are connecting to the Garmin watch via namespaced plugin access
// we need the special proguard rules to pevent obsfuscation of these classes
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

}
}
namespace 'dev.rexios.watch_connectivity_garmin'
}

flutter {
source '../..'
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="dev.rexios.watch_connectivity_garmin">
<!-- Flutter 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>
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="dev.rexios.watch_connectivity_garmin">
<application
android:label="Example App"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
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>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package io.flutter.plugins;

import androidx.annotation.Keep;
import androidx.annotation.NonNull;
import io.flutter.Log;

import io.flutter.embedding.engine.FlutterEngine;

/**
* Generated file. Do not edit.
* This file is generated by the Flutter tool based on the
* plugins that support the Android platform.
*/
@Keep
public final class GeneratedPluginRegistrant {
private static final String TAG = "GeneratedPluginRegistrant";
public static void registerWith(@NonNull FlutterEngine flutterEngine) {
try {
flutterEngine.getPlugins().add(new dev.rexios.watch_connectivity.WatchConnectivityPlugin());
} catch (Exception e) {
Log.e(TAG, "Error registering plugin watch_connectivity, dev.rexios.watch_connectivity.WatchConnectivityPlugin", e);
}
try {
flutterEngine.getPlugins().add(new dev.rexios.watch_connectivity_garmin.WatchConnectivityGarminPlugin());
} catch (Exception e) {
Log.e(TAG, "Error registering plugin watch_connectivity_garmin, dev.rexios.watch_connectivity_garmin.WatchConnectivityGarminPlugin", e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package dev.rexios.watch_connectivity_garmin

import io.flutter.embedding.android.FlutterActivity

class MainActivity: FlutterActivity() {
}
Original file line number Diff line number Diff line change
@@ -0,0 +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>
Original file line number Diff line number Diff line change
@@ -0,0 +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>
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +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
Flutter 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>
Original file line number Diff line number Diff line change
@@ -0,0 +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
Flutter 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>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="dev.rexios.watch_connectivity_garmin">
<!-- Flutter 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>
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
## Flutter wrapper
-keepattributes Signature
-keepattributes LineNumberTable,SourceFile
-renamesourcefileattribute SourceFile
-keep class io.flutter.app.** { *; }
-keep class io.flutter.plugin.** { *; }
-keep class io.flutter.util.** { *; }
-keep class io.flutter.view.** { *; }
-keep class io.flutter.** { *; }
-keep class io.flutter.plugins.** { *; }
-dontwarn io.flutter.embedding.**
-keep class com.google.firebase.** { *; }
-keep class com.garmin.** { *; }
-keep class com.garmin.android.connectiq.** { *; }
-keep class com.garmin.android.apps.connectmobile.** { *; }
-keepattributes JavascriptInterface
-keepattributes Annotation
-optimizations !method/inlining
18 changes: 18 additions & 0 deletions watch_connectivity_garmin/example/android/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
allprojects {
repositories {
google()
mavenCentral()
}
}

rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
}

tasks.register("clean", Delete) {
delete rootProject.buildDir
}
6 changes: 6 additions & 0 deletions watch_connectivity_garmin/example/android/gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true
android.enableJetifier=true
android.defaults.buildfeatures.buildconfig=true
android.nonTransitiveRClass=false
android.nonFinalResIds=false
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Loading