1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-11-09 11:47:04 +01:00

hack to get bangle working

This commit is contained in:
José Rebelo 2023-08-22 22:32:33 +01:00
parent ab2f916db6
commit 9f5a73be5e
5 changed files with 156 additions and 5 deletions

View File

@ -4,11 +4,17 @@ import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.Dev
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
@ -19,6 +25,7 @@ import android.webkit.PermissionRequest;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
@ -38,7 +45,10 @@ import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.concurrent.CountDownLatch;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
@ -49,9 +59,15 @@ import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
import nodomain.freeyourgadget.gadgetbridge.service.devices.banglejs.BangleJSDeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSupport;
import nodomain.freeyourgadget.gadgetbridge.util.Capsule;
import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
import nodomain.freeyourgadget.internethelper.aidl.http.HttpGetRequest;
import nodomain.freeyourgadget.internethelper.aidl.http.HttpResponse;
import nodomain.freeyourgadget.internethelper.aidl.http.IHttpCallback;
import nodomain.freeyourgadget.internethelper.aidl.http.IHttpService;
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_BANGLEJS_WEBVIEW_URL;
public class AppsManagementActivity extends AbstractGBActivity {
@ -73,6 +89,15 @@ public class AppsManagementActivity extends AbstractGBActivity {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_banglejs_apps_management);
final Intent intent1 = new Intent("nodomain.freeyourgadget.internethelper.HttpService");
intent1.setPackage("nodomain.freeyourgadget.internethelper");
boolean res = getApplicationContext().bindService(intent1, mHttpConnection, Context.BIND_AUTO_CREATE);
if (res) {
LOG.info("Bound to HttpService");
} else {
LOG.warn("Could not bind to HttpService");
}
Intent intent = getIntent();
Bundle bundle = intent.getExtras();
if (bundle != null) {
@ -171,6 +196,21 @@ public class AppsManagementActivity extends AbstractGBActivity {
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
private volatile IHttpService iHttpService;
private final CountDownLatch latchInit = new CountDownLatch(1);
private final ServiceConnection mHttpConnection = new ServiceConnection() {
public void onServiceConnected(final ComponentName className, final IBinder service) {
LOG.info("onServiceConnected: {}", className);
iHttpService = IHttpService.Stub.asInterface(service);
}
public void onServiceDisconnected(final ComponentName className) {
LOG.error("Service has unexpectedly disconnected: {}", className);
iHttpService = null;
}
};
private void initViews() {
//https://stackoverflow.com/questions/4325639/android-calling-javascript-functions-in-webview
webView = findViewById(R.id.webview);
@ -187,9 +227,7 @@ public class AppsManagementActivity extends AbstractGBActivity {
webView.setWebContentsDebuggingEnabled(true); // FIXME
Prefs devicePrefs = new Prefs(GBApplication.getDeviceSpecificSharedPrefs(mGBDevice.getAddress()));
String url = devicePrefs.getString(PREF_BANGLEJS_WEBVIEW_URL, "").trim();
if (url.isEmpty()) url = "https://banglejs.com/apps/android.html";
webView.loadUrl(url);
final String url = devicePrefs.getString(PREF_BANGLEJS_WEBVIEW_URL, "https://banglejs.com/apps/android.html").trim();
webView.setWebViewClient(new WebViewClient(){
public void onPageFinished(WebView view, String weburl){
@ -202,12 +240,60 @@ public class AppsManagementActivity extends AbstractGBActivity {
return true;
}
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
LOG.info("shouldIntercept {} {}", request.getUrl(), iHttpService != null);
if (iHttpService == null) {
return super.shouldInterceptRequest(view, request);
}
HttpGetRequest httpGetRequest = new HttpGetRequest(request.getUrl().toString(), new Bundle());
CountDownLatch latch = new CountDownLatch(1);
final Capsule<WebResourceResponse> internetResponseCapsule = new Capsule<>();
try {
iHttpService.get(httpGetRequest, new IHttpCallback.Stub() {
@Override
public void onResponse(HttpResponse response) throws RemoteException {
WebResourceResponse internetResponse = new WebResourceResponse(
response.getHeaders().getString("content-type"),
response.getHeaders().getString("content-encoding"),
response.getStatus(), "OK",
response.getHeadersMap(),
new ByteArrayInputStream(response.getBody())
);
internetResponseCapsule.set(internetResponse);
latch.countDown();
}
@Override
public void onException(String message) throws RemoteException {
throw new RuntimeException(message);
}
});
} catch (RemoteException e) {
throw new RuntimeException(e);
}
try {
latch.await();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return internetResponseCapsule.get();
}
@Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
Toast.makeText(AppsManagementActivity.this, "Error:" + description, Toast.LENGTH_SHORT).show();
view.loadUrl("about:blank");
}
});
final Looper mainLooper = Looper.getMainLooper();
new Handler(mainLooper).postDelayed(() -> {
webView.loadUrl(url);
}, 1000);
webView.setWebChromeClient(new WebChromeClient() {
@Override
public void onPermissionRequest(final PermissionRequest request) {

View File

@ -153,12 +153,12 @@ public class BangleJSCoordinator extends AbstractBLEDeviceCoordinator {
@Override
public boolean supportsAppsManagement(final GBDevice device) {
return BuildConfig.INTERNET_ACCESS;
return true;
}
@Override
public Class<? extends Activity> getAppsManagementActivity() {
return BuildConfig.INTERNET_ACCESS ? AppsManagementActivity.class : null;
return AppsManagementActivity.class;
}
@Override

View File

@ -0,0 +1,37 @@
/* Copyright (C) 2023 José Rebelo
This file is part of Gadgetbridge.
Gadgetbridge is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gadgetbridge is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.util;
public final class Capsule<T> {
private T value;
public Capsule() {
this.value = null;
}
public Capsule(final T value) {
this.value = value;
}
public T get() {
return value;
}
public void set(T value) {
this.value = value;
}
}

View File

@ -15,6 +15,11 @@ public class HttpGetRequest implements Parcelable {
headers = in.readBundle(ClassLoader.getSystemClassLoader());
}
public HttpGetRequest(String url, Bundle headers) {
this.url = url;
this.headers = headers;
}
public static final Creator<HttpGetRequest> CREATOR = new Creator<HttpGetRequest>() {
@Override
public HttpGetRequest createFromParcel(final Parcel in) {

View File

@ -6,6 +6,9 @@ import android.os.Parcelable;
import androidx.annotation.NonNull;
import java.util.HashMap;
import java.util.Map;
public class HttpResponse implements Parcelable {
private final int status;
private final Bundle headers;
@ -49,4 +52,24 @@ public class HttpResponse implements Parcelable {
dest.writeInt(body.length);
dest.writeByteArray(body);
}
public int getStatus() {
return status;
}
public Bundle getHeaders() {
return headers;
}
public Map<String, String> getHeadersMap() {
final Map<String, String> ret = new HashMap<>();
for (String k : headers.keySet()) {
ret.put(k, headers.getString(k));
}
return ret;
}
public byte[] getBody() {
return body;
}
}