1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-06-01 19:06:06 +02:00
This commit is contained in:
José Rebelo 2023-08-22 15:54:42 +01:00
parent 6e125563db
commit 99908fc894
32 changed files with 687 additions and 317 deletions

View File

@ -578,7 +578,7 @@
android:label="@string/pref_world_clocks_title"
android:parentActivityName=".activities.ControlCenterv2" />
<activity
android:name=".activities.MusicFilesActivity"
android:name=".activities.musicfiles.MusicFilesActivity"
android:label="@string/menuitem_music"
android:parentActivityName=".activities.ControlCenterv2" />
<activity

View File

@ -1,19 +0,0 @@
package nodomain.freeyourgadget.internethelper;
import nodomain.freeyourgadget.internethelper.IFtpServiceCallback;
interface IFtpService {
int version();
String createClient();
void destroyClient(String client);
void connect(String client, String host, int port, IFtpServiceCallback callback);
void disconnect(String client);
void login(String client, String username, String password, IFtpServiceCallback callback);
void list(String client, String path, IFtpServiceCallback callback);
void upload(String client, String path, in byte[] bytes, IFtpServiceCallback callback);
void download(String client, String path, IFtpServiceCallback callback);
}

View File

@ -1,9 +0,0 @@
package nodomain.freeyourgadget.internethelper;
import nodomain.freeyourgadget.internethelper.IHttpServiceCallback;
interface IHttpService {
int version();
void get(String url, IHttpServiceCallback cb);
}

View File

@ -1,5 +0,0 @@
package nodomain.freeyourgadget.internethelper;
oneway interface IHttpServiceCallback {
void onGet(in Bundle bundle);
}

View File

@ -1,9 +0,0 @@
package nodomain.freeyourgadget.internethelper;
import nodomain.freeyourgadget.internethelper.IWifiServiceCallback;
interface IWifiService {
int version();
String getCurrentSsid();
void connect(String ssid, String password, IWifiServiceCallback cb);
}

View File

@ -1,5 +0,0 @@
package nodomain.freeyourgadget.internethelper;
oneway interface IWifiServiceCallback {
}

View File

@ -0,0 +1,3 @@
package nodomain.freeyourgadget.internethelper.aidl.ftp;
parcelable FtpEntry;

View File

@ -1,9 +1,11 @@
package nodomain.freeyourgadget.internethelper;
package nodomain.freeyourgadget.internethelper.aidl.ftp;
oneway interface IFtpServiceCallback {
import nodomain.freeyourgadget.internethelper.aidl.ftp.FtpEntry;
oneway interface IFtpCallback {
void onConnect(boolean success, String msg);
void onLogin(boolean success, String msg);
void onList(String path, in List<String> directories, in List<String> files);
void onList(String path, in List<FtpEntry> entries);
void onUpload(String path, boolean success, String msg);
void onDownload(String path, boolean success, String msg);
}

View File

@ -0,0 +1,19 @@
package nodomain.freeyourgadget.internethelper.aidl.ftp;
import nodomain.freeyourgadget.internethelper.aidl.ftp.IFtpCallback;
interface IFtpService {
int version();
String createClient(IFtpCallback callback);
void destroyClient(String client);
void connect(String client, String host, int port);
void disconnect(String client);
void login(String client, String username, String password);
void list(String client, String path);
void upload(String client, String localSrc, String remoteDest);
void download(String client, String remoteSrc, String localDest);
}

View File

@ -0,0 +1,3 @@
package nodomain.freeyourgadget.internethelper.aidl.http;
parcelable HttpGetRequest;

View File

@ -0,0 +1,3 @@
package nodomain.freeyourgadget.internethelper.aidl.http;
parcelable HttpPostRequest;

View File

@ -0,0 +1,3 @@
package nodomain.freeyourgadget.internethelper.aidl.http;
parcelable HttpResponse;

View File

@ -0,0 +1,8 @@
package nodomain.freeyourgadget.internethelper.aidl.http;
import nodomain.freeyourgadget.internethelper.aidl.http.HttpResponse;
oneway interface IHttpCallback {
void onResponse(in HttpResponse response);
void onException(in String message);
}

View File

@ -0,0 +1,11 @@
package nodomain.freeyourgadget.internethelper.aidl.http;
import nodomain.freeyourgadget.internethelper.aidl.http.HttpGetRequest;
import nodomain.freeyourgadget.internethelper.aidl.http.HttpPostRequest;
import nodomain.freeyourgadget.internethelper.aidl.http.IHttpCallback;
interface IHttpService {
int version();
void get(in HttpGetRequest request, IHttpCallback cb);
}

View File

@ -0,0 +1,5 @@
package nodomain.freeyourgadget.internethelper.aidl.wifi;
oneway interface IWifiCallback {
}

View File

@ -0,0 +1,9 @@
package nodomain.freeyourgadget.internethelper.aidl.wifi;
import nodomain.freeyourgadget.internethelper.aidl.wifi.IWifiCallback;
interface IWifiService {
int version();
String getCurrentSsid();
void connect(String ssid, String password, IWifiCallback cb);
}

View File

@ -22,7 +22,6 @@ import static android.content.Intent.EXTRA_SUBJECT;
import static nodomain.freeyourgadget.gadgetbridge.util.GB.NOTIFICATION_CHANNEL_ID;
import static nodomain.freeyourgadget.gadgetbridge.util.GB.toast;
import android.Manifest;
import android.app.Activity;
import android.app.DatePickerDialog;
import android.app.PendingIntent;
@ -43,16 +42,12 @@ import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.SharedMemory;
import android.preference.PreferenceManager;
import android.system.ErrnoException;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
@ -87,7 +82,6 @@ import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.Serializable;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
@ -133,12 +127,12 @@ import nodomain.freeyourgadget.gadgetbridge.util.PendingIntentUtils;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
import nodomain.freeyourgadget.gadgetbridge.util.StringUtils;
import nodomain.freeyourgadget.gadgetbridge.util.WidgetPreferenceStorage;
import nodomain.freeyourgadget.internethelper.IFtpService;
import nodomain.freeyourgadget.internethelper.IFtpServiceCallback;
import nodomain.freeyourgadget.internethelper.IHttpService;
import nodomain.freeyourgadget.internethelper.IHttpServiceCallback;
import nodomain.freeyourgadget.internethelper.IWifiService;
import nodomain.freeyourgadget.internethelper.IWifiServiceCallback;
//import nodomain.freeyourgadget.internethelper.IFtpService;
//import nodomain.freeyourgadget.internethelper.IFtpServiceCallback;
//import nodomain.freeyourgadget.internethelper.IHttpService;
//import nodomain.freeyourgadget.internethelper.IHttpServiceCallback;
//import nodomain.freeyourgadget.internethelper.IWifiService;
//import nodomain.freeyourgadget.internethelper.IWifiServiceCallback;
public class DebugActivity extends AbstractGBActivity {
private static final Logger LOG = LoggerFactory.getLogger(DebugActivity.class);
@ -919,11 +913,6 @@ public class DebugActivity extends AbstractGBActivity {
.show();
}
IFtpService iRemoteService;
IHttpService ihttpService;
IWifiService iWifiService;
String client;
int i = 0;
private void testNewFunctionality() {
if (ActivityCompat.checkSelfPermission(getApplicationContext(), "nodomain.freeyourgadget.internethelper.INTERNET") != PackageManager.PERMISSION_GRANTED) {
@ -933,10 +922,15 @@ public class DebugActivity extends AbstractGBActivity {
return;
}
doWiFi();
//GBApplication.deviceService().onTestNewFunction();
}
/*
IFtpService iFtpService;
IHttpService ihttpService;
IWifiService iWifiService;
String client;
int i = 0;
private void doWiFi() {
final IWifiServiceCallback.Stub cb = new IWifiServiceCallback.Stub() {
@ -1073,7 +1067,7 @@ public class DebugActivity extends AbstractGBActivity {
}
};
if (iRemoteService == null) {
if (iFtpService == null) {
LOG.info("connecting");
ServiceConnection mConnection = new ServiceConnection() {
// Called when the connection with the service is established.
@ -1082,16 +1076,16 @@ public class DebugActivity extends AbstractGBActivity {
// Following the preceding example for an AIDL interface,
// this gets an instance of the IRemoteInterface, which we can use to call on the service.
iRemoteService = IFtpService.Stub.asInterface(service);
iFtpService = IFtpService.Stub.asInterface(service);
}
// Called when the connection with the service disconnects unexpectedly.
public void onServiceDisconnected(ComponentName className) {
LOG.error("Service has unexpectedly disconnected");
iRemoteService = null;
iFtpService = null;
}
};
Intent intent = new Intent("nodomain.freeyourgadget.internethelper.FtpService");
Intent intent = new Intent("nodomain.freeyourgadget.internethelper.ftp.FtpService");
intent.setPackage("nodomain.freeyourgadget.internethelper");
boolean res = this.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
if (res) {
@ -1101,7 +1095,7 @@ public class DebugActivity extends AbstractGBActivity {
}
} else if (i == 0) {
try {
final int version = iRemoteService.version();
final int version = iFtpService.version();
LOG.info("version = {}", version);
} catch (RemoteException e) {
LOG.error("cenas {} failed", i ,e);
@ -1109,7 +1103,7 @@ public class DebugActivity extends AbstractGBActivity {
i++;
} else if (i == 1) {
try {
client = iRemoteService.createClient();
client = iFtpService.createClient();
LOG.info("client = {}", client);
} catch (RemoteException e) {
LOG.error("cenas {} failed", i ,e);
@ -1117,7 +1111,7 @@ public class DebugActivity extends AbstractGBActivity {
i++;
} else if (i == 2) {
try {
iRemoteService.connect(client, "10.0.1.12", 8710, cb);
iFtpService.connect(client, "10.0.1.12", 8710, cb);
LOG.info("connected");
} catch (RemoteException e) {
LOG.error("connected {} failed", i ,e);
@ -1126,28 +1120,28 @@ public class DebugActivity extends AbstractGBActivity {
} else if (i == 3) {
i++;
try {
iRemoteService.login(client, "gadgetbridge", "cenas123", cb);
iFtpService.login(client, "gadgetbridge", "cenas123", cb);
} catch (RemoteException e) {
LOG.error("login {} failed", i ,e);
}
} else if (i == 4) {
i++;
try {
iRemoteService.list(client, "/", cb);
iFtpService.list(client, "/", cb);
} catch (RemoteException e) {
LOG.error("disconnect {} failed", i ,e);
}
} else if (i == 5) {
i++;
try {
iRemoteService.disconnect(client);
iFtpService.disconnect(client);
} catch (RemoteException e) {
LOG.error("disconnect {} failed", i ,e);
}
} else {
LOG.info("wtf {}", i);
}
}
}*/
private void shareLog() {
String fileName = GBApplication.getLogPath();

View File

@ -1,118 +0,0 @@
/* Copyright (C) 2023 José Rebelo
This file is part of Gadgetbridge.
Gadgetbridge is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gadgetbridge is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.activities;
import android.content.res.AssetFileDescriptor;
import android.media.MediaMetadataRetriever;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.view.MenuItem;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
public class MusicFilesActivity extends AbstractGBActivity {
private static final Logger LOG = LoggerFactory.getLogger(MusicFilesActivity.class);
private GBDevice gbDevice;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
gbDevice = getIntent().getParcelableExtra(GBDevice.EXTRA_DEVICE);
setContentView(R.layout.activity_music_files);
final ActivityResultLauncher<String> activityResultLauncher = this.registerForActivityResult(
new ActivityResultContracts.GetMultipleContents(),
urilist -> {
final MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever();
LOG.info("Got {}", urilist);
for (final Uri uri : urilist) {
mediaMetadataRetriever.setDataSource(MusicFilesActivity.this, uri);
final String title = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
final String artist = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST);
final String album = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM);
long fileSize;
try (AssetFileDescriptor fileDescriptor = getApplicationContext().getContentResolver().openAssetFileDescriptor(uri , "r")){
fileSize = fileDescriptor.getLength();
} catch (IOException e) {
throw new RuntimeException(e);
}
final JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("title", title);
jsonObject.put("album", album);
jsonObject.put("artist", artist);
jsonObject.put("size", fileSize);
} catch (final JSONException e) {
throw new RuntimeException(e);
}
final String md5;
try (InputStream inputStream = getContentResolver().openInputStream(uri)) {
md5 = FileUtils.md5sum(inputStream);
} catch (final IOException e) {
throw new RuntimeException(e);
}
LOG.info("{}: {} {}", uri, md5, jsonObject);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
mediaMetadataRetriever.close();
}
}
);
final FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(v -> {
activityResultLauncher.launch("audio/*");
});
}
@Override
public boolean onOptionsItemSelected(final MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
// back button
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
}

View File

@ -26,7 +26,6 @@ import androidx.preference.ListPreference;
import androidx.preference.Preference;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -41,7 +40,7 @@ import nodomain.freeyourgadget.gadgetbridge.activities.CalBlacklistActivity;
import nodomain.freeyourgadget.gadgetbridge.activities.ConfigureContacts;
import nodomain.freeyourgadget.gadgetbridge.activities.ConfigureWorldClocks;
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractPreferenceFragment;
import nodomain.freeyourgadget.gadgetbridge.activities.MusicFilesActivity;
import nodomain.freeyourgadget.gadgetbridge.activities.musicfiles.MusicFilesActivity;
import nodomain.freeyourgadget.gadgetbridge.activities.loyaltycards.LoyaltyCardsSettingsActivity;
import nodomain.freeyourgadget.gadgetbridge.activities.loyaltycards.LoyaltyCardsSettingsConst;
import nodomain.freeyourgadget.gadgetbridge.capabilities.HeartRateCapability;

View File

@ -0,0 +1,230 @@
/* Copyright (C) 2023 José Rebelo
This file is part of Gadgetbridge.
Gadgetbridge is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gadgetbridge is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.activities.musicfiles;
import static nodomain.freeyourgadget.gadgetbridge.util.GB.toast;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.content.res.AssetFileDescriptor;
import android.media.MediaMetadataRetriever;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.view.MenuItem;
import android.widget.Toast;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.core.app.ActivityCompat;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractGBActivity;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
import nodomain.freeyourgadget.internethelper.aidl.ftp.FtpEntry;
import nodomain.freeyourgadget.internethelper.aidl.ftp.IFtpService;
import nodomain.freeyourgadget.internethelper.aidl.ftp.IFtpCallback;
public class MusicFilesActivity extends AbstractGBActivity {
private static final Logger LOG = LoggerFactory.getLogger(MusicFilesActivity.class);
private GBDevice gbDevice;
IFtpService iFtpService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
gbDevice = getIntent().getParcelableExtra(GBDevice.EXTRA_DEVICE);
setContentView(R.layout.activity_music_files);
final ActivityResultLauncher<String> activityResultLauncher = this.registerForActivityResult(
new ActivityResultContracts.GetMultipleContents(),
urilist -> {
final MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever();
LOG.info("Got {}", urilist);
for (final Uri uri : urilist) {
mediaMetadataRetriever.setDataSource(MusicFilesActivity.this, uri);
final String title = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
final String artist = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST);
final String album = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM);
long fileSize;
try (AssetFileDescriptor fileDescriptor = getApplicationContext().getContentResolver().openAssetFileDescriptor(uri , "r")){
fileSize = fileDescriptor.getLength();
} catch (IOException e) {
throw new RuntimeException(e);
}
final JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("title", title);
jsonObject.put("album", album);
jsonObject.put("artist", artist);
jsonObject.put("size", fileSize);
} catch (final JSONException e) {
throw new RuntimeException(e);
}
final String md5;
try (InputStream inputStream = getContentResolver().openInputStream(uri)) {
md5 = FileUtils.md5sum(inputStream);
} catch (final IOException e) {
throw new RuntimeException(e);
}
grantUriPermission("nodomain.freeyourgadget.internethelper", uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
LOG.info("{}: {} {}", uri, md5, jsonObject);
try {
iFtpService.upload(ftpClient, uri.toString(), "/cenas.mp3");
} catch (RemoteException e) {
LOG.error("oops", e);
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
mediaMetadataRetriever.close();
}
}
);
final FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(v -> {
try {
if (initFtp()) {
activityResultLauncher.launch("audio/*");
}
} catch (RemoteException e) {
LOG.error("Failure", e);
}
});
}
String ftpClient;
boolean ftpReady = false;
final IFtpCallback.Stub cb = new IFtpCallback.Stub() {
@Override
public void onConnect(boolean success, String msg) throws RemoteException {
LOG.info("onConnect {} {}", success, msg);
if (success) {
iFtpService.login(ftpClient, "gadgetbridge", "cenas123");
}
}
@Override
public void onLogin(boolean success, String msg) throws RemoteException {
LOG.info("onLogin {} {}", success, msg);
ftpReady = success;
}
@Override
public void onList(String path, List<FtpEntry> entries) throws RemoteException {
LOG.info("onList {}", path, entries);
}
@Override
public void onUpload(String path, boolean success, String msg) throws RemoteException {
LOG.info("onUpload");
}
@Override
public void onDownload(String path, boolean success, String msg) throws RemoteException {
LOG.info("onDownload");
}
};
private boolean initFtp() throws RemoteException {
if (ActivityCompat.checkSelfPermission(getApplicationContext(), "nodomain.freeyourgadget.internethelper.INTERNET") != PackageManager.PERMISSION_GRANTED) {
LOG.error("No permission to access internet!");
toast(this, "internet permission missing", Toast.LENGTH_SHORT, GB.ERROR);
ActivityCompat.requestPermissions(this, new String[]{"nodomain.freeyourgadget.internethelper.INTERNET"}, 0);
return false;
}
if (iFtpService == null) {
LOG.info("connecting");
ServiceConnection mConnection = new ServiceConnection() {
// Called when the connection with the service is established.
public void onServiceConnected(ComponentName className, IBinder service) {
LOG.info("onServiceConnected");
// Following the preceding example for an AIDL interface,
// this gets an instance of the IRemoteInterface, which we can use to call on the service.
iFtpService = IFtpService.Stub.asInterface(service);
}
// Called when the connection with the service disconnects unexpectedly.
public void onServiceDisconnected(ComponentName className) {
LOG.error("Service has unexpectedly disconnected");
iFtpService = null;
}
};
Intent intent = new Intent("nodomain.freeyourgadget.internethelper.FtpService");
intent.setPackage("nodomain.freeyourgadget.internethelper");
boolean res = this.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
if (res) {
LOG.info("Bound to NetworkService");
} else {
LOG.warn("Could not bind to NetworkService");
}
return false;
} else if (!ftpReady) {
final int version = iFtpService.version();
LOG.info("version = {}", version);
ftpClient = iFtpService.createClient(cb);
LOG.info("client = {}", ftpClient);
iFtpService.connect(ftpClient, "10.0.1.49", 8710);
}
return ftpReady;
}
@Override
public boolean onOptionsItemSelected(final MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
// back button
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
}

View File

@ -0,0 +1,25 @@
/* Copyright (C) 2023 José Rebelo
This file is part of Gadgetbridge.
Gadgetbridge is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gadgetbridge is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.activities.musicfiles;
import android.content.Context;
public class MusicFilesCoordinator {
public void sendStatusUpdate(final Context context, final String msg) {
}
}

View File

@ -93,6 +93,14 @@ public interface EventHandler {
void onAppReorder(UUID uuids[]);
void onMusicFilesStart();
void onMusicFilesReq();
void onMusicFilesUpload(Uri[] uris);
void onMusicFilesStop();
void onFetchRecordedData(int dataTypes);
void onReset(int flags);

View File

@ -361,6 +361,31 @@ public class GBDeviceService implements DeviceService {
invokeService(intent);
}
@Override
public void onMusicFilesStart() {
Intent intent = createIntent().setAction(ACTION_MUSIC_FILES_START);
invokeService(intent);
}
@Override
public void onMusicFilesReq() {
Intent intent = createIntent().setAction(ACTION_MUSIC_FILES_REQ);
invokeService(intent);
}
@Override
public void onMusicFilesUpload(Uri[] uris) {
Intent intent = createIntent().setAction(ACTION_MUSIC_FILES_UPLOAD)
.putExtra(EXTRA_MUSIC_FILES, uris);
invokeService(intent);
}
@Override
public void onMusicFilesStop() {
Intent intent = createIntent().setAction(ACTION_MUSIC_FILES_STOP);
invokeService(intent);
}
@Override
public void onFetchRecordedData(int dataTypes) {
Intent intent = createIntent().setAction(ACTION_FETCH_RECORDED_DATA)

View File

@ -49,6 +49,10 @@ public interface DeviceService extends EventHandler {
String ACTION_DELETEAPP = PREFIX + ".action.deleteapp";
String ACTION_APP_CONFIGURE = PREFIX + ".action.app_configure";
String ACTION_APP_REORDER = PREFIX + ".action.app_reorder";
String ACTION_MUSIC_FILES_START = PREFIX + ".action.music_files_start";
String ACTION_MUSIC_FILES_REQ = PREFIX + ".action.music_files_req";
String ACTION_MUSIC_FILES_UPLOAD = PREFIX + ".action.music_files_upload";
String ACTION_MUSIC_FILES_STOP = PREFIX + ".action.music_files_stop";
String ACTION_INSTALL = PREFIX + ".action.install";
String ACTION_RESET = PREFIX + ".action.reset";
String ACTION_HEARTRATE_TEST = PREFIX + ".action.heartrate_test";
@ -132,6 +136,7 @@ public interface DeviceService extends EventHandler {
String EXTRA_INTERVAL_SECONDS = "interval_seconds";
String EXTRA_WEATHER = "weather";
String EXTRA_RECORDED_DATA_TYPES = "data_types";
String EXTRA_MUSIC_FILES = "music_files";
String EXTRA_FM_FREQUENCY = "fm_frequency";
String EXTRA_LED_COLOR = "led_color";
String EXTRA_GPS_LOCATION = "gps_location";

View File

@ -823,6 +823,38 @@ public abstract class AbstractDeviceSupport implements DeviceSupport {
}
/**
* Music files activity has started - prepare the device (eg. start wifi, instruct user to connect to it, start FTP.
*/
@Override
public void onMusicFilesStart() {
}
/**
* Requests the current list of music files on the device.
*/
@Override
public void onMusicFilesReq() {
}
/**
* Upload the music files represented by the URIs to the device.
*/
@Override
public void onMusicFilesUpload(Uri[] uris) {
}
/**
* Music files activity has been closed.
*/
@Override
public void onMusicFilesStop() {
}
/**
* If recorded data can be fetched from the device, this method
* can be overridden and implemented by the device support class.

View File

@ -20,6 +20,8 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.service;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.*;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Service;
@ -98,121 +100,6 @@ import nodomain.freeyourgadget.gadgetbridge.util.language.LanguageUtils;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
import nodomain.freeyourgadget.gadgetbridge.util.language.Transliterator;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_ADD_CALENDAREVENT;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_APP_CONFIGURE;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_APP_REORDER;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_CALLSTATE;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_CONNECT;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_DELETEAPP;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_DELETE_CALENDAREVENT;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_DELETE_NOTIFICATION;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_DISCONNECT;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_ENABLE_HEARTRATE_SLEEP_SUPPORT;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_ENABLE_REALTIME_HEARTRATE_MEASUREMENT;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_ENABLE_REALTIME_STEPS;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_FETCH_RECORDED_DATA;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_FIND_DEVICE;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_HEARTRATE_TEST;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_INSTALL;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_NOTIFICATION;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_PHONE_FOUND;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_POWER_OFF;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_READ_CONFIGURATION;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_REQUEST_APPINFO;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_REQUEST_DEVICEINFO;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_REQUEST_SCREENSHOT;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_RESET;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_SEND_CONFIGURATION;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_SEND_WEATHER;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_SETCANNEDMESSAGES;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_SETMUSICINFO;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_SETMUSICSTATE;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_SETNAVIGATIONINFO;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_SETTIME;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_SET_ALARMS;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_SET_CONSTANT_VIBRATION;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_SET_CONTACTS;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_SET_FM_FREQUENCY;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_SET_HEARTRATE_MEASUREMENT_INTERVAL;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_SET_GPS_LOCATION;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_SET_LED_COLOR;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_SET_LOYALTY_CARDS;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_SET_PHONE_VOLUME;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_SET_REMINDERS;
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;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_APP_CONFIG_ID;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_APP_START;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_APP_UUID;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_BOOLEAN_ENABLE;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_CALENDAREVENT_DESCRIPTION;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_CALENDAREVENT_DURATION;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_CALENDAREVENT_ID;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_CALENDAREVENT_LOCATION;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_CALENDAREVENT_TIMESTAMP;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_CALENDAREVENT_ALLDAY;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_CALENDAREVENT_TITLE;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_CALENDAREVENT_TYPE;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_CALENDAREVENT_CALNAME;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_CALENDAREVENT_COLOR;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_CALL_COMMAND;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_CALL_DISPLAYNAME;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_CALL_DNDSUPPRESSED;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_CALL_PHONENUMBER;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_CANNEDMESSAGES;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_CANNEDMESSAGES_TYPE;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_CONFIG;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_CONNECT_FIRST_TIME;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_CONTACTS;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_FIND_START;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_FM_FREQUENCY;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_GPS_LOCATION;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_INTERVAL_SECONDS;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_LED_COLOR;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_LOYALTY_CARDS;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_MUSIC_ALBUM;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_MUSIC_ARTIST;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_MUSIC_DURATION;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_MUSIC_POSITION;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_MUSIC_RATE;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_MUSIC_REPEAT;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_MUSIC_SHUFFLE;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_MUSIC_STATE;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_MUSIC_TRACK;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_MUSIC_TRACKCOUNT;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_MUSIC_TRACKNR;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NAVIGATION_DISTANCE_TO_TURN;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NAVIGATION_INSTRUCTION;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NAVIGATION_NEXT_ACTION;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NAVIGATION_ETA;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_ACTIONS;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_BODY;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_DNDSUPPRESSED;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_FLAGS;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_ICONID;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_ID;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_PEBBLE_COLOR;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_PHONENUMBER;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_SENDER;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_SOURCEAPPID;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_SOURCENAME;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_SUBJECT;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_TITLE;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_TYPE;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_PHONE_VOLUME;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_RECORDED_DATA_TYPES;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_REMINDERS;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_RESET_FLAGS;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_URI;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_VIBRATION_INTENSITY;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_WEATHER;
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_WORLD_CLOCKS;
public class DeviceCommunicationService extends Service implements SharedPreferences.OnSharedPreferenceChangeListener {
public static class DeviceStruct{
private GBDevice device;
@ -938,6 +825,19 @@ public class DeviceCommunicationService extends Service implements SharedPrefere
deviceSupport.onAppReorder(uuids);
break;
}
case ACTION_MUSIC_FILES_START:
deviceSupport.onMusicFilesStart();
break;
case ACTION_MUSIC_FILES_REQ:
deviceSupport.onMusicFilesReq();
break;
case ACTION_MUSIC_FILES_UPLOAD:
final Uri[] uris = (Uri[]) intent.getParcelableArrayExtra(EXTRA_MUSIC_FILES);
deviceSupport.onMusicFilesUpload(uris);
break;
case ACTION_MUSIC_FILES_STOP:
deviceSupport.onMusicFilesStop();
break;
case ACTION_INSTALL:
Uri uri = intent.getParcelableExtra(EXTRA_URI);
if (uri != null) {

View File

@ -286,6 +286,38 @@ public class ServiceDeviceSupport implements DeviceSupport {
delegate.onAppConfiguration(uuid, config, id);
}
@Override
public void onMusicFilesStart() {
if (checkBusy("music files start")) {
return;
}
delegate.onMusicFilesStart();
}
@Override
public void onMusicFilesReq() {
if (checkBusy("music files req")) {
return;
}
delegate.onMusicFilesReq();
}
@Override
public void onMusicFilesUpload(Uri[] uris) {
if (checkBusy("music files upload")) {
return;
}
delegate.onMusicFilesUpload(uris);
}
@Override
public void onMusicFilesStop() {
if (checkBusy("music files stop")) {
return;
}
delegate.onMusicFilesStop();
}
@Override
public void onAppReorder(UUID[] uuids) {
if (checkBusy("app reorder")) {

View File

@ -0,0 +1,20 @@
/* Copyright (C) 2023 José Rebelo
This file is part of Gadgetbridge.
Gadgetbridge is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gadgetbridge is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos;
public class ZeppOsMusicFilesCoordinator {
}

View File

@ -0,0 +1,99 @@
package nodomain.freeyourgadget.internethelper.aidl.ftp;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.NonNull;
public class FtpEntry implements Parcelable {
public enum Type {
DIRECTORY,
FILE,
SYMLINK,
UNKNOWN,
}
private final String name;
private final Type type;
private final long size;
private final String user;
private final String group;
private final long timestamp;
private final String link;
protected FtpEntry(final Parcel in) {
name = in.readString();
type = Type.values()[in.readInt()];
size = in.readLong();
user = in.readString();
group = in.readString();
timestamp = in.readLong();
link = in.readString();
}
public FtpEntry(final String name, final Type type, final long size, final String user, final String group, final long timestamp, final String link) {
this.name = name;
this.type = type;
this.size = size;
this.user = user;
this.group = group;
this.timestamp = timestamp;
this.link = link;
}
public static final Creator<FtpEntry> CREATOR = new Creator<FtpEntry>() {
@Override
public FtpEntry createFromParcel(final Parcel in) {
return new FtpEntry(in);
}
@Override
public FtpEntry[] newArray(final int size) {
return new FtpEntry[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(@NonNull final Parcel dest, final int flags) {
dest.writeString(name);
dest.writeInt(type.ordinal());
dest.writeLong(size);
dest.writeString(user);
dest.writeString(group);
dest.writeLong(timestamp);
dest.writeString(link);
}
public String getName() {
return name;
}
public Type getType() {
return type;
}
public long getSize() {
return size;
}
public String getUser() {
return user;
}
public String getGroup() {
return group;
}
public long getTimestamp() {
return timestamp;
}
public String getLink() {
return link;
}
}

View File

@ -0,0 +1,48 @@
package nodomain.freeyourgadget.internethelper.aidl.http;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.NonNull;
public class HttpGetRequest implements Parcelable {
private final String url;
private final Bundle headers;
protected HttpGetRequest(final Parcel in) {
url = in.readString();
headers = in.readBundle(ClassLoader.getSystemClassLoader());
}
public static final Creator<HttpGetRequest> CREATOR = new Creator<HttpGetRequest>() {
@Override
public HttpGetRequest createFromParcel(final Parcel in) {
return new HttpGetRequest(in);
}
@Override
public HttpGetRequest[] newArray(final int size) {
return new HttpGetRequest[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(@NonNull final Parcel dest, final int flags) {
dest.writeString(url);
dest.writeBundle(headers);
}
public String getUrl() {
return url;
}
public Bundle getHeaders() {
return headers;
}
}

View File

@ -0,0 +1,52 @@
package nodomain.freeyourgadget.internethelper.aidl.http;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.NonNull;
public class HttpResponse implements Parcelable {
private final int status;
private final Bundle headers;
private final byte[] body;
protected HttpResponse(final Parcel in) {
status = in.readInt();
headers = in.readBundle(ClassLoader.getSystemClassLoader());
final int bodyLength = in.readInt();
body = new byte[bodyLength];
in.readByteArray(body);
}
public HttpResponse(final int status, final Bundle headers, final byte[] body) {
this.status = status;
this.headers = headers;
this.body = body;
}
public static final Creator<HttpResponse> CREATOR = new Creator<HttpResponse>() {
@Override
public HttpResponse createFromParcel(final Parcel in) {
return new HttpResponse(in);
}
@Override
public HttpResponse[] newArray(final int size) {
return new HttpResponse[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(@NonNull final Parcel dest, final int flags) {
dest.writeInt(status);
dest.writeBundle(headers);
dest.writeInt(body.length);
dest.writeByteArray(body);
}
}

View File

@ -5,7 +5,7 @@
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:fitsSystemWindows="true"
tools:context="nodomain.freeyourgadget.gadgetbridge.activities.MusicFilesActivity">
tools:context="nodomain.freeyourgadget.gadgetbridge.activities.musicfiles.MusicFilesActivity">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"