Java tutorial
/* * Copyright 2004 - Present Facebook, Inc. * * 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.facebook.samples.musicdashboard; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import org.json.JSONException; import org.json.JSONObject; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.res.Resources; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.preference.PreferenceManager; import android.support.v4.app.Fragment; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.GridView; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import com.facebook.samples.musicdashboard.SongFetcherThread.SongImageDownloadListener; public class MusicGalleryFragment extends Fragment { public static final String TAG = "MusicGalleryFragment"; private static final String JSON_NAME = "name"; private static final String JSON_PICTURE = "picture"; private static final String JSON_DATA = "data"; private static final String JSON_URL = "url"; private ArrayList<Song> songs; private GridView gridView; private ArrayAdapter<Song> adapter; private ImageView profileImageView; private TextView userNameTextView; private SongFetcherThread downloadThread; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); super.setRetainInstance(true); // We have a menu setHasOptionsMenu(true); // Get the music info fetchMusic(); } void fetchMusic() { // Kill any current downloads if (downloadThread != null) { downloadThread.quit(); downloadThread = null; } songs = new ArrayList<Song>(); Context c = getActivity().getApplicationContext(); final MusicFetcher fetcher = new MusicFetcher(c); // The handler for song image/info download Handler handler = new Handler(); // The listener for song image/info download SongImageDownloadListener listener = new SongImageDownloadListener() { public void onSongImageUpdated() { if (null == adapter) return; // Notify the GridView that data has changed adapter.notifyDataSetChanged(); } }; // The thread to download song image info downloadThread = new SongFetcherThread("SongImage", c, handler, listener); downloadThread.start(); final Handler mHandler = new Handler(); // Facebook - Graph API request for the music.listens info MusicDashboardApplication.mAsyncRunner.request("me/music.listens", new BaseRequestListener() { @Override public void onComplete(final String response, Object state) { // Pass the JSON response and get the music info songs = fetcher.fetchSongs(response); mHandler.post(new Runnable() { @Override public void run() { // Update the GridView with initial info that does // not include song image and other details that // are about to be downloaded setAdapter(new SongAdapter(songs)); // Clear the cache in preparation for image downloads downloadThread.clearSongImages(); // For each song that was parsed out in the "fetchSongs" // call, get the song info and image for (Song song : songs) { downloadThread.downloadSongInfo(song); downloadThread.downloadSongImage(song); } } }); } }); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstance) { View v = inflater.inflate(R.layout.fragment_music_gallery, parent, false); // Setup logout button ImageButton logoutButton = (ImageButton) v.findViewById(R.id.button_logout); // Facebook - Logout call logoutButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { MusicDashboardApplication.mAsyncRunner.logout(getActivity(), new BaseRequestListener() { @Override public void onComplete(String response, Object state) { Log.i(TAG, "Logged out successfully"); SharedPreferences mPrefs = PreferenceManager .getDefaultSharedPreferences(getActivity().getApplicationContext()); mPrefs.edit().putString("access_token", null).commit(); mPrefs.edit().putLong("access_expires", -1).commit(); ; // Go to logged in activity Intent i = new Intent(getActivity(), LoginActivity.class); startActivity(i); } }); } }); // Get personalization info - profile picture and name profileImageView = (ImageView) v.findViewById(R.id.profile_picture); userNameTextView = (TextView) v.findViewById(R.id.user_name); // Then make the request to get the actual personalization info requestUserData(); // Get the music info gridView = (GridView) v.findViewById(R.id.music_gallery_gridView); setAdapter(new SongAdapter(songs)); // For now, clicking on a song in the GridView displays the song's title. gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { SongAdapter adapter = (SongAdapter) parent.getAdapter(); Song song = adapter.getItem(position); Toast.makeText(getActivity(), song.toString(), Toast.LENGTH_SHORT).show(); // Play the song playSong(song.getAudioUrl()); } }); return v; } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); inflater.inflate(R.menu.activity_music_gallery, menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.menu_refresh: // User selects refresh, update song content fetchMusic(); return true; default: return super.onOptionsItemSelected(item); } } void setAdapter(ArrayAdapter<Song> adapter) { this.adapter = adapter; if (gridView != null) { gridView.setAdapter(adapter); } } /* * Used to play a song */ private void playSong(String songUrl) { Uri uri = Uri.parse(songUrl); Intent launchBrowser = new Intent(Intent.ACTION_VIEW, uri); startActivity(launchBrowser); } /* * Used by the GridView adapter to set the column width */ int getColumnWidth() { if (null == gridView) return 0; Resources r = getActivity().getResources(); int horizontalSpacing = r.getDimensionPixelSize(R.dimen.gridview_horizontal_spacing); int numColumns = r.getInteger(R.integer.gridview_num_columns); int spacing = horizontalSpacing * (numColumns - 1); int padding = gridView.getListPaddingLeft() + gridView.getListPaddingRight(); return (gridView.getWidth() - padding - spacing) / numColumns; } /* * Used by the GridView adapter to set the column height for a row */ int getColumnHeight(Drawable drawable) { float aspectRatio = (float) drawable.getIntrinsicHeight() / drawable.getIntrinsicWidth(); return (int) (getColumnWidth() * aspectRatio); } /* * The GridView adapter */ private class SongAdapter extends ArrayAdapter<Song> { public SongAdapter(ArrayList<Song> songs) { super(getActivity(), 0, songs); } @Override public View getView(int position, View convertView, ViewGroup parent) { View view = convertView; if (null == view) { view = getActivity().getLayoutInflater().inflate(R.layout.gallery_song, parent, false); } ImageView songImageView = (ImageView) view.findViewById(R.id.gallery_song_photoImageView); Song song = getItem(position); Drawable drawable = song.getDrawable(getActivity()); songImageView.setImageDrawable(drawable); int height = 0; int numColumns = getActivity().getResources().getInteger(R.integer.gridview_num_columns); int firstCell = position = position % numColumns; int nextRow = firstCell + numColumns; // find the highest height on our row for (int cell = firstCell; cell < nextRow && cell < getCount(); cell++) { Song cellSong = getItem(cell); Drawable cellDrawable = cellSong.getDrawable(getActivity()); int cellHeight = getColumnHeight(cellDrawable); if (cellHeight > height) { height = cellHeight; } } songImageView.getLayoutParams().height = height; // notify songImageView that its layout params have changed songImageView.requestLayout(); return view; } } @Override public void onDestroy() { super.onDestroy(); // Stop any current downloads downloadThread.quit(); } @Override public void onResume() { super.onResume(); if (MusicDashboardApplication.mFacebook.isSessionValid()) { // Extend the access token if needed MusicDashboardApplication.mFacebook.extendAccessTokenIfNeeded(getActivity(), null); } else { // Go to logged in activity Intent i = new Intent(getActivity(), LoginActivity.class); startActivity(i); } } /* * Make a Graph API call to get personalization info */ void requestUserData() { Bundle params = new Bundle(); params.putString("fields", "name,picture"); final Handler handler = new Handler(); // Facebook - Graph API call to get personalizatoin info MusicDashboardApplication.mAsyncRunner.request("me", params, new BaseRequestListener() { @Override public void onComplete(String response, Object state) { JSONObject jsonObject; try { Log.i(TAG, "User info response: " + response); jsonObject = new JSONObject(response); final String userName = jsonObject.getString(JSON_NAME); String pictureUrl = null; // An upcoming change in how picture data is returned means // we have to check two ways for picture URL info. try { pictureUrl = jsonObject.getJSONObject(JSON_PICTURE).getJSONObject(JSON_DATA) .getString(JSON_URL); } catch (JSONException e) { // ignored } if (pictureUrl == null) { pictureUrl = jsonObject.getString(JSON_PICTURE); } final Drawable drawable = fetchImageFromUrl(getActivity(), pictureUrl, "profilepic.jpg"); handler.post(new Runnable() { @Override public void run() { // Set the personalization UI info on the main thread userNameTextView.setText(userName); profileImageView.setImageDrawable(drawable); } }); } catch (JSONException e) { Log.i(TAG, "Could not get user info"); } } }); } /* * Method that fetches an URL and returns a Drawable */ private Drawable fetchImageFromUrl(Context ctx, String url, String saveFilename) { try { InputStream is = (InputStream) this.fetch(url); Drawable d = Drawable.createFromStream(is, "src"); return d; } catch (MalformedURLException e) { Log.i(TAG, "Could not get fetch image."); return null; } catch (IOException e) { Log.i(TAG, "Could not get fetch image."); return null; } } private Object fetch(String address) throws MalformedURLException, IOException { URL url = new URL(address); Object content = url.getContent(); return content; } }