mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2025-01-25 00:57:33 +01:00
Pebble app installation: first successful installation :)
KNOWN PROBLEMS - expected filenames inside pbw files are hardcoded (pebble-app.bin etc) - long delay before installation starts - must be in app mananger at least once before installation in possible - errors while installing are not always recognized
This commit is contained in:
parent
3498ddfc7a
commit
ebdf514c0e
@ -351,9 +351,10 @@ public class BluetoothCommunicationService extends Service {
|
||||
mGBDeviceIoThread.write(mGBDeviceProtocol.encodeAppDelete(id, index));
|
||||
} else if (action.equals(ACTION_INSTALL_PEBBLEAPP)) {
|
||||
String uriString = intent.getStringExtra("app_uri");
|
||||
if (uriString != null && mGBDevice.getFreeAppSlot() != -1) {
|
||||
Log.i(TAG, "will try to install app in slot " + mGBDevice.getFreeAppSlot());
|
||||
((PebbleIoThread) mGBDeviceIoThread).installApp(Uri.parse(uriString));
|
||||
int slot = mGBDevice.getFreeAppSlot();
|
||||
if (uriString != null && slot != -1) {
|
||||
Log.i(TAG, "will try to install app in slot " + slot);
|
||||
((PebbleIoThread) mGBDeviceIoThread).installApp(Uri.parse(uriString), slot);
|
||||
}
|
||||
} else if (action.equals(ACTION_START)) {
|
||||
startForeground(NOTIFICATION_ID, createNotification("Gadgetbridge running"));
|
||||
@ -449,10 +450,7 @@ public class BluetoothCommunicationService extends Service {
|
||||
APP_UPLOAD_COMMIT,
|
||||
APP_WAIT_COMMMIT,
|
||||
APP_UPLOAD_COMPLETE,
|
||||
RES_START_INSTALL,
|
||||
RES_WAIT_TOKEN,
|
||||
RES_UPLOAD_CHUNK,
|
||||
RES_UPLOAD_COMPLETE,
|
||||
APP_REFRESH,
|
||||
}
|
||||
|
||||
private class PebbleIoThread extends GBDeviceIoThread {
|
||||
@ -471,6 +469,9 @@ public class BluetoothCommunicationService extends Service {
|
||||
private ZipInputStream mmZis = null;
|
||||
private STM32CRC mmSTM32CRC = new STM32CRC();
|
||||
private PebbleAppInstallState mmInstallState = PebbleAppInstallState.UNKNOWN;
|
||||
private String[] mmFilesToInstall = null;
|
||||
private int mmCurrentFileIndex = -1;
|
||||
private int mmInstallSlot = -1;
|
||||
|
||||
public PebbleIoThread(String btDeviceAddress) {
|
||||
super(btDeviceAddress);
|
||||
@ -514,10 +515,33 @@ public class BluetoothCommunicationService extends Service {
|
||||
case APP_START_INSTALL:
|
||||
Log.i(TAG, "start installing app binary");
|
||||
mmSTM32CRC.reset();
|
||||
mmPBWReader = new PBWReader(mmInstallURI, getApplicationContext());
|
||||
mmZis = mmPBWReader.getInputStreamAppBinary();
|
||||
int binarySize = mmPBWReader.getAppBinarySize();
|
||||
writeInstallApp(mmPebbleProtocol.encodeUploadStart(PebbleProtocol.PUTBYTES_TYPE_BINARY, mGBDevice.getFreeAppSlot(), binarySize), -1);
|
||||
if (mmPBWReader == null) {
|
||||
mmPBWReader = new PBWReader(mmInstallURI, getApplicationContext());
|
||||
mmFilesToInstall = mmPBWReader.getFilesToInstall();
|
||||
mmCurrentFileIndex = 0;
|
||||
}
|
||||
String fileName = mmFilesToInstall[mmCurrentFileIndex];
|
||||
mmZis = mmPBWReader.getInputStreamFile(fileName);
|
||||
int binarySize = mmPBWReader.getFileSize(fileName);
|
||||
// FIXME: do not assume type from filename, parse json correctly in PBWReader
|
||||
byte type = -1;
|
||||
if (fileName.equals("pebble-app.bin")) {
|
||||
type = PebbleProtocol.PUTBYTES_TYPE_BINARY;
|
||||
} else if (fileName.equals("pebble-worker.bin")) {
|
||||
type = PebbleProtocol.PUTBYTES_TYPE_WORKER;
|
||||
} else if (fileName.equals("app_resources.pbpack")) {
|
||||
type = PebbleProtocol.PUTBYTES_TYPE_RESOURCES;
|
||||
} else {
|
||||
// FIXME: proper state for cancellation
|
||||
mmInstallState = PebbleAppInstallState.UNKNOWN;
|
||||
mmPBWReader = null;
|
||||
mmIsInstalling = false;
|
||||
mmZis = null;
|
||||
mmAppInstallToken = -1;
|
||||
mmInstallSlot = -1;
|
||||
}
|
||||
|
||||
writeInstallApp(mmPebbleProtocol.encodeUploadStart(type, (byte)mmInstallSlot, binarySize), -1);
|
||||
mmInstallState = PebbleAppInstallState.APP_WAIT_TOKEN;
|
||||
break;
|
||||
case APP_WAIT_TOKEN:
|
||||
@ -540,24 +564,33 @@ public class BluetoothCommunicationService extends Service {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case APP_UPLOAD_COMMIT:
|
||||
writeInstallApp(mmPebbleProtocol.encodeUploadCommit(mmAppInstallToken, mmSTM32CRC.getResult()),-1);
|
||||
mmAppInstallToken = -1;
|
||||
mmInstallState = PebbleAppInstallState.APP_WAIT_COMMMIT;
|
||||
case APP_UPLOAD_COMMIT:
|
||||
writeInstallApp(mmPebbleProtocol.encodeUploadCommit(mmAppInstallToken, mmSTM32CRC.getResult()), -1);
|
||||
mmAppInstallToken = -1;
|
||||
mmInstallState = PebbleAppInstallState.APP_WAIT_COMMMIT;
|
||||
break;
|
||||
case APP_WAIT_COMMMIT:
|
||||
if (mmAppInstallToken != -1) {
|
||||
Log.i(TAG, "got token " + mmAppInstallToken);
|
||||
mmInstallState = PebbleAppInstallState.APP_UPLOAD_COMPLETE;
|
||||
continue;
|
||||
}
|
||||
case APP_WAIT_COMMMIT:
|
||||
if (mmAppInstallToken != -1) {
|
||||
Log.i(TAG, "got token " + mmAppInstallToken);
|
||||
mmInstallState = PebbleAppInstallState.APP_UPLOAD_COMPLETE;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case APP_UPLOAD_COMPLETE:
|
||||
writeInstallApp(mmPebbleProtocol.encodeUploadComplete(mmAppInstallToken),-1);
|
||||
mmInstallState = PebbleAppInstallState.UNKNOWN;
|
||||
writeInstallApp(mmPebbleProtocol.encodeUploadComplete(mmAppInstallToken), -1);
|
||||
if (++mmCurrentFileIndex < mmFilesToInstall.length) {
|
||||
mmInstallState = PebbleAppInstallState.APP_START_INSTALL;
|
||||
} else {
|
||||
mmInstallState = PebbleAppInstallState.APP_REFRESH;
|
||||
}
|
||||
break;
|
||||
case APP_REFRESH:
|
||||
writeInstallApp(mmPebbleProtocol.encodeAppRefresh(mmInstallSlot), -1);
|
||||
mmPBWReader = null;
|
||||
mmIsInstalling = false;
|
||||
mmZis = null;
|
||||
mmAppInstallToken = -1;
|
||||
mmInstallSlot = -1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -690,10 +723,14 @@ public class BluetoothCommunicationService extends Service {
|
||||
}
|
||||
}
|
||||
|
||||
public void installApp(Uri uri) {
|
||||
public void installApp(Uri uri, int slot) {
|
||||
if (mmIsInstalling) {
|
||||
return;
|
||||
}
|
||||
mmInstallState = PebbleAppInstallState.APP_START_INSTALL;
|
||||
mmIsInstalling = true;
|
||||
mmInstallURI = uri;
|
||||
mmInstallSlot = slot;
|
||||
mmIsInstalling = true;
|
||||
}
|
||||
|
||||
public void quit() {
|
||||
|
@ -12,6 +12,7 @@ import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
@ -21,6 +22,7 @@ public class PBWReader {
|
||||
private GBDeviceApp app;
|
||||
private final Uri uri;
|
||||
private final ContentResolver cr;
|
||||
private ArrayList<String> filesToInstall;
|
||||
|
||||
public PBWReader(Uri uri, Context context) {
|
||||
this.uri = uri;
|
||||
@ -36,9 +38,13 @@ public class PBWReader {
|
||||
}
|
||||
ZipInputStream zis = new ZipInputStream(fin);
|
||||
ZipEntry ze = null;
|
||||
filesToInstall = new ArrayList<String>();
|
||||
try {
|
||||
while ((ze = zis.getNextEntry()) != null) {
|
||||
if (ze.getName().equals("appinfo.json")) {
|
||||
String fileName = ze.getName();
|
||||
if (fileName.equals("pebble-app.bin") || fileName.equals("pebble-worker.bin") || fileName.equals("app_resources.pbpack")) {
|
||||
filesToInstall.add(fileName); // FIXME: do not hardcode filenames above
|
||||
} else if (fileName.equals("appinfo.json")) {
|
||||
long bytes = ze.getSize();
|
||||
if (bytes > 8192) // that should be too much
|
||||
break;
|
||||
@ -127,28 +133,8 @@ public class PBWReader {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public ZipInputStream getInputStreamAppBinary() {
|
||||
return getInputStreamFile("pebble-app.bin");
|
||||
}
|
||||
|
||||
public int getAppBinarySize() {
|
||||
return getFileSize("pebble-app.bin");
|
||||
}
|
||||
|
||||
public ZipInputStream getInputStreamAppWorker() {
|
||||
return getInputStreamFile("pebble-worker.bin");
|
||||
}
|
||||
|
||||
public int getAppWorkerSize() {
|
||||
return getFileSize("pebble-worker.bin");
|
||||
}
|
||||
|
||||
public ZipInputStream getInputStreamAppResources() {
|
||||
return getInputStreamFile("app_resources.pbpack");
|
||||
}
|
||||
|
||||
public int getAppResourcesSize() {
|
||||
return getFileSize("pebble-resources.pbpack");
|
||||
public String[] getFilesToInstall() {
|
||||
return filesToInstall.toArray(new String[filesToInstall.size()]);
|
||||
}
|
||||
|
||||
}
|
@ -34,8 +34,8 @@ public class PebbleAppInstallerActivity extends Activity {
|
||||
debugTextView.setText("contents:\n");
|
||||
final Uri uri = getIntent().getData();
|
||||
PBWReader pbwReader = new PBWReader(uri, getApplicationContext());
|
||||
|
||||
GBDeviceApp app = pbwReader.getGBDeviceApp();
|
||||
|
||||
if (pbwReader != null && app != null) {
|
||||
debugTextView.setText("This is just a test, you cant install anything yet \n\n" + app.getName() + " Version " + app.getVersion() + " by " + app.getCreator() + "\n");
|
||||
installButton.setEnabled(true);
|
||||
|
@ -71,6 +71,7 @@ public class PebbleProtocol extends GBDeviceProtocol {
|
||||
|
||||
static final byte APPMANAGER_GETAPPBANKSTATUS = 1;
|
||||
static final byte APPMANAGER_REMOVEAPP = 2;
|
||||
static final byte APPMANAGER_REFRESHAPP = 3;
|
||||
|
||||
static final int APPMANAGER_RES_SUCCESS = 1;
|
||||
|
||||
@ -83,10 +84,10 @@ public class PebbleProtocol extends GBDeviceProtocol {
|
||||
static final byte PUTBYTES_TYPE_FIRMWARE = 1;
|
||||
static final byte PUTBYTES_TYPE_RECOVERY = 2;
|
||||
static final byte PUTBYTES_TYPE_SYSRESOURCES = 3;
|
||||
static final byte PUTBYTES_TYPE_RESOURCES = 4;
|
||||
public static final byte PUTBYTES_TYPE_RESOURCES = 4;
|
||||
public static final byte PUTBYTES_TYPE_BINARY = 5;
|
||||
static final byte PUTBYTES_TYPE_FILE = 6;
|
||||
static final byte PUTBYTES_TYPE_WORKER = 7;
|
||||
public static final byte PUTBYTES_TYPE_WORKER = 7;
|
||||
|
||||
static final byte PHONEVERSION_APPVERSION_MAGIC = 2; // increase this if pebble complains
|
||||
static final byte PHONEVERSION_APPVERSION_MAJOR = 2;
|
||||
@ -94,7 +95,7 @@ public class PebbleProtocol extends GBDeviceProtocol {
|
||||
static final byte PHONEVERSION_APPVERSION_PATCH = 0;
|
||||
|
||||
|
||||
static final int PHONEVERSION_SESSION_CAPS_GAMMARAY = (int)0x80000000;
|
||||
static final int PHONEVERSION_SESSION_CAPS_GAMMARAY = (int) 0x80000000;
|
||||
|
||||
static final int PHONEVERSION_REMOTE_CAPS_TELEPHONY = 0x00000010;
|
||||
static final int PHONEVERSION_REMOTE_CAPS_SMS = 0x00000020;
|
||||
@ -116,6 +117,7 @@ public class PebbleProtocol extends GBDeviceProtocol {
|
||||
static final short LENGTH_PREFIX = 4;
|
||||
static final short LENGTH_SETTIME = 5;
|
||||
static final short LENGTH_REMOVEAPP = 9;
|
||||
static final short LENGTH_REFRESHAPP = 5;
|
||||
static final short LENGTH_PHONEVERSION = 17;
|
||||
static final short LENGTH_UPLOADSTART = 7;
|
||||
static final short LENGTH_UPLOADCHUNK = 9;
|
||||
@ -329,6 +331,16 @@ public class PebbleProtocol extends GBDeviceProtocol {
|
||||
return buf.array();
|
||||
}
|
||||
|
||||
public byte[] encodeAppRefresh(int index) {
|
||||
ByteBuffer buf = ByteBuffer.allocate(LENGTH_PREFIX + LENGTH_REFRESHAPP);
|
||||
buf.order(ByteOrder.BIG_ENDIAN);
|
||||
buf.putShort(LENGTH_REFRESHAPP);
|
||||
buf.putShort(ENDPOINT_APPMANAGER);
|
||||
buf.put(APPMANAGER_REFRESHAPP);
|
||||
buf.putInt(index);
|
||||
|
||||
return buf.array();
|
||||
}
|
||||
|
||||
public GBDeviceCommand decodeResponse(byte[] responseData) {
|
||||
ByteBuffer buf = ByteBuffer.wrap(responseData);
|
||||
|
Loading…
x
Reference in New Issue
Block a user