/*************************************************************************** * Copyright 2005-2009 Last.fm Ltd. * * Portions contributed by Casey Link, Lukasz Wisniewski, * * Mike Jennings, and Michael Novak Jr. * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ package fm.last.android; import java.net.URL; import java.util.concurrent.RejectedExecutionException; import android.app.Activity; import android.app.AlertDialog; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.ProgressDialog; import android.app.SearchManager; import android.appwidget.AppWidgetManager; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.net.Uri; import fm.last.android.utils.AsyncTaskEx; import android.os.Build; import android.os.Bundle; import android.os.Parcelable; import android.util.Log; import android.view.KeyEvent; import android.view.View; import android.view.Window; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import fm.last.android.activity.Profile; import fm.last.android.activity.SignUp; import fm.last.android.sync.AccountAuthenticatorService; import fm.last.api.LastFmServer; import fm.last.api.MD5; import fm.last.api.Session; import fm.last.api.SessionInfo; import fm.last.api.WSError; import fm.last.util.UrlUtil; public class LastFm extends Activity { public static final String PREFS = "LoginPrefs"; private boolean mLoginShown; private EditText mPassField; private EditText mUserField; private Button mLoginButton; private Button mSignupButton; /** Specifies if the user has just signed up */ private boolean mNewUser = false; String authInfo; /** Called when the activity is first created. */ @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); requestWindowFeature(Window.FEATURE_NO_TITLE); SharedPreferences settings = getSharedPreferences(PREFS, 0); String user = settings.getString("lastfm_user", ""); String session_key = settings.getString("lastfm_session_key", ""); String pass; try { new CheckUpdatesTask().execute((Void) null); } catch (RejectedExecutionException e) { } if(Integer.decode(Build.VERSION.SDK) >= 6) { if(!AccountAuthenticatorService.hasLastfmAccount(this)) { session_key = ""; LastFMApplication.getInstance().logout(); } } if (!user.equals("") && !session_key.equals("")) { if(getIntent().getAction() != null && getIntent().getAction().equals(Intent.ACTION_SEARCH)) { String query = ""; if(getIntent().getStringExtra(SearchManager.QUERY) != null) query = getIntent().getStringExtra(SearchManager.QUERY); else query = getIntent().getData().toString(); Log.i("LastFm", "Query: " + query); LastFMApplication.getInstance().playRadioStation(this, query, true); } else if (getIntent().getAction() != null && getIntent().getAction().equals("android.appwidget.action.APPWIDGET_CONFIGURE")) { Intent intent = getIntent(); Bundle extras = intent.getExtras(); if (extras != null) { int appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); Intent resultValue = new Intent(); resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId); setResult(RESULT_OK, resultValue); RadioWidgetProvider.updateAppWidget(this); } } else if (getIntent().getAction() != null && getIntent().getAction().equals("fm.last.android.sync.LOGIN")) { Intent intent = getIntent(); Bundle extras = intent.getExtras(); if (extras != null) { try { AccountAuthenticatorService.addAccount(this, user, session_key, extras.getParcelable("accountAuthenticatorResponse")); } catch (Exception e) { Log.i("Last.fm", "Unable to add account"); } } } else { Intent intent = getIntent(); intent = new Intent(LastFm.this, Profile.class); startActivity(intent); Intent i = new Intent("fm.last.android.scrobbler.FLUSH"); sendBroadcast(i); } finish(); return; } setContentView(R.layout.login); mPassField = (EditText) findViewById(R.id.password); mUserField = (EditText) findViewById(R.id.username); if (!user.equals("")) mUserField.setText(user); mLoginButton = (Button) findViewById(R.id.sign_in_button); mSignupButton = (Button) findViewById(R.id.sign_up_button); mUserField.setNextFocusDownId(R.id.password); mPassField.setOnKeyListener(new View.OnKeyListener() { public boolean onKey(View v, int keyCode, KeyEvent event) { switch (event.getKeyCode()) { case KeyEvent.KEYCODE_ENTER: mLoginButton.setPressed(true); mLoginButton.performClick(); return true; } return false; } }); if (icicle != null) { user = icicle.getString("username"); pass = icicle.getString("pass"); if (user != null) mUserField.setText(user); if (pass != null) mPassField.setText(pass); } mLoginButton.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { if (mLoginTask != null) return; String user = mUserField.getText().toString(); String password = mPassField.getText().toString(); if (user.length() == 0 || password.length() == 0) { LastFMApplication.getInstance().presentError(v.getContext(), getResources().getString(R.string.ERROR_MISSINGINFO_TITLE), getResources().getString(R.string.ERROR_MISSINGINFO)); return; } mLoginTask = new LoginTask(v.getContext()); mLoginTask.execute(user, password); } }); mSignupButton.setOnClickListener(new OnClickListener() { public void onClick(View v) { Intent intent = new Intent(LastFm.this, SignUp.class); startActivityForResult(intent, 0); } }); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode != 0 || resultCode != RESULT_OK) return; mUserField.setText(data.getExtras().getString("username")); mPassField.setText(data.getExtras().getString("password")); mNewUser = true; mLoginButton.requestFocus(); mLoginButton.performClick(); } @Override public void onSaveInstanceState(Bundle outState) { outState.putBoolean("loginshown", mLoginShown); if (mLoginShown) { String user = mUserField.getText().toString(); String password = mPassField.getText().toString(); outState.putString("username", user); outState.putString("password", password); } super.onSaveInstanceState(outState); } /** * In a task because it can take a while, and Android has a tendency to * panic and show the force quit/wait dialog quickly. And this blocks. */ private class LoginTask extends AsyncTaskEx<String, Void, Session> { Context context; ProgressDialog mDialog; SessionInfo userSession; Exception e; WSError wse; LoginTask(Context c) { this.context = c; mLoginButton.setEnabled(false); mDialog = ProgressDialog.show(c, "", getString(R.string.main_authenticating), true, false); mDialog.setCancelable(true); } @Override public Session doInBackground(String... params) { String user = params[0]; String pass = params[1]; try { return login(user, pass); } catch (WSError e) { e.printStackTrace(); wse = e; } catch (Exception e) { e.printStackTrace(); this.e = e; } return null; } Session login(String user, String pass) throws Exception, WSError { user = user.toLowerCase().trim(); LastFmServer server = AndroidLastFmServerFactory.getSecureServer(); String md5Password = MD5.getInstance().hash(pass); String authToken = MD5.getInstance().hash(user + md5Password); Session session = server.getMobileSession(user, authToken); if (session == null) throw (new WSError("auth.getMobileSession", "auth failure", WSError.ERROR_AuthenticationFailed)); server = AndroidLastFmServerFactory.getServer(); userSession = server.getSessionInfo(session.getKey()); if(Integer.decode(Build.VERSION.SDK) >= 6) { Parcelable authResponse = null; if(getIntent() != null && getIntent().getExtras() != null) authResponse = getIntent().getExtras().getParcelable("accountAuthenticatorResponse"); AccountAuthenticatorService.addAccount(LastFm.this, user, pass, authResponse); } return session; } @Override public void onPostExecute(Session session) { mLoginButton.setEnabled(true); mLoginTask = null; if (session != null) { SharedPreferences.Editor editor = getSharedPreferences(PREFS, 0).edit(); editor.putString("lastfm_user", session.getName()); editor.putString("lastfm_session_key", session.getKey()); editor.putString("lastfm_subscriber", session.getSubscriber()); editor.putBoolean("remove_playlists", true); editor.putBoolean("remove_tags", true); editor.putBoolean("remove_loved", true); if(userSession != null) { editor.putBoolean("lastfm_radio", userSession.getRadio()); editor.putBoolean("lastfm_freetrial", userSession.getFreeTrial()); editor.putBoolean("lastfm_expired", userSession.getExpired()); editor.putInt("lastfm_playsleft", userSession.getPlaysLeft()); editor.putInt("lastfm_playselapsed", userSession.getPlaysElapsed()); } editor.commit(); LastFMApplication.getInstance().session = session; if (getIntent().getAction() != null && getIntent().getAction().equals("android.appwidget.action.APPWIDGET_CONFIGURE")) { Intent intent = getIntent(); Bundle extras = intent.getExtras(); if (extras != null) { int appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); Intent resultValue = new Intent(); resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId); setResult(RESULT_OK, resultValue); RadioWidgetProvider.updateAppWidget(LastFm.this); } } else if (getIntent().getAction() != null && getIntent().getAction().equals("fm.last.android.sync.LOGIN")) { Intent intent = getIntent(); Bundle extras = intent.getExtras(); if (extras != null) { finish(); } } else if (getIntent().getStringExtra("station") != null) { LastFMApplication.getInstance().playRadioStation(LastFm.this, getIntent().getStringExtra("station"), true); } else { Intent intent = new Intent(LastFm.this, Profile.class); intent.putExtra("lastfm.profile.new_user", mNewUser); if(getIntent() != null && getIntent().getStringExtra(SearchManager.QUERY) != null) intent.putExtra(SearchManager.QUERY, getIntent().getStringExtra(SearchManager.QUERY)); startActivity(intent); } finish(); } else if (wse != null || (e != null && e.getMessage() != null)) { AlertDialog.Builder d = new AlertDialog.Builder(LastFm.this); d.setIcon(android.R.drawable.ic_dialog_alert); d.setNeutralButton(getString(R.string.common_ok), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { } }); if ((wse != null && wse.getCode() == WSError.ERROR_AuthenticationFailed) || (e != null && e.getMessage().contains("code 403"))) { d.setTitle(getResources().getString(R.string.ERROR_AUTH_TITLE)); d.setMessage(getResources().getString(R.string.ERROR_AUTH)); ((EditText) findViewById(R.id.password)).setText(""); d.setNegativeButton(getString(R.string.main_forgotpassword), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { final Intent myIntent = new Intent(android.content.Intent.ACTION_VIEW, Uri.parse("http://www.last.fm/settings/lostpassword")); startActivity(myIntent); } }); } else { d.setTitle(getResources().getString(R.string.ERROR_SERVER_UNAVAILABLE_TITLE)); d.setMessage(getResources().getString(R.string.ERROR_SERVER_UNAVAILABLE)); } d.show(); } else if (wse != null) { LastFMApplication.getInstance().presentError(context, wse); } if(mDialog.isShowing()) { try { mDialog.dismiss(); } catch (Exception e) { //This occasionally fails e.printStackTrace(); } } } } private LoginTask mLoginTask; private class CheckUpdatesTask extends AsyncTaskEx<Void, Void, Boolean> { private String mUpdateURL = ""; @Override public Boolean doInBackground(Void... params) { boolean success = false; try { URL url = new URL("http://cdn.last.fm/client/android/" + getPackageManager().getPackageInfo("fm.last.android", 0).versionName + ".txt"); mUpdateURL = UrlUtil.doGet(url); if (mUpdateURL.startsWith("market://") || mUpdateURL.startsWith("http://")) { success = true; Log.i("Last.fm", "Update URL: " + mUpdateURL); } } catch (Exception e) { // No updates available! Yay! } return success; } @Override public void onPostExecute(Boolean result) { if (result) { NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); Notification notification = new Notification(R.drawable.as_statusbar, getString(R.string.newversion_ticker_text), System.currentTimeMillis()); PendingIntent contentIntent = PendingIntent.getActivity(LastFm.this, 0, new Intent(Intent.ACTION_VIEW, Uri.parse(mUpdateURL)), 0); notification .setLatestEventInfo(LastFm.this, getString(R.string.newversion_info_title), getString(R.string.newversion_info_text), contentIntent); nm.notify(12345, notification); } } } }