Skip to content

Add a save button to the media controller tester app, #27

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

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions mediacontroller/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
xmlns:tools="http://schemas.android.com/tools"
package="com.example.android.mediacontroller">

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This actually doesn't work when targeting Android Q+ because of scoped storage changes. It could work on Android Q, but I think it would be better to use the Storage Access Framework for this, which wouldn't require any permissions and would let the user pick where to put the file (I explained more below, but just adding this here so I don't miss this permission being removed if you go that route.

<uses-feature
android:name="android.hardware.touchscreen"
android:required="false" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import android.os.RemoteException;
import android.support.v4.media.MediaBrowserCompat;
import android.support.v4.media.MediaBrowserCompat.MediaItem;
import android.support.v4.media.MediaDescriptionCompat;
import android.support.v4.media.MediaMetadataCompat;
import android.support.v4.media.RatingCompat;
import android.support.v4.media.session.MediaControllerCompat;
Expand Down Expand Up @@ -73,6 +74,11 @@

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

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
Expand Down Expand Up @@ -248,20 +254,20 @@ public Object instantiateItem(@NonNull ViewGroup container, int position) {
browseTreeList.setHasFixedSize(true);
browseTreeList.setAdapter(mBrowseMediaItemsAdapter);
mBrowseMediaItemsAdapter.init(findViewById(R.id.media_browse_tree_top),
findViewById(R.id.media_browse_tree_up));
findViewById(R.id.media_browse_tree_up), findViewById(R.id.media_browse_tree_save));

final RecyclerView browseTreeListExtraSuggested = findViewById(R.id.media_items_list_extra_suggested);
browseTreeListExtraSuggested.setLayoutManager(new LinearLayoutManager(this));
browseTreeListExtraSuggested.setHasFixedSize(true);
browseTreeListExtraSuggested.setAdapter(mBrowseMediaItemsExtraSuggestedAdapter);
mBrowseMediaItemsExtraSuggestedAdapter.init(findViewById(R.id.media_browse_tree_top_extra_suggested),
findViewById(R.id.media_browse_tree_up_extra_suggested));
findViewById(R.id.media_browse_tree_up_extra_suggested), findViewById(R.id.media_browse_tree_save_extra_suggested));

final RecyclerView searchItemsList = findViewById(R.id.search_items_list);
searchItemsList.setLayoutManager(new LinearLayoutManager(this));
searchItemsList.setHasFixedSize(true);
searchItemsList.setAdapter(mSearchMediaItemsAdapter);
mSearchMediaItemsAdapter.init(null, null);
mSearchMediaItemsAdapter.init(null, null, null);

findViewById(R.id.search_button).setOnClickListener(v -> {
CharSequence queryText = ((TextView) findViewById(R.id.search_query)).getText();
Expand Down Expand Up @@ -1206,7 +1212,7 @@ void updateItems(List<MediaBrowserCompat.MediaItem> items) {
* Assigns click handlers to the buttons if provided for moving to the top of the tree or
* for moving up one level in the tree.
*/
void init(View topButtonView, View upButtonView) {
void init(View topButtonView, View upButtonView, View saveButtonView) {
if (topButtonView != null) {
topButtonView.setOnClickListener(v -> {
if (mNodes.size() > 1) {
Expand All @@ -1228,6 +1234,75 @@ void init(View topButtonView, View upButtonView) {
}
});
}

if (saveButtonView != null) {
saveButtonView.setOnClickListener(v -> {
if (mNodes.isEmpty()) {
Toast toast =
Toast.makeText(
getApplicationContext(), "List Empty, nothing saved! ", Toast.LENGTH_LONG);
toast.setMargin(50, 50);
toast.show();
return;
}
File root = android.os.Environment.getExternalStorageDirectory();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This bit of code won't work on Android 11 and above because of changes for scoped storage.

If possible, I think it would be best to change this to use the Storage Access Framework with the intent action ACTION_CREATE_DOCUMENT -- this would not only allow the code to work on Android 11 and beyond, but would allow the user to pick the name & location to put the file.

The intent returns a URI in the form of content://... that can be used with ContentResolver to open an output stream, which seems like it should work with the rest of the code you have below.

File dir = new File(root.getAbsolutePath() + "/Temp");
dir.mkdirs();
File file = new File(dir, "_BrowseTreeContent.txt");
if (file.exists()) {
file.delete();
}
try {
FileOutputStream f = new FileOutputStream(file);
PrintWriter pw = new PrintWriter(f);
// We print the file path at the beginning of the file so that we can use it
// to pull the file from android to local computer in case user have forgotten.
pw.println(file.toString());

for (MediaBrowserCompat.MediaItem item : mItems) {
MediaDescriptionCompat descriptionCompat = item.getDescription();
if (descriptionCompat != null) {
String infoStr =
"Title:" + descriptionCompat.getTitle() != null
? descriptionCompat.getTitle().toString()
: "NAN";
infoStr +=
",Subtitle:" + descriptionCompat.getSubtitle() != null
? descriptionCompat.getSubtitle().toString()
: "NAN";
infoStr +=
",MediaId:" + descriptionCompat.getMediaId() != null
? descriptionCompat.getMediaId().toString()
: "NAN";
infoStr +=
",Uri:" + descriptionCompat.getMediaUri() != null
? descriptionCompat.getMediaUri().toString()
: "NAN";
infoStr +=
",Description:" + descriptionCompat.getDescription() != null
? descriptionCompat.getDescription().toString()
: "NAN";
pw.println(infoStr);
}
}

pw.flush();
pw.close();
f.close();
Toast toast =
Toast.makeText(
getApplicationContext(),
"MediaItems saved to " + file.getAbsolutePath(),
Toast.LENGTH_LONG);
toast.setMargin(50, 50);
toast.show();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
});
}
}

protected void subscribe() {
Expand Down
6 changes: 6 additions & 0 deletions mediacontroller/src/main/res/layout/media_browse_tree.xml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@
android:layout_height="wrap_content"
android:text="@string/media_browse_tree_up" />

<Button
android:id="@+id/media_browse_tree_save"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/media_browse_tree_save" />

</LinearLayout>

<TextView
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@
android:layout_height="wrap_content"
android:text="@string/media_browse_tree_up" />

<Button
android:id="@+id/media_browse_tree_save_extra_suggested"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/media_browse_tree_up" />

</LinearLayout>

<TextView
Expand Down
1 change: 1 addition & 0 deletions mediacontroller/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@

<string name="media_browse_tree_top">Top</string>
<string name="media_browse_tree_up">Up</string>
<string name="media_browse_tree_save">Save to file</string>
<string name="media_browse_tree_header">App-provided MediaItems</string>
<string name="media_browse_tree_extra_suggested_header">App-provided MediaItems Extra Suggested Flag</string>
<string name="media_no_browser">No Browser</string>
Expand Down