-
Notifications
You must be signed in to change notification settings - Fork 135
[Infra] Adding a button to snapshot the current Media Browse Tree #28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
ff4d395
Adding permissions request
c979015
Working dfs
ac86dc4
Working with race condition
d7d3228
Moving DFS to separate file
891ed0f
working browser DFS with init
d5e4693
Extract into functions
2c6fac8
Changing to Document Request intent
0e80bcf
Switching to kotlin suspend funs
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
126 changes: 126 additions & 0 deletions
126
mediacontroller/src/main/java/com/example/android/mediacontroller/MediaBrowseTreeSnapshot.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
package com.example.android.mediacontroller | ||
|
||
import android.content.Context | ||
import android.os.Handler | ||
import android.os.Looper | ||
import android.support.v4.media.MediaBrowserCompat | ||
import android.support.v4.media.MediaBrowserCompat.SubscriptionCallback | ||
import android.util.Log | ||
import android.widget.Toast | ||
import androidx.lifecycle.ViewModel | ||
import androidx.lifecycle.viewModelScope | ||
import kotlinx.coroutines.launch | ||
import java.io.OutputStream | ||
import java.io.PrintWriter | ||
import kotlin.coroutines.resume | ||
import kotlin.coroutines.suspendCoroutine | ||
|
||
|
||
class MediaBrowseTreeSnapshot(private val context: Context, private val browser: MediaBrowserCompat):ViewModel() { | ||
private val TAG = "MediaBrowseTreeSnapshot" | ||
|
||
|
||
/** | ||
* Loads the browsers top level children and runs a DFS on them printing out | ||
* each media item's contentes as it is visited. | ||
*/ | ||
fun takeBrowserSnapshot(outputStream: OutputStream) { | ||
|
||
viewModelScope.launch { | ||
val mediaItems: MutableList |
||
if (mediaItems.isNotEmpty()) { | ||
runDFSOnBrowseTree(mediaItems, outputStream) | ||
for (item in mediaItems) { | ||
Log.i(TAG, item.toString()) | ||
} | ||
} else { | ||
notifyUser("No media items found, could not save tree.") | ||
} | ||
} | ||
} | ||
|
||
private suspend fun getChildNodes(rootItemMid: String): MutableList |
||
suspendCoroutine { | ||
val mediaItems: MutableList |
||
browser.subscribe(rootItemMid, object : SubscriptionCallback() { | ||
override fun onChildrenLoaded(parentId: String, | ||
children: List |
||
// Notify the main thread that all of the children have loaded | ||
mediaItems.addAll(children) | ||
super.onChildrenLoaded(parentId, children) | ||
it.resume(mediaItems) | ||
} | ||
}) | ||
} | ||
|
||
/** | ||
* Kicks off the browse tree depth first search by visiting all of the top level media | ||
* item nodes. | ||
*/ | ||
private suspend fun runDFSOnBrowseTree(mediaItems: MutableList |
||
val printWriter = PrintWriter(outputStream) | ||
printWriter.println("Root:") | ||
for (item in mediaItems) { | ||
visitMediaItemNode(item, printWriter, 1) | ||
} | ||
printWriter.flush() | ||
printWriter.close() | ||
outputStream.close() | ||
notifyUser("MediaItems saved to specified location.") | ||
} | ||
|
||
/** | ||
* Visits a media item node by printing out its contents and then visiting all of its children. | ||
*/ | ||
private suspend fun visitMediaItemNode(mediaItem: MediaBrowserCompat.MediaItem?, printWriter: PrintWriter, depth: Int) { | ||
if (mediaItem != null) { | ||
printMediaItemDescription(printWriter, mediaItem, depth) | ||
val mid = if (mediaItem.mediaId != null) mediaItem.mediaId!! else "" | ||
|
||
// If a media item is not a leaf continue DFS on it | ||
if (mediaItem.isBrowsable && mid != "") { | ||
|
||
val mediaChildren: MutableList |
||
|
||
// Run visit on all of the nodes children | ||
for (mediaItemChild in mediaChildren) { | ||
visitMediaItemNode(mediaItemChild, printWriter, depth + 1) | ||
Log.i(TAG, "Visiting:" + mediaItemChild.toString()) | ||
} | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Prints the contents of a media item using a print writer. | ||
*/ | ||
private fun printMediaItemDescription(printWriter: PrintWriter, mediaItem: MediaBrowserCompat.MediaItem, depth: Int) { | ||
val descriptionCompat = mediaItem.description | ||
// Tab the media item to the respective depth | ||
val tabStr = String(CharArray(depth)).replace("\u0000", | ||
"\t") | ||
val titleStr = if (descriptionCompat.title != null) descriptionCompat.title.toString() else "NAN" | ||
val subTitleStr = if (descriptionCompat.subtitle != null) descriptionCompat.subtitle.toString() else "NAN" | ||
val mIDStr = if (descriptionCompat.mediaId != null) descriptionCompat.mediaId else "NAN" | ||
val uriStr = if (descriptionCompat.mediaUri != null) descriptionCompat.mediaUri.toString() else "NAN" | ||
val desStr = if (descriptionCompat.description != null) descriptionCompat.description.toString() else "NAN" | ||
val infoStr = String.format( | ||
"%sTitle:%s,Subtitle:%s,MediaId:%s,URI:%s,Description:%s", | ||
tabStr, titleStr, subTitleStr, mIDStr, uriStr, desStr) | ||
printWriter.println(infoStr) | ||
} | ||
|
||
/** | ||
* Display formatted toast to user. | ||
*/ | ||
private fun notifyUser(textToNotify: String) { | ||
Handler(Looper.getMainLooper()).post { | ||
val toast = Toast.makeText( | ||
context, | ||
textToNotify, | ||
Toast.LENGTH_LONG) | ||
toast.setMargin(50f, 50f) | ||
toast.show() | ||
} | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -119,6 +119,7 @@ | |
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider whether this bit (the output part) should be wrapped in a
withContext(Dispatchers.IO)
block.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good! I will merge this then update the functionality soon.