Skip to content

Commit 9b0ace4

Browse files
authored
Merge pull request #190 from tobexyz/feat/issue151-2
issue #151 bugixing
2 parents 3e6b051 + 2f94038 commit 9b0ace4

6 files changed

Lines changed: 175 additions & 175 deletions

File tree

yaacc/src/main/java/de/yaacc/Yaacc.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@
4949
import de.yaacc.upnp.UpnpRegistryService;
5050
import de.yaacc.upnp.server.YaaccAudioRenderingControlService;
5151
import de.yaacc.upnp.server.YaaccUpnpServerService;
52-
import de.yaacc.upnp.server.contentdirectory.SafPermissionManager;
5352
import de.yaacc.util.NotificationId;
53+
import de.yaacc.util.SafPermissionManager;
5454
import de.yaacc.util.ShutdownTimerListener;
5555

5656
/**

yaacc/src/main/java/de/yaacc/upnp/server/YaaccUpnpServerControlActivity.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,9 @@
5050
import de.yaacc.R;
5151
import de.yaacc.settings.SettingsActivity;
5252
import de.yaacc.upnp.server.contentdirectory.MediaPathFilter;
53-
import de.yaacc.upnp.server.contentdirectory.SafPermissionManager;
5453
import de.yaacc.util.AboutActivity;
5554
import de.yaacc.util.NotificationId;
55+
import de.yaacc.util.SafPermissionManager;
5656
import de.yaacc.util.ThemeHelper;
5757
import de.yaacc.util.YaaccLogActivity;
5858

@@ -154,12 +154,12 @@ protected void onCreate(Bundle savedInstanceState) {
154154

155155
private void selectSafContent() {
156156
if (!SafPermissionManager.canAddMorePermissions(this)) {
157-
Log.w(getClass().getName(), "Cannot add more SAF permissions. Limit reached: " +
158-
SafPermissionManager.getPermissionCount(this));
157+
Log.w(getClass().getName(), "Cannot add more SAF permissions. Limit reached: " +
158+
SafPermissionManager.getPermissionCount(this));
159159
// TODO: Show user dialog about limit
160160
return;
161161
}
162-
162+
163163
Log.w(getClass().getName(), "Starting SAF picker.");
164164
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
165165
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
@@ -346,7 +346,7 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
346346
uriSet.add(newUri);
347347
}
348348
MediaPathFilter.saveSafPathes(getApplicationContext(), uriSet);
349-
349+
350350
// Also add to selected paths for content directory
351351
Set<String> selectedUriSet = MediaPathFilter.getSelectedSafPathes(getApplicationContext());
352352
if (selectedUriSet == null) {

yaacc/src/main/java/de/yaacc/upnp/server/contentdirectory/SafFolderBrowser.java

Lines changed: 70 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@
1919
package de.yaacc.upnp.server.contentdirectory;
2020

2121
import android.content.Context;
22+
import android.content.SharedPreferences;
2223
import android.media.MediaMetadataRetriever;
2324
import android.net.Uri;
2425
import android.provider.DocumentsContract;
2526
import android.util.Base64;
2627
import android.util.Log;
2728

2829
import androidx.documentfile.provider.DocumentFile;
30+
import androidx.preference.PreferenceManager;
2931

3032
import org.fourthline.cling.support.model.DIDLObject;
3133
import org.fourthline.cling.support.model.Protocol;
@@ -100,10 +102,10 @@ public Integer getSize(YaaccContentDirectory contentDirectory, String myId) {
100102

101103
@Override
102104
public List<Container> browseContainer(YaaccContentDirectory contentDirectory, String myId, long firstResult, long maxResults, SortCriterion[] orderby) {
103-
Log.d("SafFolderBrowser", "browseContainer called with myId: " + myId);
105+
Log.d(getClass().getName(), "browseContainer called with myId: " + myId);
104106
List<Container> result = new ArrayList<>();
105107
if (myId.equals(ContentDirectoryIDs.SAF_FOLDER.getId())) {
106-
Log.d("SafFolderBrowser", "Browsing root SAF folder");
108+
Log.d(getClass().getName(), "Browsing root SAF folder");
107109
List<String> sortedPathes = new ArrayList<>(getSelectedSafPathes());
108110
Collections.sort(sortedPathes);
109111

@@ -117,18 +119,18 @@ public List<Container> browseContainer(YaaccContentDirectory contentDirectory, S
117119
String title = file.getName() != null ? file.getName() : path;
118120
String base64Str = Base64.encodeToString(file.getUri().toString().getBytes(), Base64.NO_WRAP);
119121
String folderId = ContentDirectoryIDs.SAF_PREFIX.getId() + base64Str;
120-
Log.d("SafFolderBrowser", "Creating root folder: " + title + " with ID: " + folderId);
122+
Log.d(getClass().getName(), "Creating root folder: " + title + " with ID: " + folderId);
121123
StorageFolder folder = new StorageFolder(folderId, ContentDirectoryIDs.SAF_FOLDER.getId(), title, "yaacc", 0, null);
122124
result.add(folder);
123125
}
124126
}
125127
} else {
126128
// Browse subfolder
127-
Log.d("SafFolderBrowser", "Browsing subfolder with ID: " + myId);
129+
Log.d(getClass().getName(), "Browsing subfolder with ID: " + myId);
128130
String pathEnc = myId.substring(ContentDirectoryIDs.SAF_PREFIX.getId().length());
129-
Log.d("SafFolderBrowser", "Encoded path: " + pathEnc);
131+
Log.d(getClass().getName(), "Encoded path: " + pathEnc);
130132
String path = new String(Base64.decode(pathEnc.getBytes(), Base64.NO_WRAP));
131-
Log.d("SafFolderBrowser", "Decoded path: " + path);
133+
Log.d(getClass().getName(), "Decoded path: " + path);
132134

133135
Uri uri = Uri.parse(path);
134136
DocumentFile root = null;
@@ -137,62 +139,62 @@ public List<Container> browseContainer(YaaccContentDirectory contentDirectory, S
137139
if (path.contains("/tree/")) {
138140
// This is a tree URI, use it directly
139141
root = DocumentFile.fromTreeUri(getContext(), uri);
140-
Log.d("SafFolderBrowser", "Using tree URI: " + path);
142+
Log.d(getClass().getName(), "Using tree URI: " + path);
141143
} else {
142144
// This is a document URI, we need to find it within its parent tree
143-
Log.d("SafFolderBrowser", "Document URI detected, finding parent tree: " + path);
145+
Log.d(getClass().getName(), "Document URI detected, finding parent tree: " + path);
144146
// For now, skip these problematic folders to avoid showing parent content
145-
Log.w("SafFolderBrowser", "Skipping document URI folder to avoid parent content");
147+
Log.w(getClass().getName(), "Skipping document URI folder to avoid parent content");
146148
return result;
147149
}
148150

149151
if (root != null && root.isDirectory()) {
150152
DocumentFile[] files = root.listFiles();
151-
Log.d("SafFolderBrowser", "Found " + files.length + " files in subfolder");
153+
Log.d(getClass().getName(), "Found " + files.length + " files in subfolder");
152154
int start = (int) Math.max(0, firstResult);
153155
int end = (int) Math.min(files.length, start + maxResults);
154-
Log.d("SafFolderBrowser", "Parent: " + myId);
156+
Log.d(getClass().getName(), "Parent: " + myId);
155157
for (int i = start; i < end; i++) {
156158
DocumentFile file = files[i];
157159
if (file.isDirectory()) {
158-
Log.d("SafFolderBrowser", "Child: " + file.getUri().toString());
160+
Log.d(getClass().getName(), "Child: " + file.getUri());
159161
String title = file.getName() != null ? file.getName() : file.getUri().toString();
160162

161163
// Create tree URI for the child folder so it can be browsed properly
162164
try {
163165
String authority = file.getUri().getAuthority();
164166
String documentId = DocumentsContract.getDocumentId(file.getUri());
165167
Uri childTreeUri = DocumentsContract.buildTreeDocumentUri(authority, documentId);
166-
Log.d("SafFolderBrowser", "Child tree URI: " + childTreeUri);
168+
Log.d(getClass().getName(), "Child tree URI: " + childTreeUri);
167169

168170
// Test if we can access this tree URI
169171
DocumentFile testAccess = DocumentFile.fromTreeUri(getContext(), childTreeUri);
170-
if (testAccess != null && testAccess.canRead()) {
172+
if (testAccess != null) {
171173
String base64Str = Base64.encodeToString(childTreeUri.toString().getBytes(), Base64.NO_WRAP);
172174
String childId = ContentDirectoryIDs.SAF_PREFIX.getId() + base64Str;
173-
Log.d("SafFolderBrowser", "Creating child folder: " + title + " with ID: " + childId);
175+
Log.d(getClass().getName(), "Creating child folder: " + title + " with ID: " + childId);
174176
StorageFolder folder = new StorageFolder(childId, myId, title, "yaacc", 0, null);
177+
folder.setRestricted(testAccess.canRead());
175178
result.add(folder);
176179
} else {
177-
178-
Log.w("SafFolderBrowser", "Cannot access child tree URI, skipping folder: " + title);
180+
Log.w(getClass().getName(), "Cannot access child tree URI, skipping folder: " + title);
179181
}
180182
} catch (Exception e) {
181-
Log.e("SafFolderBrowser", "Error creating tree URI for child, skipping folder: " + title, e);
183+
Log.e(getClass().getName(), "Error creating tree URI for child, skipping folder: " + title, e);
182184
}
183185
}
184186
}
185187
} else {
186-
Log.e("SafFolderBrowser", "Root DocumentFile is null or not a directory for path: " + path);
188+
Log.e(getClass().getName(), "Root DocumentFile is null or not a directory for path: " + path);
187189
}
188190
}
189-
Log.d("SafFolderBrowser", "Returning " + result.size() + " containers");
191+
Log.d(getClass().getName(), "Returning " + result.size() + " containers");
190192
return result;
191193
}
192194

193195
@Override
194196
public List<Item> browseItem(YaaccContentDirectory contentDirectory, String myId, long firstResult, long maxResults, SortCriterion[] orderby) {
195-
Log.d("SafFolderBrowser", "browseItem called with myId: " + myId);
197+
Log.d(getClass().getName(), "browseItem called with myId: " + myId);
196198
List<Item> result = new ArrayList<>();
197199
if (myId.equals(ContentDirectoryIDs.SAF_FOLDER.getId())) {
198200
List<String> sortedPathes = new ArrayList<>(getSelectedSafPathes());
@@ -205,38 +207,47 @@ public List<Item> browseItem(YaaccContentDirectory contentDirectory, String myId
205207
String path = sortedPathes.get(i);
206208
DocumentFile file = DocumentFile.fromSingleUri(getContext(), Uri.parse(path));
207209
if (file != null && !file.isDirectory()) {
208-
addItem(contentDirectory, result, path, file, myId);
210+
addItem(contentDirectory, result, path, file, myId, !file.canRead());
209211
}
210212
}
211213
} else {
212214
// Browse subfolder items
213-
Log.d("SafFolderBrowser", "Browsing subfolder items for: " + myId);
215+
Log.d(getClass().getName(), "Browsing subfolder items for: " + myId);
214216
String pathEnc = myId.substring(ContentDirectoryIDs.SAF_PREFIX.getId().length());
215217
String path = new String(Base64.decode(pathEnc.getBytes(), Base64.NO_WRAP));
216-
Log.d("SafFolderBrowser", "Decoded path: " + path);
218+
Log.d(getClass().getName(), "Decoded path: " + path);
217219
DocumentFile root = DocumentFile.fromTreeUri(getContext(), Uri.parse(path));
218220
if (root != null && root.isDirectory()) {
219-
DocumentFile[] files = root.listFiles();
220-
Log.d("SafFolderBrowser", "Found " + files.length + " files in folder");
221-
int start = (int) Math.max(0, firstResult);
222-
int end = (int) Math.min(files.length, start + maxResults);
223-
for (int i = start; i < end; i++) {
224-
DocumentFile file = files[i];
225-
if (!file.isDirectory()) {
226-
addItem(contentDirectory, result, file.getUri().toString(), file, myId);
221+
if (root.canRead()) {
222+
DocumentFile[] files = root.listFiles();
223+
Log.d(getClass().getName(), "Found " + files.length + " files in folder");
224+
int start = (int) Math.max(0, firstResult);
225+
int end = (int) Math.min(files.length, start + maxResults);
226+
for (int i = start; i < end; i++) {
227+
DocumentFile file = files[i];
228+
if (!file.isDirectory()) {
229+
addItem(contentDirectory, result, file.getUri().toString(), file, myId, !file.canRead());
230+
}
227231
}
232+
} else {
233+
Log.w(getClass().getName(), "Cannot access folder, skipping: " + path);
228234
}
229235
} else {
230-
Log.e("SafFolderBrowser", "Root DocumentFile is null or not a directory for path: " + path);
236+
Log.e(getClass().getName(), "Root DocumentFile is null or not a directory for path: " + path);
231237
}
232238
}
233-
Log.d("SafFolderBrowser", "Returning " + result.size() + " items");
239+
Log.d(getClass().getName(), "Returning " + result.size() + " items");
234240
return result;
235241
}
236242

237-
private void addItem(YaaccContentDirectory contentDirectory, List<Item> result, String path, DocumentFile file, String parentId) {
243+
private void addItem(YaaccContentDirectory contentDirectory, List<Item> result, String path, DocumentFile file, String parentId, boolean restricted) {
238244
String mimeTypeStr = file.getType();
239-
245+
long currentTime = System.currentTimeMillis();
246+
Log.d(getClass().getName(), "Adding item for: " + path + " with mime type: " + mimeTypeStr);
247+
if (file.getName().endsWith("m3u")) {
248+
Log.d(getClass().getName(), "Ignoring m3u file");
249+
return;
250+
}
240251
if (mimeTypeStr != null) {
241252
MimeType mimeType = MimeType.valueOf(mimeTypeStr);
242253
String mimeTypeMain = mimeType.getType();
@@ -250,24 +261,30 @@ private void addItem(YaaccContentDirectory contentDirectory, List<Item> result,
250261
ProtocolInfo protocolInfo = new ProtocolInfo(Protocol.HTTP_GET, ProtocolInfo.WILDCARD, mimeType.toString(), getDLNAAttributes(mimeType));
251262

252263
// Create resource without duration first for audio files
253-
String duration = extractDuration(file);
264+
265+
String duration = null;
266+
if (mimeTypeMain.equals("audio") && !restricted) {
267+
Log.d(getClass().getName(), "Extracting duration for: " + file.getUri() + " took: " + (System.currentTimeMillis() - currentTime) + "ms");
268+
duration = extractDuration(file);
269+
Log.d(getClass().getName(), "Extracted duration for: " + file.getUri() + " took: " + (System.currentTimeMillis() - currentTime) + "ms");
270+
}
254271
Res res = new Res(protocolInfo, file.length(), duration, null, uri);
255272

256273
Item item = null;
257274
if (mimeTypeMain.equals("audio")) {
258275
item = new AudioItem(id, parentId, title, "yaacc", res);
259-
// Load duration asynchronously
260-
//loadDurationAsync(file, item, res);
261276
} else if (mimeTypeMain.equals("video")) {
262277
item = new VideoItem(id, parentId, title, "yaacc", res);
263278
} else if (mimeTypeMain.equals("image")) {
264279
item = new ImageItem(id, parentId, title, "yaacc", res);
265280
}
266281

267282
if (item != null) {
283+
item.setRestricted(restricted);
268284
result.add(item);
269285
}
270286
}
287+
Log.d(getClass().getName(), "Added item for: " + path + "took: " + (System.currentTimeMillis() - currentTime) + "ms");
271288
}
272289

273290
/*
@@ -290,36 +307,43 @@ protected void onPostExecute(String duration) {
290307
// Replace the resource in the item
291308
item.getResources().clear();
292309
item.addResource(newRes);
293-
Log.d("SafFolderBrowser", "Updated duration for: " + item.getTitle() + " -> " + duration);
310+
Log.d(getClass().getName(), "Updated duration for: " + item.getTitle() + " -> " + duration);
294311
} catch (Exception e) {
295-
Log.w("SafFolderBrowser", "Failed to update duration for: " + item.getTitle(), e);
312+
Log.w(getClass().getName(), "Failed to update duration for: " + item.getTitle(), e);
296313
}
297314
}
298-
Log.d("SafFolderBrowser", "Item ready for playback: " + item.getTitle());
315+
Log.d(getClass().getName(), "Item ready for playback: " + item.getTitle());
299316
}
300317
}.execute();
301318
}
302319
*/
303320
private String extractDuration(DocumentFile file) {
304-
305321
MediaMetadataRetriever retriever = null;
322+
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getContext());
323+
if (preferences.contains(getContext().getString(R.string.settings_duration_format_key) + file.getUri())) {
324+
Log.d(getClass().getName(), "Found duration in cache for: " + file.getUri());
325+
return preferences.getString(getContext().getString(R.string.settings_duration_format_key) + file.getUri(), null);
326+
}
306327
try {
307328
retriever = new MediaMetadataRetriever();
308329
retriever.setDataSource(getContext(), file.getUri());
309330
String durationStr = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
310331

311332
if (durationStr != null) {
312333
long durationMs = Long.parseLong(durationStr);
313-
return FormatHelper.parseMillisToTimeStringTo(durationMs);
334+
String durationString = FormatHelper.parseMillisToTimeStringTo(durationMs);
335+
Log.d(getClass().getName(), "Put duration in cache for: " + file.getUri());
336+
preferences.edit().putString(getContext().getString(R.string.settings_duration_format_key) + file.getUri(), durationString).apply();
337+
return durationString;
314338
}
315339
} catch (Exception e) {
316-
Log.w("SafFolderBrowser", "Could not extract duration from: " + file.getUri(), e);
340+
Log.w(getClass().getName(), "Could not extract duration from: " + file.getUri(), e);
317341
} finally {
318342
if (retriever != null) {
319343
try {
320344
retriever.release();
321345
} catch (Exception e) {
322-
Log.w("SafFolderBrowser", "Error releasing MediaMetadataRetriever", e);
346+
Log.w(getClass().getName(), "Error releasing MediaMetadataRetriever", e);
323347
}
324348
}
325349
}

0 commit comments

Comments
 (0)