@@ -1155,6 +1155,7 @@ private class BrowseMediaItemsAdapter extends
11551155
11561156 private List <MediaBrowserCompat .MediaItem > mItems ;
11571157 private final Stack <String > mNodes = new Stack <>();
1158+ private MediaBrowseTreeSnapshot mMediaBrowseTreeSnapshot ;
11581159
11591160 MediaBrowserCompat .SubscriptionCallback callback =
11601161 new MediaBrowserCompat .SubscriptionCallback () {
@@ -1180,7 +1181,6 @@ public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
11801181 public void onBindViewHolder (@ NonNull ViewHolder holder , int position ){
11811182 Log .i (TAG , "On Bind view holder" );
11821183 if (mNodes .size () == 0 ) {
1183- Log .i (TAG , "Setting to no browser" );
11841184 holder .name .setText (getString (R .string .media_no_browser ));
11851185 holder .name .setVisibility (View .VISIBLE );
11861186 holder .description .setVisibility (View .GONE );
@@ -1268,7 +1268,6 @@ void updateItems(List<MediaBrowserCompat.MediaItem> items) {
12681268 * Assigns click handlers to the buttons if provided for moving to the top of the tree or
12691269 * for moving up one level in the tree.
12701270 */
1271- @ RequiresApi (api = Build .VERSION_CODES .N )
12721271 void init (View topButtonView , View upButtonView , View saveButtonView ) {
12731272 if (topButtonView != null ) {
12741273 topButtonView .setOnClickListener (v -> {
@@ -1292,172 +1291,26 @@ void init(View topButtonView, View upButtonView, View saveButtonView) {
12921291 });
12931292 }
12941293 if (saveButtonView != null ) {
1295-
1296- // Go to root of browse tree
1297- // TODO: Fix race condition with subscription callback
1298- unsubscribe ();
1299- while (mNodes .size () > 1 ) {
1300- mNodes .pop ();
1301- }
1302- subscribe ();
1303- saveButtonView .setOnClickListener (
1304- v -> {
1305-
1306- if (mNodes .isEmpty ()) {
1307- Toast toast =
1308- Toast .makeText (
1309- getApplicationContext (),
1310- "List Empty, nothing saved! " , Toast .LENGTH_LONG );
1311- toast .setMargin (50 , 50 );
1312- toast .show ();
1313- return ;
1314- }
1315-
1316- // Create output file
1317- File root = android .os .Environment .getExternalStorageDirectory ();
1318- String dirs_path = root .getAbsolutePath () + "/Temp/" ;
1319- File dirs = new File (dirs_path );
1320- dirs .mkdirs ();
1321- File file = new File (dirs .getAbsolutePath (),
1322- "_BrowseTreeContent.txt" );
1323- if (file .exists ()) {
1324- file .delete ();
1325- }
1326- try {
1327- final FileOutputStream f = new FileOutputStream (file );
1328- PrintWriter pw = new PrintWriter (f );
1329- if (mItems == null ){
1330- Log .i (TAG , "Nodes: " + mNodes .toString ());
1331- subscribe ();
1332- Toast toast =
1333- Toast .makeText (
1334- getApplicationContext (),
1335- "No media items found, could not save tree." ,
1336- Toast .LENGTH_LONG );
1337- toast .setMargin (50 , 50 );
1338- toast .show ();
1339- return ;
1340- }
1341- pw .println ("Root:" );
1342- Semaphore writeCompleted = new Semaphore (1 );
1343- ExecutorService executorService =
1344- Executors .newFixedThreadPool (4 );
1345- executorService .execute (new Runnable () {
1346- @ Override
1347- public void run () {
1348- for (MediaBrowserCompat .MediaItem item : mItems ) {
1349- try {
1350- writeCompleted .acquire ();
1351- } catch (InterruptedException e ) {
1352- e .printStackTrace ();
1353- }
1354- writeMediaItemToFile (item , pw , 1 ,
1355- executorService );
1356- writeCompleted .release ();
1357-
1358- }
1359- pw .flush ();
1360- pw .close ();
1361- try {
1362- f .close ();
1363- } catch (IOException e ) {
1364- e .printStackTrace ();
1365- }
1366- runOnUiThread (new Runnable () {
1367- public void run () {
1368- Toast toast =
1369- Toast .makeText (
1370- getApplicationContext (),
1371- "MediaItems saved to " +
1372- file .getAbsolutePath (),
1373- Toast .LENGTH_LONG );
1374- toast .setMargin (50 , 50 );
1375- toast .show ();
1376- }
1377- });
1378- }
1379- });
1380- } catch (FileNotFoundException e ) {
1381- e .printStackTrace ();
1382- }
1383- });
1384- }
1385-
1386- }
1387-
1388- @ RequiresApi (api = Build .VERSION_CODES .N )
1389- private void writeMediaItemToFile (MediaItem mediaItem , PrintWriter printWriter , int depth ,
1390- ExecutorService executorService ) {
1391- if (mediaItem != null ) {
1392- MediaDescriptionCompat descriptionCompat = mediaItem .getDescription ();
1393- if (descriptionCompat != null ) {
1394-
1395- // Tab the media item to the respective depth
1396- String tabStr = new String (new char [depth ]).replace ("\0 " ,
1397- "\t " );
1398-
1399- String titleStr = descriptionCompat .getTitle () != null
1400- ? descriptionCompat .getTitle ().toString ()
1401- : "NAN" ;
1402- String subTitleStr = descriptionCompat .getSubtitle () != null
1403- ? descriptionCompat .getSubtitle ().toString ()
1404- : "NAN" ;
1405- String mIDStr = descriptionCompat .getMediaId () != null
1406- ? descriptionCompat .getMediaId ()
1407- : "NAN" ;
1408- String uriStr = descriptionCompat .getMediaUri () != null
1409- ? descriptionCompat .getMediaUri ().toString ()
1410- : "NAN" ;
1411- String desStr = descriptionCompat .getDescription () != null
1412- ? descriptionCompat .getDescription ().toString ()
1413- : "NAN" ;
1414- String infoStr = String .format (
1415- "%sTitle:%s,Subtitle:%s,MediaId:%s,URI:%s,Description:%s" ,
1416- tabStr , titleStr , subTitleStr , mIDStr , uriStr , desStr );
1417- Log .i (TAG , "Logging media item: " + infoStr + " at depth: " + depth );
1418- printWriter .println (infoStr );
1419- }
1420- // If a media item is not a leaf continue DFS on it
1421- if (mediaItem .isBrowsable ()) {
1422- Log .i (TAG , "Media Item is browseable" );
1423- Semaphore loaded = new Semaphore (1 );
1424- try {
1425- loaded .acquire ();
1426- } catch (InterruptedException e ) {
1427- e .printStackTrace ();
1294+ saveButtonView .setOnClickListener (v -> {
1295+ if (mMediaBrowseTreeSnapshot != null ) {
1296+ mMediaBrowseTreeSnapshot .takeBrowserSnapshot ();
14281297 }
1429- final List <MediaItem > mChildren = new ArrayList <MediaItem >();
1430- executorService .execute (new Runnable () {
1431- @ Override
1432- public void run () {
1433- mBrowser .subscribe (mediaItem .getMediaId (),
1434- new MediaBrowserCompat .SubscriptionCallback () {
1435- @ Override
1436- public void onChildrenLoaded (@ NonNull String parentId ,
1437- @ NonNull List <MediaItem > children ) {
1438- // Notify the main thread that all of the children have loaded
1439- mChildren .addAll (children );
1440- loaded .release ();
1441- super .onChildrenLoaded (parentId , children );
1442- }
1443- });
1444- }
1445- });
1446-
1447- // Wait for all of the media children to be loaded before continuing DFS
1448- try {
1449- loaded .acquire ();
1450- } catch (InterruptedException e ) {
1451- e .printStackTrace ();
1298+ else if (mBrowser != null ) {
1299+ mMediaBrowseTreeSnapshot = new MediaBrowseTreeSnapshot (mBrowser , getApplicationContext ());
1300+ mMediaBrowseTreeSnapshot .takeBrowserSnapshot ();
14521301 }
1453-
1454- // Run DFS on all of the nodes children
1455- for (MediaItem mediaItemChild : mChildren ) {
1456- writeMediaItemToFile (mediaItemChild , printWriter , depth + 1 ,
1457- executorService );
1302+ else {
1303+ Log .e (TAG , "Media browser is null" );
1304+ runOnUiThread (new Runnable () {
1305+ @ Override
1306+ public void run () {
1307+ Toast .makeText (getApplicationContext (),"No media browser to snapshot" , Toast .LENGTH_SHORT ).show ();
1308+ }
1309+ });
14581310 }
1459- }
1311+ });
14601312 }
1313+
14611314 }
14621315
14631316 protected void subscribe () {
0 commit comments