Skip to content

Commit 2c6fac8

Browse files
author
Leo Neat
committed
Changing to Document Request intent
modified: mediacontroller/src/main/AndroidManifest.xml modified: mediacontroller/src/main/java/com/example/android/mediacontroller/MediaAppControllerActivity.java modified: mediacontroller/src/main/java/com/example/android/mediacontroller/MediaAppListAdapter.java modified: mediacontroller/src/main/java/com/example/android/mediacontroller/MediaBrowseTreeSnapshot.kt modified: mediacontroller/src/main/AndroidManifest.xml modified: mediacontroller/src/main/java/com/example/android/mediacontroller/MediaAppControllerActivity.java modified: mediacontroller/src/main/java/com/example/android/mediacontroller/MediaAppListAdapter.java modified: mediacontroller/src/main/java/com/example/android/mediacontroller/MediaBrowseTreeSnapshot.kt
1 parent d5e4693 commit 2c6fac8

File tree

4 files changed

+84
-81
lines changed

4 files changed

+84
-81
lines changed

mediacontroller/src/main/AndroidManifest.xml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@
1717
xmlns:tools="http://schemas.android.com/tools"
1818
package="com.example.android.mediacontroller">
1919

20-
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
21-
2220
<uses-feature
2321
android:name="android.hardware.touchscreen"
2422
android:required="false" />

mediacontroller/src/main/java/com/example/android/mediacontroller/MediaAppControllerActivity.java

Lines changed: 47 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@
7575

7676
import com.google.android.material.tabs.TabLayout;
7777

78+
import java.io.FileNotFoundException;
79+
import java.io.OutputStream;
7880
import java.util.ArrayList;
7981
import java.util.Collections;
8082
import java.util.Comparator;
@@ -113,14 +115,15 @@ public class MediaAppControllerActivity extends AppCompatActivity {
113115
// Key name for Intent extras.
114116
private static final String APP_DETAILS_EXTRA =
115117
"com.example.android.mediacontroller.APP_DETAILS_EXTRA";
118+
private static final String DEFAULT_BROWSE_TREE_FILE_NAME = "_BrowseTreeContent.txt";
116119

117120
// Index values for spinner.
118121
private static final int SEARCH_INDEX = 0;
119122
private static final int MEDIA_ID_INDEX = 1;
120123
private static final int URI_INDEX = 2;
121124

122125
// Used for user storage permission request
123-
private static final int STORAGE_PERMISSION_REQUEST = 1;
126+
private static final int CREATE_DOCUMENT_REQUEST_FOR_SNAPSHOT = 1;
124127

125128
private MediaAppDetails mMediaAppDetails;
126129
private MediaControllerCompat mController;
@@ -148,6 +151,8 @@ public class MediaAppControllerActivity extends AppCompatActivity {
148151

149152
private ViewGroup mRatingViewGroup;
150153

154+
private MediaBrowseTreeSnapshot mMediaBrowseTreeSnapshot;
155+
151156
private final SparseArray<ImageButton> mActionButtonMap = new SparseArray<>();
152157

153158
/**
@@ -172,8 +177,6 @@ protected void onCreate(Bundle savedInstanceState) {
172177
setSupportActionBar(toolbar);
173178
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
174179
toolbar.setNavigationOnClickListener(v -> finish());
175-
String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
176-
ActivityCompat.requestPermissions(MediaAppControllerActivity.this, permissions, STORAGE_PERMISSION_REQUEST);
177180

178181
mViewPager = findViewById(R.id.view_pager);
179182
mInputTypeView = findViewById(R.id.input_type);
@@ -279,28 +282,25 @@ public Object instantiateItem(@NonNull ViewGroup container, int position) {
279282
});
280283
}
281284

282-
283285
@Override
284-
public void onRequestPermissionsResult(int requestCode,
285-
@NonNull String[] permissions,
286-
@NonNull int[] grantResults) {
287-
super.onRequestPermissionsResult(requestCode,
288-
permissions,
289-
grantResults);
290-
291-
if (requestCode == STORAGE_PERMISSION_REQUEST) {
292-
if (grantResults.length > 0
293-
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
294-
Toast.makeText(getApplicationContext(),
295-
"Storage Permission Granted, can save browse tree.",
296-
Toast.LENGTH_SHORT)
297-
.show();
286+
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
287+
super.onActivityResult(requestCode, resultCode, data);
288+
if (requestCode == CREATE_DOCUMENT_REQUEST_FOR_SNAPSHOT) {
289+
if (resultCode == RESULT_OK && mMediaBrowseTreeSnapshot != null) {
290+
Uri uri = data.getData();
291+
OutputStream outputStream = null;
292+
try {
293+
outputStream = getContentResolver().openOutputStream(uri);
294+
} catch (FileNotFoundException e) {
295+
e.printStackTrace();
296+
}
297+
mMediaBrowseTreeSnapshot.takeBrowserSnapshot(outputStream);
298+
Toast.makeText(this, "Output file location: " + uri.getPath(), Toast.LENGTH_SHORT).show();
298299
} else {
299-
Toast.makeText(getApplicationContext(),
300-
"Storage Permission Denied, can not save browse tree to file.",
301-
Toast.LENGTH_SHORT)
302-
.show();
300+
Toast.makeText(this, "File could not be saved.", Toast.LENGTH_SHORT).show();
303301
}
302+
303+
304304
}
305305
}
306306

@@ -1136,7 +1136,7 @@ private class BrowseMediaItemsAdapter extends
11361136

11371137
private List<MediaBrowserCompat.MediaItem> mItems;
11381138
private final Stack<String> mNodes = new Stack<>();
1139-
private MediaBrowseTreeSnapshot mMediaBrowseTreeSnapshot;
1139+
11401140

11411141
MediaBrowserCompat.SubscriptionCallback callback =
11421142
new MediaBrowserCompat.SubscriptionCallback() {
@@ -1263,27 +1263,35 @@ void init(View topButtonView, View upButtonView, View saveButtonView) {
12631263
}
12641264
if (saveButtonView != null) {
12651265
saveButtonView.setOnClickListener(v -> {
1266-
if(mMediaBrowseTreeSnapshot != null) {
1267-
mMediaBrowseTreeSnapshot.takeBrowserSnapshot();
1268-
}
1269-
else if(mBrowser != null) {
1270-
mMediaBrowseTreeSnapshot = new MediaBrowseTreeSnapshot(mBrowser, getApplicationContext());
1271-
mMediaBrowseTreeSnapshot.takeBrowserSnapshot();
1272-
}
1273-
else{
1274-
Log.e(TAG, "Media browser is null");
1275-
runOnUiThread(new Runnable() {
1276-
@Override
1277-
public void run() {
1278-
Toast.makeText(getApplicationContext(),"No media browser to snapshot", Toast.LENGTH_SHORT).show();
1279-
}
1280-
});
1281-
}
1266+
takeMediaBrowseTreeSnapshot();
12821267
});
12831268
}
12841269

12851270
}
12861271

1272+
private void takeMediaBrowseTreeSnapshot(){
1273+
if(mBrowser != null) {
1274+
if(mMediaBrowseTreeSnapshot == null) {
1275+
mMediaBrowseTreeSnapshot = new MediaBrowseTreeSnapshot(MediaAppControllerActivity.this, mBrowser);
1276+
}
1277+
Intent saveTextFileIntent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
1278+
saveTextFileIntent.addCategory(Intent.CATEGORY_OPENABLE);
1279+
saveTextFileIntent.setType("text/plain");
1280+
saveTextFileIntent.putExtra(
1281+
Intent.EXTRA_TITLE, DEFAULT_BROWSE_TREE_FILE_NAME);
1282+
MediaAppControllerActivity.this.startActivityForResult(saveTextFileIntent, CREATE_DOCUMENT_REQUEST_FOR_SNAPSHOT);
1283+
1284+
}else{
1285+
Log.e(TAG, "Media browser is null");
1286+
runOnUiThread(new Runnable() {
1287+
@Override
1288+
public void run() {
1289+
Toast.makeText(getApplicationContext(),"No media browser to snapshot", Toast.LENGTH_SHORT).show();
1290+
}
1291+
});
1292+
}
1293+
}
1294+
12871295
protected void subscribe() {
12881296
if (mNodes.size() > 0) {
12891297
mBrowser.subscribe(mNodes.peek(), callback);

mediacontroller/src/main/java/com/example/android/mediacontroller/MediaAppListAdapter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ public void bindTo(RecyclerView.ViewHolder vh) {
124124
holder.appIconView.getContext().getString(R.string.app_icon_desc,
125125
appDetails.appName));
126126
holder.appNameView.setText(appDetails.appName);
127-
//holder.appPackageView.setText(appDetails.packageName);
127+
holder.appPackageView.setText(appDetails.packageName);
128128

129129
holder.controlButton.setOnClickListener(view ->
130130
appSelectedListener.onMediaAppClicked(appDetails, false));

mediacontroller/src/main/java/com/example/android/mediacontroller/MediaBrowseTreeSnapshot.kt

Lines changed: 36 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,27 @@
11
package com.example.android.mediacontroller
22

33
import android.content.Context
4-
import android.os.Environment
54
import android.os.Handler
65
import android.os.Looper
76
import android.support.v4.media.MediaBrowserCompat
87
import android.support.v4.media.MediaBrowserCompat.SubscriptionCallback
98
import android.util.Log
109
import android.widget.Toast
11-
import java.io.File
12-
import java.io.FileOutputStream
13-
import java.io.IOException
10+
import java.io.OutputStream
1411
import java.io.PrintWriter
1512
import java.util.concurrent.ExecutorService
1613
import java.util.concurrent.Executors
1714
import java.util.concurrent.Semaphore
1815

19-
class MediaBrowseTreeSnapshot(private val mBrowser: MediaBrowserCompat, private val mContext: Context) {
16+
17+
class MediaBrowseTreeSnapshot(private val context: Context, private val browser: MediaBrowserCompat) {
2018
private val TAG = "MediaBrowseTreeSnapshot"
2119

22-
fun takeBrowserSnapshot() {
20+
/**
21+
* Loads the browsers top level children and runs a DFS on them printing out
22+
* each media item's contentes as it is visited.
23+
*/
24+
fun takeBrowserSnapshot(outputStream: OutputStream) {
2325
val loaded = Semaphore(1)
2426
val executorService = Executors.newFixedThreadPool(4)
2527
val mItems: MutableList<MediaBrowserCompat.MediaItem> = ArrayList()
@@ -29,7 +31,7 @@ class MediaBrowseTreeSnapshot(private val mBrowser: MediaBrowserCompat, private
2931
} catch (e: InterruptedException) {
3032
e.printStackTrace()
3133
}
32-
mBrowser.subscribe(mBrowser.root, object : SubscriptionCallback() {
34+
browser.subscribe(browser.root, object : SubscriptionCallback() {
3335
override fun onChildrenLoaded(parentId: String,
3436
children: List<MediaBrowserCompat.MediaItem>) {
3537
// Notify the main thread that all of the children have loaded
@@ -49,42 +51,23 @@ class MediaBrowseTreeSnapshot(private val mBrowser: MediaBrowserCompat, private
4951
}
5052

5153
if (mItems.size > 0) {
52-
initDFSOnBrowseTree(mItems, executorService)
54+
runDFSOnBrowseTree(mItems, executorService, outputStream)
5355
} else {
5456
notifyUser("No media items found, could not save tree.")
5557
}
5658
}
5759
}
5860

59-
private fun initDFSOnBrowseTree(mItems: MutableList<MediaBrowserCompat.MediaItem>, executorService: ExecutorService) {
60-
val root = Environment.getExternalStorageDirectory()
61-
val dirsPath = root.absolutePath + "/Temp/"
62-
val dirs = File(dirsPath)
63-
dirs.mkdirs()
64-
val file = File(dirs.absolutePath,
65-
"_BrowseTreeContent.txt")
66-
if (file.exists()) {
67-
file.delete()
68-
}
69-
try {
70-
val f = FileOutputStream(file)
71-
val pw = PrintWriter(f)
72-
runDFSOnBrowseTree(mItems, executorService, pw)
73-
pw.flush()
74-
pw.close()
75-
f.close()
76-
} catch (e: IOException) {
77-
e.printStackTrace()
78-
}
79-
notifyUser("MediaItems saved to " +
80-
file.absolutePath)
81-
}
82-
83-
private fun runDFSOnBrowseTree(mItems: MutableList<MediaBrowserCompat.MediaItem>, executorService: ExecutorService, printWriter: PrintWriter) {
61+
/**
62+
* Kicks off the browse tree depth first search by visiting all of the top level media
63+
* item nodes.
64+
*/
65+
private fun runDFSOnBrowseTree(mediaItems: MutableList<MediaBrowserCompat.MediaItem>, executorService: ExecutorService, outputStream: OutputStream) {
66+
val printWriter = PrintWriter(outputStream)
8467
printWriter.println("Root:")
8568
val writeCompleted = Semaphore(1)
8669
executorService.execute {
87-
for (item in mItems) {
70+
for (item in mediaItems) {
8871
try {
8972
writeCompleted.acquire()
9073
} catch (e: InterruptedException) {
@@ -94,9 +77,16 @@ class MediaBrowseTreeSnapshot(private val mBrowser: MediaBrowserCompat, private
9477
executorService)
9578
writeCompleted.release()
9679
}
80+
printWriter.flush()
81+
printWriter.close()
82+
outputStream.close()
83+
notifyUser("MediaItems saved to specified location.")
9784
}
9885
}
9986

87+
/**
88+
* Visits a media item node by printing out its contents and then visiting all of its children.
89+
*/
10090
private fun visitMediaItemNode(mediaItem: MediaBrowserCompat.MediaItem?, printWriter: PrintWriter, depth: Int,
10191
executorService: ExecutorService) {
10292
if (mediaItem != null) {
@@ -111,14 +101,14 @@ class MediaBrowseTreeSnapshot(private val mBrowser: MediaBrowserCompat, private
111101
} catch (e: InterruptedException) {
112102
e.printStackTrace()
113103
}
114-
val mChildren: MutableList<MediaBrowserCompat.MediaItem> = ArrayList()
104+
val mediaChildren: MutableList<MediaBrowserCompat.MediaItem> = ArrayList()
115105
executorService.execute {
116-
mBrowser.subscribe(mid,
106+
browser.subscribe(mid,
117107
object : SubscriptionCallback() {
118108
override fun onChildrenLoaded(parentId: String,
119109
children: List<MediaBrowserCompat.MediaItem>) {
120110
// Notify the main thread that all of the children have loaded
121-
mChildren.addAll(children)
111+
mediaChildren.addAll(children)
122112
loaded.release()
123113
super.onChildrenLoaded(parentId, children)
124114
}
@@ -133,14 +123,17 @@ class MediaBrowseTreeSnapshot(private val mBrowser: MediaBrowserCompat, private
133123
}
134124

135125
// Run visit on all of the nodes children
136-
for (mediaItemChild in mChildren) {
126+
for (mediaItemChild in mediaChildren) {
137127
visitMediaItemNode(mediaItemChild, printWriter, depth + 1,
138128
executorService)
139129
}
140130
}
141131
}
142132
}
143133

134+
/**
135+
* Prints the contents of a media item using a print writer.
136+
*/
144137
private fun printMediaItemDescription(printWriter: PrintWriter, mediaItem: MediaBrowserCompat.MediaItem, depth: Int) {
145138
val descriptionCompat = mediaItem.description
146139
// Tab the media item to the respective depth
@@ -154,13 +147,17 @@ class MediaBrowseTreeSnapshot(private val mBrowser: MediaBrowserCompat, private
154147
val infoStr = String.format(
155148
"%sTitle:%s,Subtitle:%s,MediaId:%s,URI:%s,Description:%s",
156149
tabStr, titleStr, subTitleStr, mIDStr, uriStr, desStr)
150+
Log.i(TAG, "Writing media Item");
157151
printWriter.println(infoStr)
158152
}
159153

154+
/**
155+
* Display formatted toast to user.
156+
*/
160157
private fun notifyUser(textToNotify: String) {
161158
Handler(Looper.getMainLooper()).post {
162159
val toast = Toast.makeText(
163-
mContext,
160+
context,
164161
textToNotify,
165162
Toast.LENGTH_LONG)
166163
toast.setMargin(50f, 50f)

0 commit comments

Comments
 (0)