Skip to content

Commit 4abc349

Browse files
authored
Merge pull request #167 from tobexyz/feat/issue67
Feat/issue67
2 parents 1bbf987 + d0d4a95 commit 4abc349

69 files changed

Lines changed: 2502 additions & 460 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

gradle/wrapper/gradle-wrapper.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
33
distributionPath=wrapper/dists
44
zipStoreBase=GRADLE_USER_HOME
55
zipStorePath=wrapper/dists
6-
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip
6+
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-all.zip

yaacc/build.gradle

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
buildscript {
22

33
dependencies {
4-
classpath 'com.android.tools.build:gradle:8.7.3'
4+
classpath 'com.android.tools.build:gradle:8.12.2'
55

66
}
77
}
@@ -15,7 +15,6 @@ dependencies {
1515
testImplementation 'com.tngtech.junit.dataprovider:junit4-dataprovider:2.10'
1616
testImplementation 'xmlpull:xmlpull:1.1.3.1'
1717
testImplementation 'net.sf.kxml:kxml2:2.3.0'
18-
testImplementation 'org.slf4j:slf4j-android:1.7.36'
1918
implementation 'jakarta.enterprise:jakarta.enterprise.cdi-api:4.0.1'
2019
implementation 'com.google.android.material:material:1.7.0'
2120
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'

yaacc/src/main/AndroidManifest.xml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
1717

1818
<uses-permission android:name="android.permission.WAKE_LOCK" />
19+
<uses-permission
20+
android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
21+
tools:ignore="ScopedStorage" />
1922
<uses-permission
2023
android:maxSdkVersion="33"
2124
android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
@@ -37,7 +40,8 @@
3740
android:localeConfig="@xml/locales_config"
3841
android:supportsRtl="true"
3942
android:theme="@style/AppTheme"
40-
android:usesCleartextTraffic="true">
43+
android:usesCleartextTraffic="true"
44+
android:requestLegacyExternalStorage="true">
4145

4246
<activity
4347
android:name=".browser.TabBrowserActivity"

yaacc/src/main/java/de/yaacc/browser/BrowseDeviceAdapter.java

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import android.app.Activity;
2121
import android.content.Context;
2222
import android.content.ContextWrapper;
23+
import android.content.Intent;
2324
import android.net.Uri;
2425
import android.util.Log;
2526
import android.view.LayoutInflater;
@@ -40,9 +41,12 @@
4041
import java.net.URL;
4142
import java.util.LinkedList;
4243
import java.util.List;
44+
import java.util.Timer;
45+
import java.util.TimerTask;
4346

4447
import de.yaacc.R;
4548
import de.yaacc.upnp.UpnpClient;
49+
import de.yaacc.upnp.server.YaaccUpnpServerControlActivity;
4650
import de.yaacc.util.MediaStoreScanner;
4751
import de.yaacc.util.ThemeHelper;
4852
import de.yaacc.util.image.IconDownloadTask;
@@ -86,7 +90,7 @@ public ViewHolder onCreateViewHolder(ViewGroup parent,
8690
View view = LayoutInflater.from(parent.getContext())
8791
.inflate(R.layout.browse_device_item, parent, false);
8892
view.setOnClickListener(new ServerListClickListener(deviceList, this, upnpClient, context));
89-
return new ViewHolder(view);
93+
return new ViewHolder(view, context);
9094
}
9195

9296
@Override
@@ -115,6 +119,7 @@ public void onBindViewHolder(final ViewHolder holder, final int listPosition) {
115119
holder.scanButton.setVisibility(View.VISIBLE);
116120
holder.scanButtonLabel.setVisibility(View.VISIBLE);
117121
holder.icon.setImageResource(R.drawable.yaacc48_24_png);
122+
holder.configButton.setVisibility(View.VISIBLE);
118123
}
119124

120125
holder.name.setText(device.getDetails().getFriendlyName());
@@ -135,16 +140,31 @@ static class ViewHolder extends RecyclerView.ViewHolder {
135140
TextView name;
136141
ImageButton scanButton;
137142
TextView scanButtonLabel;
143+
ImageButton configButton;
138144

145+
Context context;
146+
private Timer timer;
139147

140-
public ViewHolder(View itemView) {
148+
public ViewHolder(View itemView, Context context) {
141149
super(itemView);
142-
this.icon = (ImageView) itemView.findViewById(R.id.browseDeviceItemIcon);
143-
this.name = (TextView) itemView.findViewById(R.id.browseDeviceItemName);
144-
this.scanButtonLabel = (TextView) itemView.findViewById(R.id.browseDeviceItemMediaStoreScanLabel);
145-
this.scanButton = (ImageButton) itemView.findViewById(R.id.browseDeviceItemRescan);
150+
this.context = context;
151+
timer = new Timer();
152+
this.icon = itemView.findViewById(R.id.browseDeviceItemIcon);
153+
this.name = itemView.findViewById(R.id.browseDeviceItemName);
154+
this.scanButtonLabel = itemView.findViewById(R.id.browseDeviceItemMediaStoreScanLabel);
155+
this.scanButton = itemView.findViewById(R.id.browseDeviceItemRescan);
146156
scanButton.setOnClickListener((v) -> {
147-
new MediaStoreScanner().scanMediaFiles(getActivity(v.getContext()));
157+
timer.schedule(new TimerTask() {
158+
@Override
159+
public void run() {
160+
new MediaStoreScanner().scanMediaFiles(getActivity(v.getContext()));
161+
}
162+
}, 10L);
163+
164+
});
165+
this.configButton = itemView.findViewById(R.id.browseDeviceItemConfig);
166+
configButton.setOnClickListener((v) -> {
167+
ViewHolder.this.context.startActivity(new Intent(ViewHolder.this.context, YaaccUpnpServerControlActivity.class));
148168
});
149169
}
150170

yaacc/src/main/java/de/yaacc/browser/TabBrowserActivity.java

Lines changed: 54 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import android.content.pm.PackageManager;
2626
import android.graphics.drawable.Drawable;
2727
import android.net.Uri;
28+
import android.os.Build;
2829
import android.os.Bundle;
2930
import android.os.Handler;
3031
import android.os.Looper;
@@ -84,19 +85,7 @@
8485
* @author Tobias Schoene (the openbit)
8586
*/
8687
public class TabBrowserActivity extends AppCompatActivity implements OnClickListener {
87-
private static final String[] permissions = new String[]{
88-
Manifest.permission.INTERNET,
89-
Manifest.permission.ACCESS_WIFI_STATE,
90-
Manifest.permission.ACCESS_NETWORK_STATE,
91-
Manifest.permission.CHANGE_WIFI_STATE,
92-
Manifest.permission.CHANGE_WIFI_MULTICAST_STATE,
93-
Manifest.permission.READ_EXTERNAL_STORAGE,
94-
Manifest.permission.WRITE_EXTERNAL_STORAGE,
95-
Manifest.permission.RECEIVE_BOOT_COMPLETED,
96-
Manifest.permission.WAKE_LOCK,
97-
Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
98-
99-
};
88+
10089
private static final String CURRENT_TAB_KEY = "currentTab";
10190
//FIXME dirty
10291
public static boolean leftSettings = false;
@@ -111,14 +100,64 @@ public class TabBrowserActivity extends AppCompatActivity implements OnClickList
111100
private Intent serverService = null;
112101
private Toast volumeToast = null;
113102

103+
//https://developer.android.com/about/versions/14/changes/partial-photo-video-access
104+
private static String[] getPermissions() {
105+
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
106+
return new String[]{
107+
Manifest.permission.INTERNET,
108+
Manifest.permission.ACCESS_WIFI_STATE,
109+
Manifest.permission.ACCESS_NETWORK_STATE,
110+
Manifest.permission.CHANGE_WIFI_STATE,
111+
Manifest.permission.CHANGE_WIFI_MULTICAST_STATE,
112+
Manifest.permission.WRITE_EXTERNAL_STORAGE,
113+
Manifest.permission.RECEIVE_BOOT_COMPLETED,
114+
Manifest.permission.WAKE_LOCK,
115+
Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS,
116+
Manifest.permission.READ_MEDIA_AUDIO,
117+
Manifest.permission.READ_MEDIA_IMAGES,
118+
Manifest.permission.READ_MEDIA_VIDEO,
119+
Manifest.permission.MANAGE_EXTERNAL_STORAGE
120+
121+
};
122+
} else if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
123+
return new String[]{
124+
Manifest.permission.INTERNET,
125+
Manifest.permission.ACCESS_WIFI_STATE,
126+
Manifest.permission.ACCESS_NETWORK_STATE,
127+
Manifest.permission.CHANGE_WIFI_STATE,
128+
Manifest.permission.CHANGE_WIFI_MULTICAST_STATE,
129+
Manifest.permission.WRITE_EXTERNAL_STORAGE,
130+
Manifest.permission.READ_EXTERNAL_STORAGE,
131+
Manifest.permission.RECEIVE_BOOT_COMPLETED,
132+
Manifest.permission.WAKE_LOCK,
133+
Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS,
134+
Manifest.permission.MANAGE_EXTERNAL_STORAGE
135+
};
136+
}
137+
return new String[]{
138+
Manifest.permission.INTERNET,
139+
Manifest.permission.ACCESS_WIFI_STATE,
140+
Manifest.permission.ACCESS_NETWORK_STATE,
141+
Manifest.permission.CHANGE_WIFI_STATE,
142+
Manifest.permission.CHANGE_WIFI_MULTICAST_STATE,
143+
Manifest.permission.READ_EXTERNAL_STORAGE,
144+
Manifest.permission.WRITE_EXTERNAL_STORAGE,
145+
Manifest.permission.RECEIVE_BOOT_COMPLETED,
146+
Manifest.permission.WAKE_LOCK,
147+
Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
148+
149+
};
150+
151+
}
152+
114153
@Override
115154
protected void onSaveInstanceState(@NonNull Bundle outState) {
116155
super.onSaveInstanceState(outState);
117156
outState.putInt(CURRENT_TAB_KEY, tabLayout.getSelectedTabPosition());
118157
}
119158

120159
private boolean checkIfAlreadyhavePermission() {
121-
for (String permission : permissions) {
160+
for (String permission : getPermissions()) {
122161
int permissionState = ContextCompat.checkSelfPermission(this, permission);
123162
if (permissionState == PackageManager.PERMISSION_DENIED) {
124163
return false;
@@ -128,7 +167,7 @@ private boolean checkIfAlreadyhavePermission() {
128167
}
129168

130169
private void requestForSpecificPermission() {
131-
ActivityCompat.requestPermissions(this, permissions,
170+
ActivityCompat.requestPermissions(this, getPermissions(),
132171
101);
133172

134173
}

yaacc/src/main/java/de/yaacc/imageviewer/ImageViewerActivity.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ private void init(Bundle savedInstanceState, Intent intent) {
165165
}
166166
pictureShowActive = intent.getBooleanExtra(AUTO_START_SHOW, false);
167167
}
168-
if (imageUris.size() > 0) {
168+
if (imageUris != null && !imageUris.isEmpty()) {
169169
loadImage();
170170
} else {
171171
runOnUiThread(() -> {
@@ -180,12 +180,12 @@ private void init(Bundle savedInstanceState, Intent intent) {
180180

181181
@Override
182182
protected void onDestroy() {
183-
super.onDestroy();
184183
try {
185184
unbindService(this);
186185
} catch (IllegalArgumentException iae) {
187186
Log.d(getClass().getName(), "Ignore exception on unbind service while activity destroy");
188187
}
188+
super.onDestroy();
189189
}
190190

191191
/*
@@ -198,9 +198,9 @@ protected void onResume() {
198198

199199
imageViewerBroadcastReceiver = new ImageViewerBroadcastReceiver(this);
200200
imageViewerBroadcastReceiver.registerReceiver();
201-
super.onResume();
202201
this.bindService(new Intent(this, PlayerService.class),
203202
this, Context.BIND_AUTO_CREATE);
203+
super.onResume();
204204
}
205205

206206
/*

yaacc/src/main/java/de/yaacc/imageviewer/RetrieveImageTask.java

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -183,23 +183,12 @@ private InputStream getUriAsStream(Uri imageUri)
183183
private Bitmap decodeSampledBitmapFromStream(Uri imageUri, int reqWidth,
184184
int reqHeight) throws IOException {
185185
InputStream is = getUriAsStream(imageUri);
186-
int tmpWidth = reqWidth;
187-
int tmpHeight = reqHeight;
188-
if (reqHeight > 2048) {
189-
tmpHeight = 2048;
190-
tmpWidth = reqHeight * (2048 / reqWidth);
191-
}
192-
if (reqWidth > 2048) {
193-
tmpWidth = 2048;
194-
tmpHeight = reqWidth * (2048 / reqHeight);
195-
}
196-
197186
final BitmapFactory.Options options = new BitmapFactory.Options();
198187
options.inJustDecodeBounds = false;
199-
options.outHeight = tmpHeight;
200-
options.outWidth = tmpWidth;
188+
options.outHeight = reqHeight;
189+
options.outWidth = reqWidth;
201190
options.inDensity = DisplayMetrics.DENSITY_LOW;
202-
options.inTempStorage = new byte[7680016];
191+
options.inSampleSize = 2;
203192
Log.d(this.getClass().getName(),
204193
"displaying image size width, height, inSampleSize "
205194
+ options.outWidth + "," + options.outHeight + ","

yaacc/src/main/java/de/yaacc/musicplayer/BackgroundMusicService.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,21 @@ public BackgroundMusicService() {
6767
public void onCreate() {
6868
super.onCreate();
6969
Log.d(this.getClass().getName(), "On Create");
70+
71+
// Start foreground immediately with a basic notification
72+
Notification minimalNotification = new NotificationCompat.Builder(this, Yaacc.NOTIFICATION_CHANNEL_ID)
73+
.setContentTitle("Background Music Service")
74+
.setContentText("Initializing...")
75+
.setSmallIcon(R.drawable.ic_notification_default)
76+
.setGroup(Yaacc.NOTIFICATION_GROUP_KEY) // Ensure group is set for consistency
77+
.setSilent(true) // Keep it silent initially
78+
.build();
79+
startForeground(NotificationId.BACKGROUND_MUSIC_SERVICE.getId(), minimalNotification);
80+
81+
// Perform potentially long-running initializations
7082
((Yaacc) getApplicationContext()).createYaaccGroupNotification();
83+
84+
// Now create and set the final notification
7185
Intent notificationIntent = new Intent(this, TabBrowserActivity.class);
7286
PendingIntent pendingIntent = PendingIntent.getActivity(this,
7387
0, notificationIntent, PendingIntent.FLAG_IMMUTABLE);
@@ -79,6 +93,7 @@ public void onCreate() {
7993
.setContentIntent(pendingIntent)
8094
.setGroup(Yaacc.NOTIFICATION_GROUP_KEY)
8195
.build();
96+
// Update the notification by calling startForeground again
8297
startForeground(NotificationId.BACKGROUND_MUSIC_SERVICE.getId(), notification);
8398

8499
}
@@ -290,4 +305,4 @@ public BackgroundMusicService getService() {
290305
}
291306
}
292307

293-
}
308+
}

yaacc/src/main/java/de/yaacc/player/PlayableItem.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public class PlayableItem {
3939
private Uri uri;
4040
private long duration;
4141

42-
private UUID id;
42+
private final UUID id;
4343

4444

4545
public PlayableItem(Item item, int defaultDuration) {
@@ -50,7 +50,7 @@ public PlayableItem(Item item, int defaultDuration) {
5050
if (resource != null) {
5151
setUri(Uri.parse(resource.getValue()));
5252
String mimeType = resource.getProtocolInfo().getContentFormat();
53-
if (mimeType == null || mimeType.equals("")) {
53+
if (mimeType == null || mimeType.isEmpty()) {
5454
String fileExtension = MimeTypeMap.getFileExtensionFromUrl(getUri().toString());
5555
mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(fileExtension);
5656
}
@@ -59,7 +59,7 @@ public PlayableItem(Item item, int defaultDuration) {
5959
// calculate duration
6060

6161
long millis = defaultDuration;
62-
Log.d(getClass().getName(), "resource.getDuration(): " + resource.getDuration());
62+
Log.v(getClass().getName(), "resource.getDuration(): " + resource.getDuration());
6363
if (resource.getDuration() != null) {
6464
try {
6565
String[] tokens = resource.getDuration().split(":");
@@ -72,7 +72,7 @@ public PlayableItem(Item item, int defaultDuration) {
7272
if (tokens.length > 2) {
7373
String seconds = tokens[2];
7474
if (tokens[2].contains(".")) {
75-
Log.d(getClass().getName(), "tokens[2]: " + tokens[2] + "spli: " + tokens[2].split("\\.").length);
75+
Log.d(getClass().getName(), "tokens[2]: " + tokens[2] + "split: " + tokens[2].split("\\.").length);
7676
seconds = tokens[2].split("\\.")[0];
7777
}
7878
millis += Long.parseLong(seconds);

0 commit comments

Comments
 (0)