/* * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.music; import android.app.Activity; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.content.res.Resources; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.PixelFormat; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.media.MediaMetadata; import android.media.session.MediaController; import android.net.Uri; import android.provider.MediaStore; import android.view.View; import android.widget.TabWidget; import android.widget.TextView; import com.android.music.utils.LogHelper; import com.android.music.utils.MusicProvider; import java.util.Formatter; import java.util.Iterator; import java.util.Locale; /* Static methods useful for activities */ public class MusicUtils { private static final String TAG = LogHelper.makeLogTag(MusicUtils.class); public static final String TAG_MEDIA_ID = "__MEDIA_ID"; public static final String TAG_PARENT_ITEM = "__PARENT_ITEM"; public static final String TAG_WITH_TABS = "__WITH_TABS"; // A really simple BitmapDrawable-like class, that doesn't do // scaling, dithering or filtering. private static class FastBitmapDrawable extends Drawable { private Bitmap mBitmap; public FastBitmapDrawable(Bitmap b) { mBitmap = b; } @Override public void draw(Canvas canvas) { canvas.drawBitmap(mBitmap, 0, 0, null); } @Override public int getOpacity() { return PixelFormat.OPAQUE; } @Override public void setAlpha(int alpha) {} @Override public void setColorFilter(ColorFilter cf) {} } public static Bitmap resizeBitmap(Bitmap bitmap, Bitmap ref) { int w = ref.getWidth(); int h = ref.getHeight(); return Bitmap.createScaledBitmap(bitmap, w, h, false); } public static Drawable getDrawableBitmap(Bitmap bitmap, BitmapDrawable defaultArtwork) { final Bitmap icon = defaultArtwork.getBitmap(); int w = icon.getWidth(); int h = icon.getHeight(); bitmap = Bitmap.createScaledBitmap(bitmap, w, h, false); return new FastBitmapDrawable(bitmap); } public static String makeAlbumsLabel( Context context, int numalbums, int numsongs, boolean isUnknown) { // There are two formats for the albums/songs information: // "N Song(s)" - used for unknown artist/album // "N Album(s)" - used for known albums StringBuilder songs_albums = new StringBuilder(); Resources r = context.getResources(); if (isUnknown) { if (numsongs == 1) { songs_albums.append(context.getString(R.string.onesong)); } else { String f = r.getQuantityText(R.plurals.Nsongs, numsongs).toString(); sFormatBuilder.setLength(0); sFormatter.format(f, Integer.valueOf(numsongs)); songs_albums.append(sFormatBuilder); } } else { String f = r.getQuantityText(R.plurals.Nalbums, numalbums).toString(); sFormatBuilder.setLength(0); sFormatter.format(f, Integer.valueOf(numalbums)); songs_albums.append(sFormatBuilder); songs_albums.append(context.getString(R.string.albumsongseparator)); } return songs_albums.toString(); } /** * This is now only used for the query screen */ public static String makeAlbumsSongsLabel( Context context, int numalbums, int numsongs, boolean isUnknown) { // There are several formats for the albums/songs information: // "1 Song" - used if there is only 1 song // "N Songs" - used for the "unknown artist" item // "1 Album"/"N Songs" // "N Album"/"M Songs" // Depending on locale, these may need to be further subdivided StringBuilder songs_albums = new StringBuilder(); if (numsongs == 1) { songs_albums.append(context.getString(R.string.onesong)); } else { Resources r = context.getResources(); if (!isUnknown) { String f = r.getQuantityText(R.plurals.Nalbums, numalbums).toString(); sFormatBuilder.setLength(0); sFormatter.format(f, Integer.valueOf(numalbums)); songs_albums.append(sFormatBuilder); songs_albums.append(context.getString(R.string.albumsongseparator)); } String f = r.getQuantityText(R.plurals.Nsongs, numsongs).toString(); sFormatBuilder.setLength(0); sFormatter.format(f, Integer.valueOf(numsongs)); songs_albums.append(sFormatBuilder); } return songs_albums.toString(); } /* Try to use String.format() as little as possible, because it creates a * new Formatter every time you call it, which is very inefficient. * Reusing an existing Formatter more than tripled the speed of * makeTimeString(). * This Formatter/StringBuilder are also used by makeAlbumSongsLabel() */ private static StringBuilder sFormatBuilder = new StringBuilder(); private static Formatter sFormatter = new Formatter(sFormatBuilder, Locale.getDefault()); private static final Object[] sTimeArgs = new Object[5]; public static String makeTimeString(Context context, long secs) { String durationformat = context.getString( secs < 3600 ? R.string.durationformatshort : R.string.durationformatlong); /* Provide multiple arguments so the format can be changed easily * by modifying the xml. */ sFormatBuilder.setLength(0); final Object[] timeArgs = sTimeArgs; timeArgs[0] = secs / 3600; timeArgs[1] = secs / 60; timeArgs[2] = (secs / 60) % 60; timeArgs[3] = secs; timeArgs[4] = secs % 60; return sFormatter.format(durationformat, timeArgs).toString(); } static int getIntPref(Context context, String name, int def) { SharedPreferences prefs = context.getSharedPreferences(context.getPackageName(), Context.MODE_PRIVATE); return prefs.getInt(name, def); } static void setIntPref(Context context, String name, int value) { SharedPreferences prefs = context.getSharedPreferences(context.getPackageName(), Context.MODE_PRIVATE); Editor ed = prefs.edit(); ed.putInt(name, value); SharedPreferencesCompat.apply(ed); } static int sActiveTabIndex = -1; static boolean updateButtonBar(Activity a, int highlight) { final TabWidget ll = (TabWidget) a.findViewById(R.id.buttonbar); boolean withtabs = false; Intent intent = a.getIntent(); if (intent != null) { withtabs = intent.getBooleanExtra(MusicUtils.TAG_WITH_TABS, false); } if (highlight == 0 || !withtabs) { ll.setVisibility(View.GONE); return withtabs; } else if (withtabs) { ll.setVisibility(View.VISIBLE); } for (int i = ll.getChildCount() - 1; i >= 0; i--) { View v = ll.getChildAt(i); boolean isActive = (v.getId() == highlight); if (isActive) { ll.setCurrentTab(i); sActiveTabIndex = i; } v.setTag(i); v.setOnFocusChangeListener(new View.OnFocusChangeListener() { public void onFocusChange(View v, boolean hasFocus) { if (hasFocus) { for (int i = 0; i < ll.getTabCount(); i++) { if (ll.getChildTabViewAt(i) == v) { ll.setCurrentTab(i); processTabClick((Activity) ll.getContext(), v, ll.getChildAt(sActiveTabIndex).getId()); break; } } } } }); v.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { processTabClick( (Activity) ll.getContext(), v, ll.getChildAt(sActiveTabIndex).getId()); } }); } return withtabs; } static void processTabClick(Activity a, View v, int current) { int id = v.getId(); if (id == current) { return; } final TabWidget ll = (TabWidget) a.findViewById(R.id.buttonbar); activateTab(a, id); if (id != R.id.nowplayingtab) { ll.setCurrentTab((Integer) v.getTag()); setIntPref(a, "activetab", id); } } static void activateTab(Activity a, int id) { Intent intent = new Intent(Intent.ACTION_PICK); switch (id) { case R.id.artisttab: intent.setDataAndType(Uri.EMPTY, "vnd.android.cursor.dir/artistalbum"); break; case R.id.albumtab: intent.setDataAndType(Uri.EMPTY, "vnd.android.cursor.dir/album"); break; case R.id.songtab: intent.setDataAndType(Uri.EMPTY, "vnd.android.cursor.dir/track"); break; case R.id.playlisttab: intent.setDataAndType(Uri.EMPTY, MediaStore.Audio.Playlists.CONTENT_TYPE); break; case R.id.nowplayingtab: intent = new Intent(a, MediaPlaybackActivity.class); a.startActivity(intent); // fall through and return default: return; } intent.putExtra(MusicUtils.TAG_WITH_TABS, true); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); a.startActivity(intent); a.finish(); a.overridePendingTransition(0, 0); } static void updateNowPlaying(Activity a) { View nowPlayingView = a.findViewById(R.id.nowplaying); if (nowPlayingView == null) { return; } MediaController controller = a.getMediaController(); if (controller != null) { MediaMetadata metadata = controller.getMetadata(); if (metadata != null) { TextView title = (TextView) nowPlayingView.findViewById(R.id.title); TextView artist = (TextView) nowPlayingView.findViewById(R.id.artist); title.setText(metadata.getString(MediaMetadata.METADATA_KEY_TITLE)); String artistName = metadata.getString(MediaMetadata.METADATA_KEY_ARTIST); if (MusicProvider.UNKOWN.equals(artistName)) { artistName = a.getString(R.string.unknown_artist_name); } artist.setText(artistName); nowPlayingView.setVisibility(View.VISIBLE); nowPlayingView.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { Context c = v.getContext(); c.startActivity(new Intent(c, MediaPlaybackActivity.class)); } }); return; } } nowPlayingView.setVisibility(View.GONE); } }