Back to project page Youtubemysongs.
The source code is released under:
Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCT...
If you think the Android project Youtubemysongs listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
package com.aanchal.youtubemysongs; /*ww w . j a v a2 s . c om*/ import com.aanchal.youtubemysongs.Song; import com.aanchal.youtubemysongs.DeveloperKey; import com.aanchal.youtubemysongs.SongLogger; import com.aanchal.youtubemysongs.AppRater; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.net.URL; import java.net.URLConnection; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.List; import java.util.Random; import android.app.Activity; import android.app.ProgressDialog; import android.content.Context; import android.content.Intent; import android.content.pm.ResolveInfo; import android.content.res.Configuration; import android.database.Cursor; import android.graphics.Color; import android.net.ConnectivityManager; import android.os.AsyncTask; import android.os.Bundle; import android.provider.MediaStore; import android.provider.Settings.Secure; import android.text.Editable; import android.text.Spannable; import android.text.SpannableStringBuilder; import android.text.TextWatcher; import android.text.style.ForegroundColorSpan; import android.text.style.RelativeSizeSpan; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.BaseAdapter; import android.widget.EditText; import android.widget.Filter; import android.widget.Filterable; import android.widget.ListView; import android.widget.TextView; import android.widget.AdapterView.OnItemClickListener; import android.widget.Toast; import org.apache.commons.io.IOUtils; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import org.json.JSONArray; import org.json.JSONObject; import com.aanchal.youtubemysongs.R; import com.google.android.youtube.player.YouTubeInitializationResult; import com.google.android.youtube.player.YouTubeStandalonePlayer; import com.google.ads.*; public class MainActivity extends Activity { static final int MAX_QUERY_SONGS = 5; private static final int SONG_CANDIDATES = 1; private static final String YOUTUBE_VIDEO_INFORMATION_URL = "http://www.youtube.com/get_video_info?&video_id="; ListView musiclist; Cursor musiccursor; Song querySong; List<Song> allSongs; List<Song> currentSongs; int count; static int selectedIndex; private ConnectivityManager cm; Activity myself; EditText inputSearch; MusicAdapter adapter; private ProgressDialog progressDialog; SongLogger logger; static String duration; long startTime = -1; static Random randomGenerator = new Random(); static AppRater appRate = new AppRater(); private TextWatcher searchTextWatcher = new TextWatcher() { // @Override public void onTextChanged(CharSequence s, int start, int before, int count) { // ignore } //@Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { // ignore } // @Override public void afterTextChanged(Editable s) { adapter.getFilter().filter(s.toString()); } }; private class LoggerTask extends AsyncTask<Object, Void, Long> { protected Long doInBackground(Object... param) { logger.resetAndSend(MainActivity.this); return (long) 1; } } class Process extends AsyncTask<Object, Void, String> { @Override protected void onPreExecute() { super.onPreExecute(); progressDialog = ProgressDialog.show(MainActivity.this, null, "Automagic search in progress...", true, false); } @Override protected String doInBackground(Object... param) { return getVideoIdForSong(querySong); } private boolean canResolveIntent(Intent intent) { List<ResolveInfo> resolveInfo = getPackageManager().queryIntentActivities(intent, 0); return resolveInfo != null && !resolveInfo.isEmpty(); } private int getDuration() { try { return Integer.parseInt(duration); } catch (Exception e) { return -1; } } @Override protected void onPostExecute(String result) { if (progressDialog != null) progressDialog.dismiss(); super.onPostExecute(result); if (result == null) Toast.makeText(myself, "Sorry! No video found :(", Toast.LENGTH_SHORT).show(); else { Intent intent = YouTubeStandalonePlayer.createVideoIntent( myself , DeveloperKey.DEVELOPER_KEY, result,0, true, false); if (intent == null || !canResolveIntent(intent)) YouTubeInitializationResult.SERVICE_MISSING.getErrorDialog(myself, 2).show(); else { startTime = System.currentTimeMillis(); logger.videoStarted(result, querySong, getDuration(), selectedIndex); startActivity(intent); } } } } public static String sha256(String base) { try{ MessageDigest digest = MessageDigest.getInstance("SHA-256"); byte[] hash = digest.digest(base.getBytes("UTF-8")); StringBuffer hexString = new StringBuffer(); for (int i = 0; i < hash.length; i++) { String hex = Integer.toHexString(0xff & hash[i]); if(hex.length() == 1) hexString.append('0'); hexString.append(hex); } return hexString.toString(); } catch(Exception ex){ throw new RuntimeException(ex); } } /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { logger =new SongLogger(sha256(Secure.getString(this.getContentResolver(), Secure.ANDROID_ID))); super.onCreate(savedInstanceState); setContentView(R.layout.mainactivity); cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); myself = this; inputSearch = (EditText) findViewById(R.id.inputSearch); inputSearch.addTextChangedListener(searchTextWatcher); init_phone_music_grid(); startTime = -1; } @Override public void onPause() { super.onPause(); //Log.v("Logging", "Pause Called"); if(progressDialog != null) progressDialog.dismiss(); progressDialog = null; } @Override public void onStart() { super.onStart(); //Log.v("Logging", "Start Called"); } @Override public void onResume() { super.onResume(); //Log.v("Logging", "Resume Called"); new LoggerTask().execute(null,null,null); if (startTime != -1) { int elapsedTime = (int) ((System.currentTimeMillis() - startTime)/1000); //Log.v("Logging", "Registering a click with time = " + Integer.toString(elapsedTime)); AppRater.songClicked(this, elapsedTime > 20); } startTime = -1; } @Override public void onStop() { super.onStop(); //Log.v("Logging", "Stop Called"); } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); //Log.v("Logging","Orientation changed"); /*// Checks the orientation of the screen if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) { Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show(); } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){ Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show(); }*/ } @SuppressWarnings("deprecation") private void init_phone_music_grid() { System.gc(); String[] proj = { MediaStore.Audio.Media._ID,MediaStore.Audio.Media.DISPLAY_NAME,MediaStore.Audio.Media.ARTIST, MediaStore.Audio.Media.TITLE,MediaStore.Audio.Media.ALBUM }; try { musiccursor = managedQuery(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,proj, null, null, null); // TODO: Check if musiccursor is null count = musiccursor.getCount(); int titleCol = musiccursor.getColumnIndexOrThrow(MediaStore.Audio.Media.TITLE); int artistCol = musiccursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ARTIST); int albumCol = musiccursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ALBUM); allSongs = new ArrayList<Song>(); currentSongs = new ArrayList<Song>(); musiccursor.moveToFirst(); for(int i = 0; i < count; ++i, musiccursor.moveToNext()) { allSongs.add(new Song(musiccursor.getString(titleCol), musiccursor.getString(albumCol), musiccursor.getString(artistCol))); currentSongs.add(new Song(musiccursor.getString(titleCol), musiccursor.getString(albumCol), musiccursor.getString(artistCol))); } musiclist = (ListView) findViewById(R.id.PhoneMusicList); adapter = new MusicAdapter(getApplicationContext()); musiclist.setAdapter(adapter); musiclist.setOnItemClickListener(musicgridlistener); } catch (NullPointerException e) { Toast.makeText(getApplicationContext(), "No songs found on phone", Toast.LENGTH_LONG).show(); } } // returns query results in JSON form private static JSONArray getResults(String query) { if (query.contains("<unknown>")) return null; try { // TODO: Get short and medium duration only, exclude long videos String url="http://gdata.youtube.com/feeds/api/videos?q="+query+"&max-results="+MAX_QUERY_SONGS+"&v=2&alt=jsonc"; URL jsonURL = new URL(url); URLConnection jc = jsonURL.openConnection(); InputStream is = jc.getInputStream(); String jsonTxt = IOUtils.toString( is ); Log.v("temp","Query:" + query + " Returned: " + jsonTxt); JSONObject jj = new JSONObject(jsonTxt); JSONObject jdata = jj.getJSONObject("data"); int totalItems = Math.min(MAX_QUERY_SONGS,jdata.getInt("totalItems")); JSONArray aitems = null; if (totalItems > 0) aitems = jdata.getJSONArray("items"); return aitems; } catch (Exception e) { return null; } } // given a song, retrieve the youtube id, returns null if no playable video is found private static String getVideoIdForSong(Song song) { JSONArray[] results = new JSONArray[3]; results[0] = getResults(song.getAlbumQueryString()); results[1] = getResults(song.getArtistQueryString()); if (results[0] == null && results[1] == null) results[2] = getResults(song.getTitleQueryString()); else results[2] = getResults(song.getArtistAlbumQueryString()); int[] indexes = new int[3]; indexes[0] = indexes[1] = indexes[2] = 0; String[] candidates = new String[SONG_CANDIDATES]; String[] durations = new String[SONG_CANDIDATES]; int counter = 0; while(true) { Boolean exhausted = true; for(int i = 0; i < 3; ++i) if (results[i] != null && indexes[i] < results[i].length()) { try { JSONObject item0 = results[i].getJSONObject(indexes[i]); indexes[i]++; String ret = item0.getString("id"); HttpClient lClient = new DefaultHttpClient(); HttpGet lGetMethod = new HttpGet(YOUTUBE_VIDEO_INFORMATION_URL + ret); HttpResponse lResp = null; lResp = lClient.execute(lGetMethod); ByteArrayOutputStream lBOS = new ByteArrayOutputStream(); lResp.getEntity().writeTo(lBOS); String lInfoStr = new String(lBOS.toString("UTF-8")); if (!lInfoStr.contains("fail")) { durations[counter] = item0.getString("duration"); candidates[counter] = ret; ++counter; if (counter == SONG_CANDIDATES) { selectedIndex = randomGenerator.nextInt(counter); duration = durations[selectedIndex]; return candidates[selectedIndex]; } } exhausted = false; } catch (Exception e) { // do nothing, continue } } if (exhausted) break; } if (counter > 0) { selectedIndex = randomGenerator.nextInt(counter); duration = durations[selectedIndex]; return candidates[selectedIndex]; } return null; } private OnItemClickListener musicgridlistener = new OnItemClickListener() { public void onItemClick(AdapterView parent, View v, int position,long id) { try { //Upon clicking on a song name this will retrieve MAX_QUERY_SONGS number of songs from youtube and play the top result. System.gc(); querySong = currentSongs.get(position); if (cm.getActiveNetworkInfo() != null && cm.getActiveNetworkInfo().isAvailable() && cm.getActiveNetworkInfo().isConnected()) new Process().execute(null,null,null); else Toast.makeText(getApplicationContext(), "No internet connection", Toast.LENGTH_LONG).show(); } catch (Exception e) {e.printStackTrace();} } }; public class MusicAdapter extends BaseAdapter implements Filterable { private Context mContext; public MusicAdapter(Context c) { mContext = c; } public int getCount() { return currentSongs.size(); } public Object getItem(int position) { return position; } public long getItemId(int position) { return position; } public View getView(int position, View convertView, ViewGroup parent) { System.gc(); TextView tv; if (convertView == null) { tv = new TextView(mContext.getApplicationContext()); } else{ tv = (TextView) convertView; } tv.setTextSize(12); Song song = currentSongs.get(position); int titleLength = song.title.length(); int artistLength = song.artist.length(); SpannableStringBuilder stringBuilder = new SpannableStringBuilder(song.title + "\n"+song.artist); stringBuilder.setSpan(new RelativeSizeSpan(1.5f), 0, titleLength,Spannable.SPAN_INCLUSIVE_INCLUSIVE); stringBuilder.setSpan(new ForegroundColorSpan(Color.rgb(135, 206, 250)), titleLength + 1, titleLength + artistLength +1, Spannable.SPAN_INCLUSIVE_INCLUSIVE); tv.setText(stringBuilder); return tv; } //@Override public Filter getFilter() { return new Filter() { @SuppressWarnings("unchecked") @Override protected void publishResults(CharSequence constraint, FilterResults results) { // Now we have to inform the adapter about the new list filtered if (results.count == 0) notifyDataSetInvalidated(); else { currentSongs = (List<Song>) results.values; notifyDataSetChanged(); } } @Override protected FilterResults performFiltering(CharSequence constraint) { FilterResults results = new FilterResults(); // We implement here the filter logic if (constraint == null || constraint.length() == 0) { // No filter implemented we return all the list results.values = allSongs; results.count = allSongs.size(); } else { // We perform filtering operation List<Song> filteredSongs = new ArrayList<Song>(); String searchString = constraint.toString().toLowerCase(); for (Song song : allSongs) { if (song.title.toLowerCase().contains(searchString) || song.artist.toLowerCase().contains(searchString)) filteredSongs.add(song); } results.values = filteredSongs; results.count = filteredSongs.size(); } return results; } }; } } }