diff --git a/README.md b/README.md
index 3eb5905e6..a264f89d8 100644
--- a/README.md
+++ b/README.md
@@ -41,6 +41,7 @@ vendor's servers.
- T-Rex [**\[!\]**](#special-pairing-procedures)
- Verge Lite [**\[!\]**](#special-pairing-procedures)
- [X ](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Mi-Band-5) [**\[!\]**](#special-pairing-procedures)
+- [Bangle.js](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Bangle.js)
- BFH-16
- [Casio](https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Casio)
- Casio GB-X6900B
diff --git a/app/build.gradle b/app/build.gradle
index 80fe1036d..ee4ef5613 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -60,6 +60,7 @@ android {
vectorDrawables.useSupportLibrary = true
multiDexEnabled true
buildConfigField "String", "GIT_HASH_SHORT", "\"${getGitHashShort()}\""
+ buildConfigField "boolean", "INTERNET_ACCESS", "false"
resValue "string", "pebble_content_provider", "com.getpebble.android.provider"
}
signingConfigs {
@@ -121,6 +122,27 @@ android {
}
+ flavorDimensions "device_type"
+ productFlavors {
+ main {
+ // Ensure that when starting from scratch, 'main' is selected, not 'banglejs'
+ getIsDefault().set(true)
+ // the default build product flavor
+ dimension "device_type"
+ //applicationIdSuffix ""
+ //versionNameSuffix ""
+ }
+ banglejs {
+ dimension "device_type"
+ applicationId "com.espruino.gadgetbridge"
+ applicationIdSuffix ".banglejs"
+ versionNameSuffix "-banglejs"
+ buildConfigField "boolean", "INTERNET_ACCESS", "true"
+ // Disable pebble provider to allow Bangle.js Gadgetbridge to coexist with Gadgetbridge
+ resValue "string", "pebble_content_provider", "com.getpebble.android.nopebble.provider"
+ }
+ }
+
lintOptions {
abortOnError ABORT_ON_CHECK_FAILURE
lintConfig file("${project.rootDir}/config/lint/lint.xml")
@@ -195,6 +217,7 @@ dependencies {
implementation 'com.github.wax911:android-emojify:0.1.7'
implementation 'com.google.protobuf:protobuf-lite:3.0.1'
implementation "androidx.multidex:multidex:2.0.1"
+ implementation 'com.android.volley:volley:1.2.1'
}
preBuild.dependsOn(":GBDaoGenerator:genSources")
diff --git a/app/src/banglejs/AndroidManifest.xml b/app/src/banglejs/AndroidManifest.xml
new file mode 100644
index 000000000..8478e0e63
--- /dev/null
+++ b/app/src/banglejs/AndroidManifest.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/banglejs/res/drawable/ic_launcher_foreground.xml b/app/src/banglejs/res/drawable/ic_launcher_foreground.xml
new file mode 100644
index 000000000..92a455296
--- /dev/null
+++ b/app/src/banglejs/res/drawable/ic_launcher_foreground.xml
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/banglejs/res/values/strings.xml b/app/src/banglejs/res/values/strings.xml
new file mode 100644
index 000000000..e965e9764
--- /dev/null
+++ b/app/src/banglejs/res/values/strings.xml
@@ -0,0 +1,8 @@
+
+
+ Bangle.js Gadgetbridge
+ Bangle.js Gadgetbridge
+ About Bangle.js Gadgetbridge
+ Android companion app for Bangle.js built on top of the Gadgetbridge project, with added Internet Access.
+ Bangle.js running
+
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ControlCenterv2.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ControlCenterv2.java
index 2b2e82205..e63c4d23e 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ControlCenterv2.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ControlCenterv2.java
@@ -65,6 +65,7 @@ import java.util.Set;
import de.cketti.library.changelog.ChangeLog;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
+import nodomain.freeyourgadget.gadgetbridge.BuildConfig;
import nodomain.freeyourgadget.gadgetbridge.adapter.GBDeviceAdapterv2;
import nodomain.freeyourgadget.gadgetbridge.database.DBAccess;
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
@@ -438,6 +439,12 @@ public class ControlCenterv2 extends AppCompatActivity
}
}
+ if (BuildConfig.INTERNET_ACCESS) {
+ if (ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.INTERNET) == PackageManager.PERMISSION_DENIED) {
+ wantedPermissions.add(Manifest.permission.INTERNET);
+ }
+ }
+
if (!wantedPermissions.isEmpty()) {
Prefs prefs = GBApplication.getPrefs();
// If this is not the first run, we can rely on
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/banglejs/BangleJSDeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/banglejs/BangleJSDeviceSupport.java
index 73fb64da3..e79089800 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/banglejs/BangleJSDeviceSupport.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/banglejs/BangleJSDeviceSupport.java
@@ -31,6 +31,13 @@ import android.widget.Toast;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
+import com.android.volley.Request;
+import com.android.volley.Response;
+import com.android.volley.RequestQueue;
+import com.android.volley.VolleyError;
+import com.android.volley.toolbox.StringRequest;
+import com.android.volley.toolbox.Volley;
+
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@@ -270,6 +277,39 @@ public class BangleJSDeviceSupport extends AbstractBTLEDeviceSupport {
LocalBroadcastManager.getInstance(getContext()).sendBroadcast(intent);
}
} break;
+ case "http": {
+ // FIXME: This should be behind a default-off option in Gadgetbridge settings
+ RequestQueue queue = Volley.newRequestQueue(getContext());
+ String url = json.getString("url");
+ // Request a string response from the provided URL.
+ StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
+ new Response.Listener() {
+ @Override
+ public void onResponse(String response) {
+ JSONObject o = new JSONObject();
+ try {
+ o.put("t", "http");
+ o.put("resp", response);
+ } catch (JSONException e) {
+ GB.toast(getContext(), "HTTP: " + e.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR);
+ }
+ uartTxJSON("http", o);
+ }
+ }, new Response.ErrorListener() {
+ @Override
+ public void onErrorResponse(VolleyError error) {
+ JSONObject o = new JSONObject();
+ try {
+ o.put("t", "http");
+ o.put("err", error.toString());
+ } catch (JSONException e) {
+ GB.toast(getContext(), "HTTP: " + e.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR);
+ }
+ uartTxJSON("http", o);
+ }
+ });
+ queue.add(stringRequest);
+ } break;
}
}
@@ -628,23 +668,34 @@ public class BangleJSDeviceSupport extends AbstractBTLEDeviceSupport {
/** Convert a drawable to a bitmap, for use with bitmapToEspruino */
public static Bitmap drawableToBitmap(Drawable drawable) {
+ final int maxWidth = 32;
+ final int maxHeight = 32;
+ /* Return bitmap directly but only if it's small enough. It could be
+ we have a bitmap but it's just too big to send direct to the bangle */
if (drawable instanceof BitmapDrawable) {
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
- if (bitmapDrawable.getBitmap() != null) {
- return bitmapDrawable.getBitmap();
- }
+ Bitmap bmp = bitmapDrawable.getBitmap();
+ if (bmp != null && bmp.getWidth()<=maxWidth && bmp.getHeight()<=maxHeight)
+ return bmp;
}
- int w = 24;
- int h = 24;
+ /* Otherwise render this to a bitmap ourselves.. work out size */
+ int w = maxWidth;
+ int h = maxHeight;
if (drawable.getIntrinsicWidth() > 0 && drawable.getIntrinsicHeight() > 0) {
w = drawable.getIntrinsicWidth();
h = drawable.getIntrinsicHeight();
- // don't allocate anything too big
- if (w>24) w=24;
- if (h>24) h=24;
+ // don't allocate anything too big, but keep the ratio
+ if (w>maxWidth) {
+ h = h * maxWidth / w;
+ w = maxWidth;
+ }
+ if (h>maxHeight) {
+ w = w * maxHeight / h;
+ h = maxHeight;
+ }
}
+ /* render */
Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); // Single color bitmap will be created of 1x1 pixel
-
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);