has been a while since I've touched Android!

This commit is contained in:
rusefillc 2022-05-24 20:04:25 -04:00
parent 829de00a21
commit 7f0babed06
7 changed files with 147 additions and 98 deletions

View File

@ -29,12 +29,12 @@ public class DfuUpload {
localDfuImageFileName = localFolder + File.separator + DFU_FILE_NAME;
}
void fileOperation(final TextView mResultView) {
void downloadFileIfNotPresent(final TextView mResultView) {
if (new File(this.localFullFile).exists()) {
mResultView.append(this.BUNDLE_FILE + " found!\n");
mResultView.append(BUNDLE_FILE + " found!\n");
uncompressFile(this.localFullFile, this.localFolder, this.localDfuImageFileName, mResultView);
} else {
mResultView.append(this.BUNDLE_FILE + " not found!\n");
mResultView.append(BUNDLE_FILE + " not found!\n");
new Thread(new Runnable() {
@Override
@ -43,30 +43,15 @@ public class DfuUpload {
ConnectionAndMeta c = new ConnectionAndMeta(BUNDLE_FILE).invoke(ConnectionAndMeta.BASE_URL_LATEST);
ConnectionAndMeta.downloadFile(localFullFile, c, new ConnectionAndMeta.DownloadProgressListener() {
@Override
public void onPercentage(final int currentProgress) {
mResultView.post(new Runnable() {
@Override
public void run() {
mResultView.append("Downloading " + currentProgress + "\n");
}
});
}
});
mResultView.post(new Runnable() {
@Override
public void run() {
mResultView.append("Downloaded! " + "\n");
public void onPercentage(final int currentPercentage) {
mResultView.post(() -> mResultView.append("Downloaded " + currentPercentage + "%\n"));
}
});
mResultView.post(() -> mResultView.append("Downloaded! " + "\n"));
uncompressFile(localFullFile, localFolder, localDfuImageFileName, mResultView);
} catch (IOException | KeyManagementException | NoSuchAlgorithmException e) {
mResultView.post(new Runnable() {
@Override
public void run() {
mResultView.append("Error downloading " + e + "\n");
}
});
mResultView.post(() -> mResultView.append("Error downloading " + e + "\n"));
}
}
}).start();

View File

@ -0,0 +1,6 @@
package com.rusefi.app;
public enum PermissionGrantedAction {
DFU,
DASHBOARD,
}

View File

@ -60,6 +60,7 @@ import com.rusefi.proxy.NetworkConnector;
import com.rusefi.proxy.NetworkConnectorContext;
import com.rusefi.ui.StatusConsumer;
import java.io.IOException;
import java.util.Date;
public class rusEFI extends Activity {
@ -71,20 +72,20 @@ public class rusEFI extends Activity {
//
// protected static final int DFU_DETACH_TIMEOUT = 1000;
private static final String VERSION = "rusEFI app v0.0000008\n";
private static final String VERSION = "rusEFI app v0.20220524\n";
/* UI elements */
private TextView mStatusView;
private TextView mResultView;
private TextView mResultView; // global dump of all messages
private TextView broadcastStatus;
private EditText authToken;
private EditText authTokenUI;
private TextView authStatusMessage;
private TextView authStatusClickableUrl;
private UsbManager usbManager;
private DfuUpload dfuUpload;
private SoundBroadcast soundBroadcast = new SoundBroadcast();
private PermissionGrantedAction onPermissionGrantedAction;
@SuppressLint("SetTextI18n")
@Override
@ -102,6 +103,7 @@ public class rusEFI extends Activity {
findViewById(R.id.buttonDfu).setVisibility(View.GONE);
broadcastStatus = findViewById(R.id.broadcastStatus);
broadcastStatus.setVisibility(View.GONE);
usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
@ -110,8 +112,8 @@ public class rusEFI extends Activity {
mStatusView = findViewById(R.id.text_status);
mResultView = findViewById(R.id.text_result);
authToken = findViewById(R.id.authToken);
authToken.addTextChangedListener(new TextWatcher() {
authTokenUI = findViewById(R.id.authToken);
authTokenUI.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
@ -123,7 +125,7 @@ public class rusEFI extends Activity {
@Override
public void afterTextChanged(Editable editable) {
String text = authToken.getText().toString();
String text = authTokenUI.getText().toString();
if (AuthTokenUtil.isToken(text)) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(rusEFI.this);
SharedPreferences.Editor editor = preferences.edit();
@ -143,13 +145,14 @@ public class rusEFI extends Activity {
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
registerReceiver(mUsbReceiver, filter);
mResultView.append(VERSION);
visibleLogAppend(VERSION);
dfuUpload = new DfuUpload(this);
dfuUpload.fileOperation(mResultView);
String authToken = getAuthToken();
this.authToken.setText(authToken);
//dfuUpload.downloadFileIfNotPresent(mResultView);
String authToken = readPersistedAuthToken();
authTokenUI.setText(authToken);
int visibility = AuthTokenUtil.isToken(authToken) ? View.GONE : View.VISIBLE;
authStatusMessage.setVisibility(visibility);
authStatusClickableUrl.setVisibility(visibility);
@ -159,7 +162,7 @@ public class rusEFI extends Activity {
// SoundBroadcast.checkOrRequestPermission(this);
}
private String getAuthToken() {
private String readPersistedAuthToken() {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(rusEFI.this);
return preferences.getString(AuthTokenUtil.AUTH_TOKEN, "");
}
@ -185,8 +188,13 @@ public class rusEFI extends Activity {
if (ACTION_USB_PERMISSION.equals(action)) {
synchronized (this) {
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
UsbDevice dfuDevice = DfuDeviceLocator.findDevice(usbManager);
doDfuUpdate(dfuDevice, rusEFI.this.mResultView);
if (onPermissionGrantedAction == PermissionGrantedAction.DFU) {
UsbDevice dfuDevice = DfuDeviceLocator.findDevice(usbManager);
doDfuUpdate(dfuDevice);
} else if (onPermissionGrantedAction == PermissionGrantedAction.DASHBOARD) {
connectDashboard();
}
}
}
}
@ -195,45 +203,49 @@ public class rusEFI extends Activity {
private void switchOrProgramDfu() {
UsbDevice dfuDevice = DfuDeviceLocator.findDevice(usbManager);
if (dfuDevice != null) {
dfuUpdate(dfuDevice);
} else {
mResultView.append("No DFU device\n");
if (dfuDevice == null) {
visibleLogAppend("No DFU device\n");
switchToDfu();
// once device is in DFU mode we expect what exactly to happen?
} else if (!usbManager.hasPermission(dfuDevice)) {
requestUsbPermission(dfuDevice, PermissionGrantedAction.DFU);
} else {
doDfuUpdate(dfuDevice);
}
}
public void visibleLogAppend(String s) {
CharSequence current = mResultView.getText();
mResultView.setText(s + "\n" + current);
}
@SuppressLint("SetTextI18n")
private void switchToDfu() {
AndroidSerial serial = AndroidSerial.getAndroidSerial(mStatusView, mResultView, usbManager);
AndroidSerial serial = AndroidSerial.getAndroidSerial(this, mStatusView, usbManager);
if (serial == null) {
// error already reported to mStatusView
return;
}
mResultView.append("Switching to DFU\n");
visibleLogAppend("Switching to DFU\n");
DfuHelper.sendDfuRebootCommand(serial, StatusConsumer.VOID);
}
private void dfuUpdate(UsbDevice dfuDevice) {
if (usbManager.hasPermission(dfuDevice)) {
doDfuUpdate(dfuDevice, mResultView);
} else {
PendingIntent mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
usbManager.requestPermission(dfuDevice, mPermissionIntent);
}
public void requestUsbPermission(UsbDevice usbDevice, PermissionGrantedAction action) {
// why do we not have similar 'request serial USB permission'?
onPermissionGrantedAction = action;
PendingIntent mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
usbManager.requestPermission(usbDevice, mPermissionIntent);
}
@SuppressLint("SetTextI18n")
private void doDfuUpdate(UsbDevice dfuDevice, TextView mResultView) {
private void doDfuUpdate(UsbDevice dfuDevice) {
mStatusView.setText("rusEFI: DFU detected");
DfuDeviceLocator.Result dfu = new DfuDeviceLocator().openDfu(usbManager, dfuDevice);
DfuImage dfuImage = new DfuImage();
dfuImage.read(dfuUpload.localDfuImageFileName);
mResultView.append("Image size " + dfuImage.getImageSize() + "\n");
visibleLogAppend("Image size " + dfuImage.getImageSize() + "\n");
DfuConnection connection = new AndroidDfuConnection(dfu.getConnection(), dfu.getInterfaceIndex(), dfu.getTransferSize(), dfu.getFlashRange());
@ -244,12 +256,16 @@ public class rusEFI extends Activity {
DfuLogic.uploadImage(logger, connection, dfuImage, dfu.getFlashRange());
} catch (IllegalStateException e) {
this.mResultView.append("Error " + e + "\n");
visibleLogAppend("Error " + e + "\n");
}
}
public void onConnectButton(View view) {
connectDashboard();
}
/**
* Called when the user touches the button
* Called when the user touches a button
*/
public void sendMessage(View view) {
if (view.getId() == R.id.buttonDfu) {
@ -259,7 +275,7 @@ public class rusEFI extends Activity {
} else if (view.getId() == R.id.buttonBroadcast) {
startService(new Intent(this, SerialService.class));
AndroidSerial serial = AndroidSerial.getAndroidSerial(mStatusView, mResultView, usbManager);
AndroidSerial serial = AndroidSerial.getAndroidSerial(this, mStatusView, usbManager);
if (serial == null) {
// error already reported to mStatusView
Snackbar mySnackbar = Snackbar.make(view, "No ECU detected", BaseTransientBottomBar.LENGTH_LONG);
@ -276,48 +292,65 @@ public class rusEFI extends Activity {
}));
linkManager.getConnector().connectAndReadConfiguration(new BinaryProtocol.Arguments(true),
new ConnectionStateListener() {
@Override
public void onConnectionEstablished() {
mResultView.post(() -> mResultView.append(new Date() + " On connection established\n"));
@Override
public void onConnectionEstablished() {
mResultView.post(() -> visibleLogAppend(new Date() + " On connection established\n"));
NetworkConnectorContext context = new NetworkConnectorContext();
NetworkConnector.ActivityListener oncePerSecondStatistics = new NetworkConnector.ActivityListener() {
long previousTime;
NetworkConnectorContext context = new NetworkConnectorContext();
NetworkConnector.ActivityListener oncePerSecondStatistics = new NetworkConnector.ActivityListener() {
long previousTime;
@Override
public void onActivity(IoStream targetEcuSocket) {
long now = System.currentTimeMillis();
if (now - previousTime < Timeouts.SECOND) {
// only update status once per second
return;
}
previousTime = now;
broadcastStatus.post(() -> broadcastStatus.setText(targetEcuSocket.getBytesIn() + "/" + targetEcuSocket.getBytesOut()));
}
};
NetworkConnector.NetworkConnectorResult result = new NetworkConnector().start(NetworkConnector.Implementation.Android,
readPersistedAuthToken(), context, new NetworkConnector.ReconnectListener() {
@Override
public void onReconnect() {
}
}, linkManager, oncePerSecondStatistics);
mResultView.post(() -> visibleLogAppend(new Date() + " Broadcast: " + result + "\n"));
}
@Override
public void onActivity(IoStream targetEcuSocket) {
long now = System.currentTimeMillis();
if (now - previousTime < Timeouts.SECOND) {
return;
}
previousTime = now;
broadcastStatus.post(() -> broadcastStatus.setText(targetEcuSocket.getBytesIn() + "/" + targetEcuSocket.getBytesOut()));
public void onConnectionFailed() {
mResultView.post(() -> visibleLogAppend("Connection failed\n"));
}
};
NetworkConnector.NetworkConnectorResult result = new NetworkConnector().start(NetworkConnector.Implementation.Android,
getAuthToken(), context, new NetworkConnector.ReconnectListener() {
@Override
public void onReconnect() {
}
}, linkManager, oncePerSecondStatistics);
});
mResultView.post(() -> mResultView.append(new Date() + " Broadcast: " + result + "\n"));
}
@Override
public void onConnectionFailed() {
mResultView.post(() -> mResultView.append("Connection failed\n"));
}
});
Snackbar mySnackbar = Snackbar.make(view, "Broadcasting with " + getAuthToken(), BaseTransientBottomBar.LENGTH_LONG);
Snackbar mySnackbar = Snackbar.make(view, "Broadcasting with " + readPersistedAuthToken(), BaseTransientBottomBar.LENGTH_LONG);
mySnackbar.show();
}
}
private void connectDashboard() {
AndroidSerial serial = AndroidSerial.getAndroidSerial(this, mStatusView, usbManager);
if (serial == null) {
// error already reported to mStatusView
return;
}
try {
String signature = BinaryProtocol.getSignature(serial);
visibleLogAppend("Connected to " + signature);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
protected void onNewIntent(Intent intent) {
}

View File

@ -1,6 +1,7 @@
package com.rusefi.app.serial;
import android.annotation.SuppressLint;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbManager;
import android.widget.TextView;
@ -11,6 +12,8 @@ import com.hoho.android.usbserial.driver.UsbSerialDriver;
import com.hoho.android.usbserial.driver.UsbSerialPort;
import com.hoho.android.usbserial.driver.UsbSerialProber;
import com.opensr5.io.DataListener;
import com.rusefi.app.PermissionGrantedAction;
import com.rusefi.app.rusEFI;
import com.rusefi.binaryprotocol.IncomingDataBuffer;
import com.rusefi.dfu.DfuLogic;
import com.rusefi.io.ByteReader;
@ -41,18 +44,35 @@ public class AndroidSerial extends AbstractIoStream {
dataBuffer = createDataBuffer("");
}
@SuppressLint("SetTextI18n")
@Nullable
public static AndroidSerial getAndroidSerial(TextView mStatusView, TextView mResultView, UsbManager usbManager) {
private static UsbSerialDriver getSerialDriver(rusEFI rusEFI, TextView mStatusView, UsbManager usbManager, PermissionGrantedAction action) {
List<UsbSerialDriver> availableDrivers = findUsbSerial(usbManager);
if (availableDrivers.isEmpty()) {
mStatusView.setText("Serial not found");
mResultView.append("No serial devices " + new Date() + "\n");
rusEFI.visibleLogAppend("No serial devices " + new Date() + "\n");
return null;
}
mStatusView.setText("rusEFI: " + availableDrivers.size() + " device(s)");
UsbSerialDriver driver = availableDrivers.get(0);
UsbDevice usbDevice = driver.getDevice();
if (!usbManager.hasPermission(usbDevice)) {
mStatusView.setText("Need permission");
rusEFI.requestUsbPermission(usbDevice, action);
return null;
}
return driver;
}
@SuppressLint("SetTextI18n")
@Nullable
public static AndroidSerial getAndroidSerial(rusEFI rusEFI, TextView mStatusView, UsbManager usbManager) {
// todo: should support separate actions not default to dashboard!
UsbSerialDriver driver = getSerialDriver(rusEFI, mStatusView, usbManager, PermissionGrantedAction.DASHBOARD);
if (driver == null) {
// error already reported to UI or permission request was fired
return null;
}
UsbDeviceConnection connection = usbManager.openDevice(driver.getDevice());
if (connection == null) {
// add UsbManager.requestPermission(driver.getDevice(), ..) handling here

View File

@ -53,6 +53,13 @@
android:onClick="sendMessage"
android:text="Sound" />
<Button
android:id="@+id/buttonConnect"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onConnectButton"
android:text="Connect" />
<Button
android:id="@+id/buttonBroadcast"
android:layout_width="match_parent"
@ -64,7 +71,7 @@
android:id="@+id/broadcastStatus"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextView" />
android:text="Hello rusEFI" />
<ScrollView
android:layout_width="match_parent"

View File

@ -36,7 +36,7 @@ public class AutoupdateUtil {
JProgressBar jProgressBar = new JProgressBar();
frameHelper.getFrame().setTitle(title);
jProgressBar.setMaximum(ConnectionAndMeta.STEPS);
jProgressBar.setMaximum(ConnectionAndMeta.CENTUM);
jProgressBarAtomicReference.set(jProgressBar);
frameHelper.showFrame(jProgressBar, true);
}

View File

@ -15,7 +15,7 @@ public class ConnectionAndMeta {
public static final String BASE_URL_LATEST = "https://rusefi.com/build_server/autoupdate/";
private static final int BUFFER_SIZE = 32 * 1024;
public static final int STEPS = 1000;
public static final int CENTUM = 100;
private final String zipFileName;
private HttpsURLConnection httpConnection;
private long completeFileSize;
@ -42,15 +42,13 @@ public class ConnectionAndMeta {
downloadedFileSize += newDataSize;
// calculate progress
final int currentProgress = (int) ((((double) downloadedFileSize) / ((double) completeFileSize)) * STEPS);
int currentPercentage = (int) (100L * downloadedFileSize / completeFileSize);
int currentPercentage = (int) (CENTUM * downloadedFileSize / completeFileSize);
if (currentPercentage > printedPercentage + 5) {
System.out.println("Downloaded " + currentPercentage + "%");
printedPercentage = currentPercentage;
listener.onPercentage(currentPercentage);
}
listener.onPercentage(currentProgress);
bout.write(data, 0, newDataSize);
}
@ -86,7 +84,7 @@ public class ConnectionAndMeta {
}
public interface DownloadProgressListener {
void onPercentage(int currentProgress);
void onPercentage(int currentPercentage);
}
private static class AcceptAnyCertificateTrustManager implements X509TrustManager {