mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-11-27 20:36:51 +01:00
Fossil/Skagen Hybrids: Add app/watchface downloading from watch to app manager
This commit is contained in:
parent
82dac7177e
commit
845887ddeb
@ -17,6 +17,8 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.activities.appmanager;
|
||||
|
||||
import static nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSupport.QHYBRID_ACTION_DOWNLOADED_FILE;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.BroadcastReceiver;
|
||||
@ -34,6 +36,7 @@ import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.PopupMenu;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
|
||||
@ -57,7 +60,11 @@ import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.ExternalPebbleJSActivity;
|
||||
import nodomain.freeyourgadget.gadgetbridge.adapter.GBDeviceAppAdapter;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.FileManagementActivity;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.FossilFileReader;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.FossilHRInstallHandler;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.QHybridConstants;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.QHybridCoordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceApp;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.DeviceService;
|
||||
@ -65,6 +72,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.pebble.PebbleProtocol;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GridAutoFitLayoutManager;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.PebbleUtils;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.Version;
|
||||
@ -142,6 +150,7 @@ public abstract class AbstractAppManagerFragment extends Fragment {
|
||||
app.setUpToDate(false);
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
LOG.warn("App JSON: " + app.getJSON().toString());
|
||||
LOG.warn("Couldn't read app version", e);
|
||||
}
|
||||
if (filterApp(app)) {
|
||||
@ -174,19 +183,55 @@ public abstract class AbstractAppManagerFragment extends Fragment {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
String action = intent.getAction();
|
||||
if (action.equals(ACTION_REFRESH_APPLIST)) {
|
||||
if (intent.hasExtra("app_count")) {
|
||||
LOG.info("got app info from device");
|
||||
if (!isCacheManager()) {
|
||||
LOG.info("will refresh list based on data from device");
|
||||
refreshListFromDevice(intent);
|
||||
switch (action) {
|
||||
case ACTION_REFRESH_APPLIST: {
|
||||
if (intent.hasExtra("app_count")) {
|
||||
LOG.info("got app info from device");
|
||||
if (!isCacheManager()) {
|
||||
LOG.info("will refresh list based on data from device");
|
||||
refreshListFromDevice(intent);
|
||||
}
|
||||
} else if (mCoordinator.supportsAppListFetching()) {
|
||||
refreshList();
|
||||
} else if (isCacheManager()) {
|
||||
refreshList();
|
||||
}
|
||||
} else if (mCoordinator.supportsAppListFetching()) {
|
||||
refreshList();
|
||||
} else if (isCacheManager()) {
|
||||
refreshList();
|
||||
mGBDeviceAppAdapter.notifyDataSetChanged();
|
||||
break;
|
||||
}
|
||||
case QHYBRID_ACTION_DOWNLOADED_FILE: {
|
||||
if (!intent.getBooleanExtra("EXTRA_SUCCESS", false)) {
|
||||
LOG.warn("wapp download was not successful");
|
||||
GB.toast(context.getString(R.string.appmanager_download_app_error), Toast.LENGTH_LONG, GB.ERROR);
|
||||
break;
|
||||
}
|
||||
if (!intent.getBooleanExtra("EXTRA_TOCACHE", false)) {
|
||||
break;
|
||||
}
|
||||
String path = intent.getStringExtra("EXTRA_PATH");
|
||||
String name = intent.getStringExtra("EXTRA_NAME");
|
||||
LOG.info("Attempting to add downloaded app " + name + " to cache");
|
||||
FossilFileReader fileReader;
|
||||
try {
|
||||
fileReader = new FossilFileReader(Uri.fromFile(new File(path)), context);
|
||||
} catch (IOException e) {
|
||||
LOG.warn("Could not find downloaded wapp", e);
|
||||
break;
|
||||
}
|
||||
if (FossilHRInstallHandler.saveAppInCache(fileReader, fileReader.getBackground(), fileReader.getPreview(), mCoordinator, context)) {
|
||||
LOG.info("Successfully moved downloaded app " + name + " to cache");
|
||||
GB.toast(String.format(context.getString(R.string.appmanager_downloaded_to_cache), name), Toast.LENGTH_LONG, GB.INFO);
|
||||
if (isCacheManager()) {
|
||||
refreshList();
|
||||
mGBDeviceAppAdapter.notifyDataSetChanged();
|
||||
}
|
||||
(new File(path)).delete();
|
||||
} else {
|
||||
LOG.warn("Parsing downloaded wapp was not successful");
|
||||
GB.toast(context.getString(R.string.appmanager_download_app_error), Toast.LENGTH_LONG, GB.ERROR);
|
||||
}
|
||||
break;
|
||||
}
|
||||
mGBDeviceAppAdapter.notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -306,6 +351,7 @@ public abstract class AbstractAppManagerFragment extends Fragment {
|
||||
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(ACTION_REFRESH_APPLIST);
|
||||
filter.addAction(QHYBRID_ACTION_DOWNLOADED_FILE);
|
||||
|
||||
LocalBroadcastManager.getInstance(getContext()).registerReceiver(mReceiver, filter);
|
||||
|
||||
@ -401,12 +447,7 @@ public abstract class AbstractAppManagerFragment extends Fragment {
|
||||
}
|
||||
|
||||
public void onItemClick(View view, GBDeviceApp deviceApp) {
|
||||
if (isCacheManager()) {
|
||||
openPopupMenu(view, deviceApp);
|
||||
} else {
|
||||
UUID uuid = deviceApp.getUUID();
|
||||
GBApplication.deviceService(mGBDevice).onAppStart(uuid, true);
|
||||
}
|
||||
openPopupMenu(view, deviceApp);
|
||||
}
|
||||
|
||||
public boolean openPopupMenu(View view, GBDeviceApp deviceApp) {
|
||||
@ -415,6 +456,12 @@ public abstract class AbstractAppManagerFragment extends Fragment {
|
||||
Menu menu = popupMenu.getMenu();
|
||||
final GBDeviceApp selectedApp = deviceApp;
|
||||
|
||||
if (!selectedApp.isOnDevice() || selectedApp.getType() != GBDeviceApp.Type.WATCHFACE) {
|
||||
menu.removeItem(R.id.appmanager_watchface_activate);
|
||||
}
|
||||
if (!selectedApp.isOnDevice() || selectedApp.getType() != GBDeviceApp.Type.APP_GENERIC) {
|
||||
menu.removeItem(R.id.appmanager_app_start);
|
||||
}
|
||||
if (!selectedApp.isInCache()) {
|
||||
menu.removeItem(R.id.appmanager_app_edit);
|
||||
menu.removeItem(R.id.appmanager_app_reinstall);
|
||||
@ -455,6 +502,9 @@ public abstract class AbstractAppManagerFragment extends Fragment {
|
||||
if ((mGBDevice.getType() != DeviceType.FOSSILQHYBRID) || (selectedApp.getType() != GBDeviceApp.Type.WATCHFACE)) {
|
||||
menu.removeItem(R.id.appmanager_app_edit);
|
||||
}
|
||||
if ((mGBDevice.getType() != DeviceType.FOSSILQHYBRID) || (!selectedApp.isOnDevice()) || ((selectedApp.getType() != GBDeviceApp.Type.WATCHFACE) && (selectedApp.getType() != GBDeviceApp.Type.APP_GENERIC))) {
|
||||
menu.removeItem(R.id.appmanager_app_download);
|
||||
}
|
||||
|
||||
if (mGBDevice.getType() == DeviceType.PEBBLE) {
|
||||
switch (selectedApp.getType()) {
|
||||
@ -514,6 +564,14 @@ public abstract class AbstractAppManagerFragment extends Fragment {
|
||||
}
|
||||
GBApplication.deviceService(mGBDevice).onAppDelete(selectedApp.getUUID());
|
||||
return true;
|
||||
case R.id.appmanager_app_start:
|
||||
case R.id.appmanager_watchface_activate:
|
||||
GBApplication.deviceService(mGBDevice).onAppStart(selectedApp.getUUID(), true);
|
||||
return true;
|
||||
case R.id.appmanager_app_download:
|
||||
GBApplication.deviceService(mGBDevice).onAppDownload(selectedApp.getUUID());
|
||||
GB.toast(getContext().getString(R.string.appmanager_download_started), Toast.LENGTH_LONG, GB.INFO);
|
||||
return true;
|
||||
case R.id.appmanager_app_reinstall:
|
||||
File cachePath = new File(appCacheDir, selectedApp.getUUID() + mCoordinator.getAppFileExtension());
|
||||
GBApplication.deviceService(mGBDevice).onInstallApp(Uri.fromFile(cachePath));
|
||||
|
@ -76,6 +76,8 @@ public interface EventHandler {
|
||||
|
||||
void onAppStart(UUID uuid, boolean start);
|
||||
|
||||
void onAppDownload(UUID uuid);
|
||||
|
||||
void onAppDelete(UUID uuid);
|
||||
|
||||
void onAppConfiguration(UUID appUuid, String config, Integer id);
|
||||
|
@ -175,7 +175,9 @@ public class FileManagementActivity extends AbstractGBActivity implements View.O
|
||||
Intent fileIntent = new Intent();
|
||||
fileIntent.putExtra("EXTRA_ENCRYPTED", isEncrypted);
|
||||
fileIntent.setAction(QHybridSupport.QHYBRID_COMMAND_DOWNLOAD_FILE);
|
||||
fileIntent.putExtra("EXTRA_HANDLE", (FileHandle) fileTypesSpinner.getSelectedItem());
|
||||
fileIntent.putExtra("EXTRA_MAJORHANDLE", ((FileHandle) fileTypesSpinner.getSelectedItem()).getMajorHandle());
|
||||
fileIntent.putExtra("EXTRA_MINORHANDLE", ((FileHandle) fileTypesSpinner.getSelectedItem()).getMinorHandle());
|
||||
fileIntent.putExtra("EXTRA_NAME", ((FileHandle) fileTypesSpinner.getSelectedItem()).name());
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(fileIntent);
|
||||
} else if (v.getId() == R.id.qhybrid_button_upload_file) {
|
||||
Intent chooserIntent = new Intent()
|
||||
|
@ -102,7 +102,6 @@ public class FossilHRInstallHandler implements InstallHandler {
|
||||
installActivity.setInstallItem(installItem);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onStartInstall(GBDevice device) {
|
||||
DeviceCoordinator mCoordinator = DeviceHelper.getInstance().getCoordinator(device);
|
||||
@ -116,7 +115,7 @@ public class FossilHRInstallHandler implements InstallHandler {
|
||||
manager.sendBroadcast(new Intent(AbstractAppManagerFragment.ACTION_REFRESH_APPLIST));
|
||||
}
|
||||
|
||||
public static void saveAppInCache(FossilFileReader fossilFile, Bitmap backgroundImg, Bitmap previewImg, DeviceCoordinator mCoordinator, Context mContext) {
|
||||
public static boolean saveAppInCache(FossilFileReader fossilFile, Bitmap backgroundImg, Bitmap previewImg, DeviceCoordinator mCoordinator, Context mContext) {
|
||||
GBDeviceApp app;
|
||||
File destDir;
|
||||
// write app file
|
||||
@ -127,7 +126,7 @@ public class FossilHRInstallHandler implements InstallHandler {
|
||||
FileUtils.copyURItoFile(mContext, fossilFile.getUri(), new File(destDir, app.getUUID().toString() + mCoordinator.getAppFileExtension()));
|
||||
} catch (IOException e) {
|
||||
LOG.error("Saving app in cache failed: " + e.getMessage(), e);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
// write app metadata
|
||||
File outputFile = new File(destDir, app.getUUID().toString() + ".json");
|
||||
@ -136,7 +135,7 @@ public class FossilHRInstallHandler implements InstallHandler {
|
||||
writer = new BufferedWriter(new FileWriter(outputFile));
|
||||
} catch (IOException e) {
|
||||
LOG.error("Failed to open output file: " + e.getMessage(), e);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
LOG.info(app.getJSON().toString());
|
||||
@ -150,8 +149,10 @@ public class FossilHRInstallHandler implements InstallHandler {
|
||||
writer.close();
|
||||
} catch (IOException e) {
|
||||
LOG.error("Failed to write to output file: " + e.getMessage(), e);
|
||||
return false;
|
||||
} catch (JSONException e) {
|
||||
LOG.error(e.getMessage(), e);
|
||||
LOG.error("Failed to load or write appKeys JSON: " + e.getMessage(), e);
|
||||
return false;
|
||||
}
|
||||
// write watchface background image
|
||||
if (backgroundImg != null) {
|
||||
@ -162,6 +163,7 @@ public class FossilHRInstallHandler implements InstallHandler {
|
||||
fos.close();
|
||||
} catch (IOException e) {
|
||||
LOG.error("Failed to write to output file: " + e.getMessage(), e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// write watchface preview image
|
||||
@ -173,8 +175,10 @@ public class FossilHRInstallHandler implements InstallHandler {
|
||||
fos.close();
|
||||
} catch (IOException e) {
|
||||
LOG.error("Failed to write to output file: " + e.getMessage(), e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -301,6 +301,13 @@ public class GBDeviceService implements DeviceService {
|
||||
invokeService(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAppDownload(UUID uuid) {
|
||||
Intent intent = createIntent().setAction(ACTION_DOWNLOADAPP)
|
||||
.putExtra(EXTRA_APP_UUID, uuid);
|
||||
invokeService(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAppDelete(UUID uuid) {
|
||||
Intent intent = createIntent().setAction(ACTION_DELETEAPP)
|
||||
|
@ -44,6 +44,7 @@ public interface DeviceService extends EventHandler {
|
||||
String ACTION_REQUEST_APPINFO = PREFIX + ".action.request_appinfo";
|
||||
String ACTION_REQUEST_SCREENSHOT = PREFIX + ".action.request_screenshot";
|
||||
String ACTION_STARTAPP = PREFIX + ".action.startapp";
|
||||
String ACTION_DOWNLOADAPP = PREFIX + ".action.downloadapp";
|
||||
String ACTION_DELETEAPP = PREFIX + ".action.deleteapp";
|
||||
String ACTION_APP_CONFIGURE = PREFIX + ".action.app_configure";
|
||||
String ACTION_APP_REORDER = PREFIX + ".action.app_reorder";
|
||||
|
@ -748,6 +748,16 @@ public abstract class AbstractDeviceSupport implements DeviceSupport {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* If apps can be downloaded from the device, this method can be
|
||||
* overridden and implemented by the device support class.
|
||||
* @param uuid the Gadgetbridge internal UUID of the app
|
||||
*/
|
||||
@Override
|
||||
public void onAppDownload(UUID uuid) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* If apps on the device can be deleted with a command, this method
|
||||
* can be overridden and implemented by the device support class.
|
||||
|
@ -134,6 +134,7 @@ import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_SE
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_SET_WORLD_CLOCKS;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_START;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_STARTAPP;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_DOWNLOADAPP;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_TEST_NEW_FUNCTION;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_ALARMS;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_APP_CONFIG;
|
||||
@ -847,6 +848,11 @@ public class DeviceCommunicationService extends Service implements SharedPrefere
|
||||
deviceSupport.onAppStart(uuid, start);
|
||||
break;
|
||||
}
|
||||
case ACTION_DOWNLOADAPP: {
|
||||
UUID uuid = (UUID) intent.getSerializableExtra(EXTRA_APP_UUID);
|
||||
deviceSupport.onAppDownload(uuid);
|
||||
break;
|
||||
}
|
||||
case ACTION_DELETEAPP: {
|
||||
UUID uuid = (UUID) intent.getSerializableExtra(EXTRA_APP_UUID);
|
||||
deviceSupport.onAppDelete(uuid);
|
||||
|
@ -251,6 +251,14 @@ public class ServiceDeviceSupport implements DeviceSupport {
|
||||
delegate.onAppStart(uuid, start);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAppDownload(UUID uuid) {
|
||||
if (checkBusy("app download")) {
|
||||
return;
|
||||
}
|
||||
delegate.onAppDownload(uuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAppDelete(UUID uuid) {
|
||||
if (checkBusy("app delete")) {
|
||||
|
@ -284,10 +284,10 @@ public class QHybridSupport extends QHybridBaseSupport {
|
||||
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));
|
||||
byte majorHandle = intent.getByteExtra("EXTRA_MAJORHANDLE", (byte) 0x00);
|
||||
byte minorHandle = intent.getByteExtra("EXTRA_MINORHANDLE", (byte) 0x00);
|
||||
String filename = intent.getStringExtra("EXTRA_NAME");
|
||||
watchAdapter.downloadFile(majorHandle, minorHandle, filename, intent.getBooleanExtra("EXTRA_ENCRYPTED", false), false);
|
||||
break;
|
||||
}
|
||||
case QHYBRID_COMMAND_UPLOAD_FILE:{
|
||||
@ -833,6 +833,11 @@ public class QHybridSupport extends QHybridBaseSupport {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAppDownload(UUID uuid) {
|
||||
((FossilHRWatchAdapter) watchAdapter).downloadAppToCache(uuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAppDelete(UUID uuid) {
|
||||
if(this.watchAdapter instanceof FossilHRWatchAdapter) {
|
||||
|
@ -147,7 +147,7 @@ public abstract class WatchAdapter {
|
||||
public void onDeleteNotification(int id) {
|
||||
}
|
||||
|
||||
public void downloadFile(FileHandle handle, boolean fileIsEncrypted) {
|
||||
public void downloadFile(byte majorHandle, byte minorHandle, String name, boolean fileIsEncrypted, boolean toCache) {
|
||||
}
|
||||
|
||||
public void uploadFileGenerateHeader(FileHandle handle, String filePath, boolean fileIsEncrypted) {
|
||||
|
@ -486,6 +486,16 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
public void downloadAppToCache(UUID uuid) {
|
||||
LOG.info("Going to download app with UUID " + uuid.toString());
|
||||
for (ApplicationInformation appInfo : installedApplications) {
|
||||
if (UUID.nameUUIDFromBytes(appInfo.getAppName().getBytes(StandardCharsets.UTF_8)).equals(uuid)) {
|
||||
LOG.info("Going to download app with name " + appInfo.getAppName() + " and handle " + appInfo.getFileHandle());
|
||||
downloadFile(FileHandle.APP_CODE.getMajorHandle(), appInfo.getFileHandle(), appInfo.getAppName(), false, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setVibrationStrengthFromConfig() {
|
||||
Prefs prefs = new Prefs(getDeviceSpecificPreferences());
|
||||
int vibrationStrengh = prefs.getInt(DeviceSettingsPreferenceConst.PREF_VIBRATION_STRENGH_PERCENTAGE, 2);
|
||||
@ -920,15 +930,18 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
private void handleFileDownload(FileHandle handle, byte[] file) {
|
||||
private void handleFileDownload(String name, byte[] file, boolean toCache) {
|
||||
Intent resultIntent = new Intent(QHybridSupport.QHYBRID_ACTION_DOWNLOADED_FILE);
|
||||
File outputFile = new File(getContext().getExternalFilesDir("download"), handle.name() + "_" + System.currentTimeMillis() + ".bin");
|
||||
File outputFile = new File(getContext().getExternalFilesDir("download"), 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());
|
||||
resultIntent.putExtra("EXTRA_NAME", name);
|
||||
resultIntent.putExtra("EXTRA_TOCACHE", toCache);
|
||||
LOG.info("Wrote downloaded file to " + outputFile.getAbsolutePath());
|
||||
} catch (IOException e) {
|
||||
LOG.error("Error while downloading file", e);
|
||||
resultIntent.putExtra("EXTRA_SUCCESS", false);
|
||||
@ -1002,21 +1015,21 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void downloadFile(final FileHandle handle, boolean fileIsEncrypted) {
|
||||
public void downloadFile(byte majorHandle, byte minorHandle, String name, boolean fileIsEncrypted, boolean toCache) {
|
||||
if (fileIsEncrypted) {
|
||||
queueWrite((FileEncryptedInterface) new FileEncryptedGetRequest(handle, this) {
|
||||
queueWrite((FileEncryptedInterface) new FileEncryptedGetRequest(majorHandle, minorHandle, this) {
|
||||
@Override
|
||||
public void handleFileData(byte[] fileData) {
|
||||
LOG.debug("downloaded encrypted file");
|
||||
handleFileDownload(handle, fileData);
|
||||
handleFileDownload(name, fileData, toCache);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
queueWrite(new FileGetRawRequest(handle, this) {
|
||||
queueWrite(new FileGetRawRequest(majorHandle, minorHandle, this) {
|
||||
@Override
|
||||
public void handleFileRawData(byte[] fileData) {
|
||||
LOG.debug("downloaded regular file");
|
||||
handleFileDownload(handle, fileData);
|
||||
handleFileDownload(name, fileData, toCache);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -24,12 +24,14 @@ import java.util.UUID;
|
||||
import java.util.zip.CRC32;
|
||||
|
||||
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.file.FileHandle;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.FossilRequest;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.file.ResultCode;
|
||||
|
||||
public abstract class FileGetRawRequest extends FossilRequest {
|
||||
private short handle;
|
||||
private byte majorHandle;
|
||||
private byte minorHandle;
|
||||
private FossilWatchAdapter adapter;
|
||||
|
||||
private ByteBuffer fileBuffer;
|
||||
@ -38,20 +40,26 @@ public abstract class FileGetRawRequest extends FossilRequest {
|
||||
|
||||
private boolean finished = false;
|
||||
|
||||
public FileGetRawRequest(short handle, FossilWatchAdapter adapter) {
|
||||
this.handle = handle;
|
||||
public FileGetRawRequest(byte majorHandle, byte minorHandle, FossilWatchAdapter adapter) {
|
||||
this.majorHandle = majorHandle;
|
||||
this.minorHandle = minorHandle;
|
||||
this.adapter = adapter;
|
||||
|
||||
this.data =
|
||||
createBuffer()
|
||||
.putShort(handle)
|
||||
.put(minorHandle)
|
||||
.put(majorHandle)
|
||||
.putInt(0)
|
||||
.putInt(0xFFFFFFFF)
|
||||
.array();
|
||||
}
|
||||
|
||||
public FileGetRawRequest(FileHandle handle, FossilWatchAdapter adapter){
|
||||
this(handle.getHandle(), adapter);
|
||||
public FileGetRawRequest(FileHandle handle, FossilWatchAdapter adapter) {
|
||||
this(handle.getMajorHandle(), handle.getMinorHandle(), adapter);
|
||||
}
|
||||
|
||||
public FileGetRawRequest(short handle, FossilWatchAdapter adapter) {
|
||||
this((byte) ((handle >> 8) & 0xff), (byte) (handle), adapter);
|
||||
}
|
||||
|
||||
public FossilWatchAdapter getAdapter() {
|
||||
@ -72,7 +80,8 @@ public abstract class FileGetRawRequest extends FossilRequest {
|
||||
ByteBuffer buffer = ByteBuffer.wrap(value);
|
||||
buffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
short handle = buffer.getShort(1);
|
||||
short minorHandle = buffer.get(1);
|
||||
short majorHandle = buffer.get(2);
|
||||
int size = buffer.getInt(4);
|
||||
|
||||
byte status = buffer.get(3);
|
||||
@ -82,8 +91,11 @@ public abstract class FileGetRawRequest extends FossilRequest {
|
||||
throw new RuntimeException("FileGet error: " + code + " (" + status + ")");
|
||||
}
|
||||
|
||||
if(this.handle != handle){
|
||||
throw new RuntimeException("handle: " + handle + " expected: " + this.handle);
|
||||
if (this.minorHandle != minorHandle) {
|
||||
throw new RuntimeException("minor handle: " + minorHandle + " expected: " + this.minorHandle);
|
||||
}
|
||||
if (this.majorHandle != majorHandle) {
|
||||
throw new RuntimeException("major handle: " + majorHandle + " expected: " + this.majorHandle);
|
||||
}
|
||||
log("file size: " + size);
|
||||
fileBuffer = ByteBuffer.allocate(size);
|
||||
@ -94,8 +106,11 @@ public abstract class FileGetRawRequest extends FossilRequest {
|
||||
buffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
short handle = buffer.getShort(1);
|
||||
if(this.handle != handle){
|
||||
throw new RuntimeException("handle: " + handle + " expected: " + this.handle);
|
||||
if (this.minorHandle != minorHandle) {
|
||||
throw new RuntimeException("minor handle: " + minorHandle + " expected: " + this.minorHandle);
|
||||
}
|
||||
if (this.majorHandle != majorHandle) {
|
||||
throw new RuntimeException("major handle: " + majorHandle + " expected: " + this.majorHandle);
|
||||
}
|
||||
|
||||
CRC32 crc = new CRC32();
|
||||
@ -104,7 +119,7 @@ public abstract class FileGetRawRequest extends FossilRequest {
|
||||
int crcExpected = buffer.getInt(8);
|
||||
|
||||
if((int) crc.getValue() != crcExpected){
|
||||
throw new RuntimeException("handle: " + handle + " expected: " + this.handle);
|
||||
throw new RuntimeException("crc: " + crc.getValue() + " expected: " + crcExpected);
|
||||
}
|
||||
|
||||
this.handleFileRawData(this.fileData);
|
||||
|
@ -43,7 +43,8 @@ import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.StringUtils;
|
||||
|
||||
public abstract class FileEncryptedGetRequest extends FossilRequest implements FileEncryptedInterface{
|
||||
private short handle;
|
||||
private byte majorHandle;
|
||||
private byte minorHandle;
|
||||
private FossilHRWatchAdapter adapter;
|
||||
|
||||
private ByteBuffer fileBuffer;
|
||||
@ -61,20 +62,22 @@ public abstract class FileEncryptedGetRequest extends FossilRequest implements F
|
||||
private int packetCount = 0;
|
||||
private int ivIncrementor = 0x1f;
|
||||
|
||||
public FileEncryptedGetRequest(short handle, FossilHRWatchAdapter adapter) {
|
||||
this.handle = handle;
|
||||
public FileEncryptedGetRequest(byte majorHandle, byte minorHandle, FossilHRWatchAdapter adapter) {
|
||||
this.majorHandle = majorHandle;
|
||||
this.minorHandle = minorHandle;
|
||||
this.adapter = adapter;
|
||||
|
||||
this.data =
|
||||
createBuffer()
|
||||
.putShort(handle)
|
||||
.put(minorHandle)
|
||||
.put(majorHandle)
|
||||
.putInt(0)
|
||||
.putInt(0xFFFFFFFF)
|
||||
.array();
|
||||
}
|
||||
|
||||
public FileEncryptedGetRequest(FileHandle handle, FossilHRWatchAdapter adapter) {
|
||||
this(handle.getHandle(), adapter);
|
||||
public FileEncryptedGetRequest(short handle, FossilHRWatchAdapter adapter) {
|
||||
this((byte) ((handle >> 8) & 0xff), (byte) (handle), adapter);
|
||||
}
|
||||
|
||||
private void initDecryption() {
|
||||
@ -134,7 +137,8 @@ public abstract class FileEncryptedGetRequest extends FossilRequest implements F
|
||||
|
||||
this.initDecryption();
|
||||
|
||||
short handle = buffer.getShort(1);
|
||||
short minorHandle = buffer.get(1);
|
||||
short majorHandle = buffer.get(2);
|
||||
fileSize = buffer.getInt(4);
|
||||
|
||||
byte status = buffer.get(3);
|
||||
@ -144,8 +148,11 @@ public abstract class FileEncryptedGetRequest extends FossilRequest implements F
|
||||
throw new RuntimeException("FileGet error: " + code + " (" + status + ")");
|
||||
}
|
||||
|
||||
if (this.handle != handle) {
|
||||
throw new RuntimeException("handle: " + handle + " expected: " + this.handle);
|
||||
if (this.minorHandle != minorHandle) {
|
||||
throw new RuntimeException("minor handle: " + minorHandle + " expected: " + this.minorHandle);
|
||||
}
|
||||
if (this.majorHandle != majorHandle) {
|
||||
throw new RuntimeException("major handle: " + majorHandle + " expected: " + this.majorHandle);
|
||||
}
|
||||
log("file size: " + fileSize);
|
||||
fileBuffer = ByteBuffer.allocate(fileSize);
|
||||
@ -156,8 +163,11 @@ public abstract class FileEncryptedGetRequest extends FossilRequest implements F
|
||||
buffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
short handle = buffer.getShort(1);
|
||||
if (this.handle != handle) {
|
||||
throw new RuntimeException("handle: " + handle + " expected: " + this.handle);
|
||||
if (this.minorHandle != minorHandle) {
|
||||
throw new RuntimeException("minor handle: " + minorHandle + " expected: " + this.minorHandle);
|
||||
}
|
||||
if (this.majorHandle != majorHandle) {
|
||||
throw new RuntimeException("major handle: " + majorHandle + " expected: " + this.majorHandle);
|
||||
}
|
||||
|
||||
CRC32 crc = new CRC32();
|
||||
|
@ -1,5 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<item
|
||||
android:id="@+id/appmanager_watchface_activate"
|
||||
android:title="@string/appmanager_watchface_activate"/>
|
||||
<item
|
||||
android:id="@+id/appmanager_app_start"
|
||||
android:title="@string/appmanager_app_start"/>
|
||||
<item
|
||||
android:id="@+id/appmanager_app_edit"
|
||||
android:title="@string/appmanager_app_edit"/>
|
||||
@ -9,6 +15,9 @@
|
||||
<item
|
||||
android:id="@+id/appmanager_app_share"
|
||||
android:title="@string/appmanager_app_share"/>
|
||||
<item
|
||||
android:id="@+id/appmanager_app_download"
|
||||
android:title="@string/appmanager_app_download"/>
|
||||
<item
|
||||
android:id="@+id/appmanager_app_delete"
|
||||
android:title="@string/appmananger_app_delete"/>
|
||||
|
@ -102,6 +102,9 @@
|
||||
<string name="appmanager_cached_watchapps_watchfaces">Apps in cache</string>
|
||||
<string name="appmanager_installed_watchapps">Installed apps</string>
|
||||
<string name="appmanager_installed_watchfaces">Installed watchfaces</string>
|
||||
<string name="appmanager_watchface_activate">Activate</string>
|
||||
<string name="appmanager_app_start">Start</string>
|
||||
<string name="appmanager_app_download">Download to cache</string>
|
||||
<string name="appmananger_app_delete">Delete</string>
|
||||
<string name="appmananger_app_delete_cache">Delete and remove from cache</string>
|
||||
<string name="appmananger_app_reinstall">Reinstall</string>
|
||||
@ -117,6 +120,9 @@
|
||||
<string name="app_configure">Configure</string>
|
||||
<string name="app_move_to_top">Move to top</string>
|
||||
<string name="appmanager_item_outdated">(outdated)</string>
|
||||
<string name="appmanager_download_started">App download started</string>
|
||||
<string name="appmanager_downloaded_to_cache">Downloaded %s to cache</string>
|
||||
<string name="appmanager_download_app_error">Error downloading app</string>
|
||||
<!-- Strings related to AppBlacklist -->
|
||||
<string name="title_activity_notification_management">Notification settings</string>
|
||||
<string name="blacklist_all_for_notifications">Blacklist all for notifications</string>
|
||||
|
Loading…
Reference in New Issue
Block a user