1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-10-06 13:20:30 +02:00

Xiaomi: Allow re-parse activity from storage

This commit is contained in:
José Rebelo 2024-09-17 22:53:46 +01:00
parent d33fa79187
commit 05570a3cae
2 changed files with 89 additions and 45 deletions

View File

@ -23,6 +23,8 @@ import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.location.Location;
import android.net.Uri;
import android.os.Handler;
import android.widget.Toast;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
@ -39,7 +41,6 @@ import java.util.List;
import java.util.Map;
import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.BuildConfig;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventUpdatePreferences;
@ -463,66 +464,111 @@ public class XiaomiSupport extends AbstractDeviceSupport {
return StringUtils.replaceEach(inputString, EMOJI_SOURCE, EMOJI_TARGET);
}
boolean parsingActivityFilesFromStorage = false;
private void parseAllActivityFilesFromStorage() {
// This function as-is should only be used for debug purposes
if (!BuildConfig.DEBUG) {
LOG.error("This should never be used in release builds");
if (parsingActivityFilesFromStorage) {
GB.toast(getContext(), "Already parsing!", Toast.LENGTH_LONG, GB.ERROR);
return;
}
parsingActivityFilesFromStorage = true;
LOG.info("Parsing all activity files from storage");
final File[] activityFiles;
try {
final File externalFilesDir = getCoordinator().getWritableExportDirectory(getDevice());
final File targetDir = new File(externalFilesDir, "rawFetchOperations");
final File exportDir = new File(externalFilesDir, "rawFetchOperations");
if (!targetDir.exists()) {
LOG.warn("rawFetchOperations not found");
if (!exportDir.exists() || !exportDir.isDirectory()) {
LOG.error("export directory {} not found", exportDir);
GB.toast(getContext(), "export directory " + exportDir + " not found", Toast.LENGTH_LONG, GB.ERROR);
return;
}
final File[] activityFiles = targetDir.listFiles((dir, name) -> name.startsWith("xiaomi_"));
activityFiles = exportDir.listFiles((dir, name) -> name.startsWith("xiaomi_"));
if (activityFiles == null) {
LOG.warn("activityFiles is null");
LOG.error("activityFiles is null for {}", exportDir);
GB.toast(getContext(), "activityFiles is null for " + exportDir, Toast.LENGTH_LONG, GB.ERROR);
return;
}
for (final File activityFile : activityFiles) {
LOG.debug("Parsing {}", activityFile);
// The logic below just replicates XiaomiActivityFileFetcher
final byte[] data;
try (InputStream in = new FileInputStream(activityFile)) {
data = FileUtils.readAll(in, 999999);
} catch (final IOException ioe) {
LOG.error("Failed to read {}", activityFile, ioe);
continue;
}
final byte[] fileIdBytes = Arrays.copyOfRange(data, 0, 7);
final XiaomiActivityFileId fileId = XiaomiActivityFileId.from(fileIdBytes);
final XiaomiActivityParser activityParser = XiaomiActivityParser.create(fileId);
if (activityParser == null) {
LOG.warn("Failed to find parser for {}", fileId);
continue;
}
try {
if (activityParser.parse(this, fileId, data)) {
LOG.info("Successfully parsed {}", fileId);
} else {
LOG.warn("Failed to parse {}", fileId);
}
} catch (final Exception ex) {
LOG.error("Exception while parsing {}", fileId, ex);
}
if (activityFiles.length == 0) {
LOG.error("No activity files found in {}", exportDir);
GB.toast(getContext(), "No activity files found in " + exportDir, Toast.LENGTH_LONG, GB.ERROR);
return;
}
} catch (final Exception e) {
LOG.error("Failed to parse from storage", e);
GB.toast(getContext(), "Failed to parse from storage", Toast.LENGTH_LONG, GB.ERROR, e);
return;
}
GB.toast(getContext(), "Check notification for progress", Toast.LENGTH_LONG, GB.INFO);
GB.updateTransferNotification("Parsing activity files", "...", true, 0, getContext());
final long[] lastNotificationUpdateTs = new long[]{System.currentTimeMillis()};
final Handler handler = new Handler(getContext().getMainLooper());
new Thread(() -> {
try {
int[] i = new int[]{0};
for (final File activityFile : activityFiles) {
i[0]++;
LOG.debug("Parsing {}", activityFile);
final long now = System.currentTimeMillis();
if (now - lastNotificationUpdateTs[0] > 1500L) {
lastNotificationUpdateTs[0] = now;
handler.post(() -> {
GB.updateTransferNotification(
"Parsing activity files", "File " + i[0] + " of " + activityFiles.length,
true,
(i[0] * 100) / activityFiles.length, getContext()
);
;
});
}
// The logic below just replicates XiaomiActivityFileFetcher
final byte[] data;
try (InputStream in = new FileInputStream(activityFile)) {
data = FileUtils.readAll(in, 999999);
} catch (final IOException ioe) {
LOG.error("Failed to read {}", activityFile, ioe);
continue;
}
final byte[] fileIdBytes = Arrays.copyOfRange(data, 0, 7);
final XiaomiActivityFileId fileId = XiaomiActivityFileId.from(fileIdBytes);
final XiaomiActivityParser activityParser = XiaomiActivityParser.create(fileId);
if (activityParser == null) {
LOG.warn("Failed to find parser for {}", fileId);
continue;
}
try {
if (activityParser.parse(this, fileId, data)) {
LOG.info("Successfully parsed {}", fileId);
} else {
LOG.warn("Failed to parse {}", fileId);
}
} catch (final Exception ex) {
LOG.error("Exception while parsing {}", fileId, ex);
}
}
} catch (final Exception e) {
LOG.error("Failed to parse from storage", e);
}
handler.post(() -> {
parsingActivityFilesFromStorage = false;
GB.updateTransferNotification("", "", false, 100, getContext());
GB.signalActivityDataFinish(getDevice());
});
}).start();
}
public void setFeatureSupported(final String featureKey, final boolean supported) {

View File

@ -30,7 +30,6 @@ import java.util.List;
import java.util.PriorityQueue;
import java.util.Queue;
import nodomain.freeyourgadget.gadgetbridge.BuildConfig;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions;
@ -38,7 +37,6 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.xiaomi.XiaomiPrefere
import nodomain.freeyourgadget.gadgetbridge.service.devices.xiaomi.XiaomiSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.xiaomi.services.XiaomiHealthService;
import nodomain.freeyourgadget.gadgetbridge.util.CheckSums;
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
public class XiaomiActivityFileFetcher {
@ -119,7 +117,7 @@ public class XiaomiActivityFileFetcher {
LOG.warn("Failed to parse {}", fileId);
}
} catch (final Exception ex) {
LOG.error("Exception while parsing " + fileId, ex);
LOG.error("Exception while parsing {}", fileId, ex);
}
triggerNextFetch();