1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-11-28 12:56:49 +01:00

Fossil Hybrid: added manual file down/upload

This commit is contained in:
Daniel Dakhno 2020-10-16 01:50:44 +02:00
parent 57f6b225d8
commit 3b2a16b6fc
9 changed files with 289 additions and 11 deletions

View File

@ -570,5 +570,8 @@
<activity <activity
android:name=".devices.qhybrid.ImageEditActivity" android:name=".devices.qhybrid.ImageEditActivity"
android:exported="true" /> android:exported="true" />
<activity
android:name=".devices.qhybrid.FileManagementActivity"
android:exported="true" />
</application> </application>
</manifest> </manifest>

View File

@ -0,0 +1,124 @@
package nodomain.freeyourgadget.gadgetbridge.devices.qhybrid;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ExpandableListView;
import android.widget.Spinner;
import android.widget.Switch;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import java.io.Serializable;
import java.nio.file.attribute.FileTime;
import no.nordicsemi.android.dfu.FileType;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractGBActivity;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.file.FileHandle;
public class FileManagementActivity extends AbstractGBActivity implements View.OnClickListener {
private final int REQUEST_CODE_PICK_UPLOAD_FILE = 0;
private Spinner fileTypesSpinner;
private Switch encryptedFile;
BroadcastReceiver fileResultReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(QHybridSupport.QHYBRID_ACTION_DOWNLOADED_FILE)) {
boolean success = intent.getBooleanExtra("EXTRA_SUCCESS", false);
if (!success) {
Toast.makeText(FileManagementActivity.this, "error downloading file, check logcat", Toast.LENGTH_LONG).show();
return;
}
String path = intent.getStringExtra("EXTRA_PATH");
Toast.makeText(FileManagementActivity.this, "downloaded file " + path, Toast.LENGTH_LONG).show();
}else if(intent.getAction().equals(QHybridSupport.QHYBRID_ACTION_UPLOADED_FILE)) {
boolean success = intent.getBooleanExtra("EXTRA_SUCCESS", false);
if (!success) {
Toast.makeText(FileManagementActivity.this, "error uploading file, check logcat", Toast.LENGTH_LONG).show();
return;
}
Toast.makeText(FileManagementActivity.this, "uploaded file", Toast.LENGTH_LONG).show();
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_qhybrid_file_management);
initViews();
}
@Override
protected void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter();
filter.addAction(QHybridSupport.QHYBRID_ACTION_DOWNLOADED_FILE);
filter.addAction(QHybridSupport.QHYBRID_ACTION_UPLOADED_FILE);
LocalBroadcastManager.getInstance(this).registerReceiver(fileResultReceiver, filter);
}
@Override
protected void onPause() {
super.onPause();
LocalBroadcastManager.getInstance(this).unregisterReceiver(fileResultReceiver);
}
private void initViews() {
FileHandle[] handles = FileHandle.values();
fileTypesSpinner = findViewById(R.id.qhybrid_file_types);
fileTypesSpinner.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, handles));
encryptedFile = findViewById(R.id.qhybrid_switch_encrypted_file);
findViewById(R.id.qhybrid_button_download_file).setOnClickListener(this);
findViewById(R.id.qhybrid_button_upload_file).setOnClickListener(this);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode != REQUEST_CODE_PICK_UPLOAD_FILE) return;
if(resultCode != RESULT_OK) return;
Intent callIntent = new Intent(QHybridSupport.QHYBRID_COMMAND_UPLOAD_FILE);
callIntent.putExtra("EXTRA_HANDLE", (FileHandle) fileTypesSpinner.getSelectedItem());
callIntent.putExtra("EXTRA_ENCRYPTED", encryptedFile.isChecked());
callIntent.putExtra("EXTRA_PATH", data.getData().getPath());
// callIntent.setData(data.getData());
LocalBroadcastManager.getInstance(this).sendBroadcast(callIntent);
}
@Override
public void onClick(View v) {
boolean isEncrypted = encryptedFile.isChecked();
if (v.getId() == R.id.qhybrid_button_download_file) {
Intent fileIntent = new Intent();
fileIntent.putExtra("EXTRA_ENCRYPTED", isEncrypted);
fileIntent.setAction(QHybridSupport.QHYBRID_COMMAND_DOWNLOAD_FILE);
fileIntent.putExtra("EXTRA_HANDLE", (FileHandle) fileTypesSpinner.getSelectedItem());
LocalBroadcastManager.getInstance(this).sendBroadcast(fileIntent);
} else if (v.getId() == R.id.qhybrid_button_upload_file) {
Intent chooserIntent = new Intent()
.setType("*/*")
.setAction(Intent.ACTION_GET_CONTENT);
Intent intent = Intent.createChooser(chooserIntent, "Select a file");
startActivityForResult(intent, REQUEST_CODE_PICK_UPLOAD_FILE);
}
}
}

View File

@ -68,6 +68,7 @@ public class HRConfigActivity extends AbstractGBActivity implements View.OnClick
setContentView(R.layout.activity_qhybrid_hr_settings); setContentView(R.layout.activity_qhybrid_hr_settings);
findViewById(R.id.qhybrid_action_add).setOnClickListener(this); findViewById(R.id.qhybrid_action_add).setOnClickListener(this);
findViewById(R.id.qhybrid_file_management_trigger).setOnClickListener(this);
sharedPreferences = GBApplication.getPrefs().getPreferences(); sharedPreferences = GBApplication.getPrefs().getPreferences();
@ -401,6 +402,9 @@ public class HRConfigActivity extends AbstractGBActivity implements View.OnClick
.setPositiveButton("ok", this) .setPositiveButton("ok", this)
.setTitle("create action") .setTitle("create action")
.show(); .show();
} else if(v.getId() == R.id.qhybrid_file_management_trigger) {
finish();
startActivity(new Intent(getApplicationContext(), FileManagementActivity.class));
} }
} }

View File

@ -70,6 +70,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.Watc
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.WatchAdapterFactory; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.WatchAdapterFactory;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil_hr.FossilHRWatchAdapter; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil_hr.FossilHRWatchAdapter;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.file.FileHandle;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.DownloadFileRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.DownloadFileRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.PlayNotificationRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.PlayNotificationRequest;
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils; import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
@ -91,6 +92,12 @@ public class QHybridSupport extends QHybridBaseSupport {
public static final String QHYBRID_COMMAND_SET_WIDGET_CONTENT = "nodomain.freeyourgadget.gadgetbridge.Q_SET_WIDGET_CONTENT"; public static final String QHYBRID_COMMAND_SET_WIDGET_CONTENT = "nodomain.freeyourgadget.gadgetbridge.Q_SET_WIDGET_CONTENT";
public static final String QHYBRID_COMMAND_SET_BACKGROUND_IMAGE = "nodomain.freeyourgadget.gadgetbridge.Q_SET_BACKGROUND_IMAGE"; public static final String QHYBRID_COMMAND_SET_BACKGROUND_IMAGE = "nodomain.freeyourgadget.gadgetbridge.Q_SET_BACKGROUND_IMAGE";
public static final String QHYBRID_COMMAND_DOWNLOAD_FILE = "nodomain.freeyourgadget.gadgetbridge.Q_DOWNLOAD_FILE";
public static final String QHYBRID_COMMAND_UPLOAD_FILE = "nodomain.freeyourgadget.gadgetbridge.Q_UPLOAD_FILE";
public static final String QHYBRID_ACTION_DOWNLOADED_FILE = "nodomain.freeyourgadget.gadgetbridge.Q_DOWNLOADED_FILE";
public static final String QHYBRID_ACTION_UPLOADED_FILE = "nodomain.freeyourgadget.gadgetbridge.Q_UPLOADED_FILE";
private static final String QHYBRID_ACTION_SET_ACTIVITY_HAND = "nodomain.freeyourgadget.gadgetbridge.Q_SET_ACTIVITY_HAND"; private static final String QHYBRID_ACTION_SET_ACTIVITY_HAND = "nodomain.freeyourgadget.gadgetbridge.Q_SET_ACTIVITY_HAND";
public static final String QHYBRID_EVENT_SETTINGS_UPDATED = "nodomain.freeyourgadget.gadgetbridge.Q_SETTINGS_UPDATED"; public static final String QHYBRID_EVENT_SETTINGS_UPDATED = "nodomain.freeyourgadget.gadgetbridge.Q_SETTINGS_UPDATED";
@ -146,6 +153,8 @@ public class QHybridSupport extends QHybridBaseSupport {
commandFilter.addAction(QHYBRID_COMMAND_UPDATE_WIDGETS); commandFilter.addAction(QHYBRID_COMMAND_UPDATE_WIDGETS);
commandFilter.addAction(QHYBRID_COMMAND_SEND_MENU_ITEMS); commandFilter.addAction(QHYBRID_COMMAND_SEND_MENU_ITEMS);
commandFilter.addAction(QHYBRID_COMMAND_SET_BACKGROUND_IMAGE); commandFilter.addAction(QHYBRID_COMMAND_SET_BACKGROUND_IMAGE);
commandFilter.addAction(QHYBRID_COMMAND_UPLOAD_FILE);
commandFilter.addAction(QHYBRID_COMMAND_DOWNLOAD_FILE);
commandReceiver = new BroadcastReceiver() { commandReceiver = new BroadcastReceiver() {
@Override @Override
@ -237,6 +246,21 @@ public class QHybridSupport extends QHybridBaseSupport {
watchAdapter.setBackgroundImage(pixels); watchAdapter.setBackgroundImage(pixels);
break; break;
} }
case QHYBRID_COMMAND_DOWNLOAD_FILE:{
Object handleObject = intent.getSerializableExtra("EXTRA_HANDLE");
if(handleObject == null || !(handleObject instanceof FileHandle)) return;
FileHandle handle = (FileHandle) handleObject;
watchAdapter.downloadFile(handle, intent.getBooleanExtra("EXTRA_ENCRYPTED", false));
break;
}
case QHYBRID_COMMAND_UPLOAD_FILE:{
Object handleObject = intent.getSerializableExtra("EXTRA_HANDLE");
if(handleObject == null || !(handleObject instanceof FileHandle)) return;
FileHandle handle = (FileHandle) handleObject;
String filePath = intent.getStringExtra("EXTRA_PATH");
watchAdapter.uploadFile(handle, filePath, intent.getBooleanExtra("EXTRA_ENCRYPTED", false));
break;
}
} }
} }
}; };

View File

@ -30,6 +30,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.MusicSpec;
import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec; import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec;
import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec; import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSupport; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.file.FileHandle;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.PlayNotificationRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.PlayNotificationRequest;
public abstract class WatchAdapter { public abstract class WatchAdapter {
@ -138,4 +139,10 @@ public abstract class WatchAdapter {
public void onDeleteNotification(int id) { public void onDeleteNotification(int id) {
} }
public void downloadFile(FileHandle handle, boolean fileIsEncrypted) {
}
public void uploadFile(FileHandle handle, String filePath, boolean fileIsEncrypted) {
}
} }

View File

@ -46,6 +46,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSuppo
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.WatchAdapter; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.WatchAdapter;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.buttonconfig.ConfigFileBuilder; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.buttonconfig.ConfigFileBuilder;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.buttonconfig.ConfigPayload; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.buttonconfig.ConfigPayload;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.file.FileHandle;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.Request; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.Request;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.FossilRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.FossilRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.RequestMtuRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.RequestMtuRequest;
@ -241,7 +242,7 @@ public class FossilWatchAdapter extends WatchAdapter {
ConfigFileBuilder builder = new ConfigFileBuilder(payloads); ConfigFileBuilder builder = new ConfigFileBuilder(payloads);
FilePutRequest fileUploadRequets = new FilePutRequest((short) 0x0600, builder.build(true), this) { FilePutRequest fileUploadRequets = new FilePutRequest(FileHandle.SETTINGS_BUTTONS, builder.build(true), this) {
@Override @Override
public void onFilePut(boolean success) { public void onFilePut(boolean success) {
if (success) if (success)
@ -361,7 +362,7 @@ public class FossilWatchAdapter extends WatchAdapter {
@Override @Override
public void onTestNewFunction() { public void onTestNewFunction() {
queueWrite(new FilePutRequest( queueWrite(new FilePutRequest(
(short) 0x0600, FileHandle.HAND_ACTIONS,
new byte[]{ new byte[]{
(byte) 0x01, (byte) 0x00, (byte) 0x08, (byte) 0x01, (byte) 0x01, (byte) 0x24, (byte) 0x00, (byte) 0x85, (byte) 0x01, (byte) 0x30, (byte) 0x52, (byte) 0xFF, (byte) 0x26, (byte) 0x00, (byte) 0x03, (byte) 0x00, (byte) 0x09, (byte) 0x04, (byte) 0x01, (byte) 0x03, (byte) 0xA0, (byte) 0x00, (byte) 0x00, (byte) 0xA0, (byte) 0x00, (byte) 0x00, (byte) 0x08, (byte) 0x01, (byte) 0x05, (byte) 0x00, (byte) 0x93, (byte) 0x00, (byte) 0x02, (byte) 0x09, (byte) 0x04, (byte) 0x01, (byte) 0x03, (byte) 0x00, (byte) 0x24, (byte) 0x00, (byte) 0x00, (byte) 0x24, (byte) 0x00, (byte) 0x08, (byte) 0x01, (byte) 0x50, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x1F, (byte) 0xBE, (byte) 0xB4, (byte) 0x1B (byte) 0x01, (byte) 0x00, (byte) 0x08, (byte) 0x01, (byte) 0x01, (byte) 0x24, (byte) 0x00, (byte) 0x85, (byte) 0x01, (byte) 0x30, (byte) 0x52, (byte) 0xFF, (byte) 0x26, (byte) 0x00, (byte) 0x03, (byte) 0x00, (byte) 0x09, (byte) 0x04, (byte) 0x01, (byte) 0x03, (byte) 0xA0, (byte) 0x00, (byte) 0x00, (byte) 0xA0, (byte) 0x00, (byte) 0x00, (byte) 0x08, (byte) 0x01, (byte) 0x05, (byte) 0x00, (byte) 0x93, (byte) 0x00, (byte) 0x02, (byte) 0x09, (byte) 0x04, (byte) 0x01, (byte) 0x03, (byte) 0x00, (byte) 0x24, (byte) 0x00, (byte) 0x00, (byte) 0x24, (byte) 0x00, (byte) 0x08, (byte) 0x01, (byte) 0x50, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x1F, (byte) 0xBE, (byte) 0xB4, (byte) 0x1B
}, },

View File

@ -3,7 +3,6 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fos
import android.bluetooth.BluetoothGattCharacteristic; import android.bluetooth.BluetoothGattCharacteristic;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
@ -13,14 +12,19 @@ import android.graphics.Paint;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.net.Uri; import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.widget.Toast; import android.widget.Toast;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.File; import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.FileOutputStream; import java.io.FileOutputStream;
@ -29,11 +33,8 @@ import java.io.InputStream;
import java.nio.BufferOverflowException; import java.nio.BufferOverflowException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.List;
import java.util.TimeZone;
import java.util.UUID; import java.util.UUID;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -60,26 +61,26 @@ import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec;
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSupport; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.file.FileHandle;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.parser.ActivityEntry; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.parser.ActivityEntry;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.parser.ActivityFileParser; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.parser.ActivityFileParser;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.Request;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.RequestMtuRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.RequestMtuRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.SetDeviceStateRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.SetDeviceStateRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.configuration.ConfigurationPutRequest.TimeConfigItem;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FileDeleteRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FileDeleteRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FileGetRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FileLookupRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FileLookupRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FilePutRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.notification.PlayCallNotificationRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.notification.PlayCallNotificationRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.notification.PlayTextNotificationRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.notification.PlayTextNotificationRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.activity.ActivityFilesGetRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.async.ConfirmAppStatusRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.async.ConfirmAppStatusRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.authentication.VerifyPrivateKeyRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.authentication.VerifyPrivateKeyRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.buttons.ButtonConfiguration; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.buttons.ButtonConfiguration;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.buttons.ButtonConfigurationPutRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.buttons.ButtonConfigurationPutRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.configuration.ConfigurationGetRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.configuration.ConfigurationGetRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.configuration.ConfigurationPutRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.configuration.ConfigurationPutRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.file.AssetFile;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.file.AssetFilePutRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.file.AssetFilePutRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.file.FileEncryptedGetRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.file.FileEncryptedGetRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.file.FilePutRawRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.file.FirmwareFilePutRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.file.FirmwareFilePutRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.image.AssetImage; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.image.AssetImage;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.image.AssetImageFactory; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.image.AssetImageFactory;
@ -478,7 +479,7 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
if (pushFiles.size() > 0) { if (pushFiles.size() > 0) {
queueWrite(new AssetFilePutRequest( queueWrite(new AssetFilePutRequest(
pushFiles.toArray(new AssetImage[0]), pushFiles.toArray(new AssetImage[0]),
(byte) 0x00, FileHandle.ASSET_BACKGROUND_IMAGES,
this this
)); ));
} }
@ -492,6 +493,70 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
} }
} }
private void handleFileDownload(FileHandle handle, byte[] file){
Intent resultIntent = new Intent(QHybridSupport.QHYBRID_ACTION_DOWNLOADED_FILE);
File outputFile = new File(getContext().getExternalFilesDir("download"), handle.name() + "_" + System.currentTimeMillis() + ".bin");
try {
FileOutputStream fos = new FileOutputStream(outputFile);
fos.write(file);
fos.close();
resultIntent.putExtra("EXTRA_SUCCESS", true);
resultIntent.putExtra("EXTRA_PATH", outputFile.getAbsolutePath());
} catch (IOException e) {
e.printStackTrace();
resultIntent.putExtra("EXTRA_SUCCESS", false);
}
LocalBroadcastManager.getInstance(getContext()).sendBroadcast(resultIntent);
}
@Override
public void uploadFile(FileHandle handle, String filePath, boolean fileIsEncrypted) {
final Intent resultIntent = new Intent(QHybridSupport.QHYBRID_ACTION_UPLOADED_FILE);
byte[] fileData;
try {
FileInputStream fis = new FileInputStream(filePath);
fileData = new byte[fis.available()];
fis.read(fileData);
fis.close();
} catch (IOException e) {
e.printStackTrace();
resultIntent.putExtra("EXTRA_SUCCESS", false);
LocalBroadcastManager.getInstance(getContext()).sendBroadcast(resultIntent);
return;
}
queueWrite(new FilePutRawRequest(handle, fileData, this){
@Override
public void onFilePut(boolean success) {
resultIntent.putExtra("EXTRA_SUCCESS", success);
LocalBroadcastManager.getInstance(getContext()).sendBroadcast(resultIntent);
}
});
}
@Override
public void downloadFile(final FileHandle handle, boolean fileIsEncrypted) {
if(fileIsEncrypted){
negotiateSymmetricKey();
queueWrite(new FileEncryptedGetRequest(handle, this) {
@Override
public void handleFileData(byte[] fileData) {
logger.debug("downloaded encrypted file");
handleFileDownload(handle, fileData);
}
});
}else{
queueWrite(new FileGetRequest(handle, this) {
@Override
public void handleFileData(byte[] fileData) {
logger.debug("downloaded regular file");
handleFileDownload(handle, fileData);
}
});
}
}
@Override @Override
public void setWidgetContent(String widgetID, String content, boolean renderOnWatch) { public void setWidgetContent(String widgetID, String content, boolean renderOnWatch) {
boolean update = false; boolean update = false;

View File

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Spinner
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/qhybrid_file_types" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="vertical">
<Switch
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="encrypted file"
android:id="@+id/qhybrid_switch_encrypted_file" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="download file"
android:id="@+id/qhybrid_button_download_file" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="upload file"
android:id="@+id/qhybrid_button_upload_file" />
</LinearLayout>
</RelativeLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -118,4 +118,11 @@
</LinearLayout> </LinearLayout>
<Button
android:id="@+id/qhybrid_file_management_trigger"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="File management" />
</LinearLayout> </LinearLayout>