mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-11-12 13:09:24 +01:00
Xiaomi: Allow re-parse activity from storage
This commit is contained in:
parent
d33fa79187
commit
05570a3cae
@ -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) {
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user