Uma API que encontrei navegando na Internet e que me surpreendeu pela boa documentação e facilidade de utilização é a API Vagalume.com.br. Ela oferece informações sobre músicas e artistas; podemos buscar músicas por trecho da letra ou pelo nome.
Nesse artigo vou mostrar como obter a letra da música que está tocando no Android e o código pode ser obtido neste link.
Instalando o Android Studio
Baixe o arquivo de instalação neste link e siga os passos da instalação abaixo:
No tipo de instalação, escolhi a opção Standard, pois não preciso personalizar nada neste momento.
Agora vem a parte mais demorada. Aceite as licenças e pode ir tomar um café.
Ao terminar a instalação, inicie o Android Studio e você verá a tela abaixo:
Criando o projeto
Escolha a opção Start a new Android Studio project, nesta tela você deve escolher o nome da sua aplicação, informar um domínio (eu criei comobr.com.presba, mas o ideal é usar o seu domínio real, pois o Android já muda a ordem para criar o pacote, nesse caso deveria ter sido presba.com.br).
Na próxima tela você deve escolher o SDK mínimo para a sua aplicação.
Quanto menor o SDK selecionado, maior será o número de usuários possíveis para seu App. Eu deixei selecionada a API 15, que é a partir do Android 4.0.3.
A próxima tela é onde devemos escolher o template para iniciar o nosso projeto.
Selecionei Blank Activity por se tratar de um app bem simples.
A última tela antes do início da programação é onde devemos informar o nome da Activity principal, um nome para o layout dessa activity, um título para a app e o nome do menu.
A única coisa que eu alterei foi o campo Title para definir o título da app.
O projeto está agora pronto para iniciar.
Preparando a interface
Para a interface, não pretendo mexer muito, pois preciso apenas separar um espaço para apresentar a letra da música.
No arquivo /res/layout/activity_main.xml, precisamos colocar um ScrollView para poder habilitar a rolagem para as letras das músicas que são extensas.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:scrollbars="vertical" tools:context=".MainActivity"> <ScrollView android:layout_width="fill_parent" android:layout_height="fill_parent"> <TextView android:id="@+id/status" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/carregando" /> </ScrollView> </RelativeLayout>
O arquivo /res/values/strings.xml tem os valores utilizados para a app. Este arquivo serve para fazer a tradução da app sem que tenha muito trabalho, mas para o nosso caso não faremos para multi-idioma.
<resources> <string name="app_name">Letra da Música</string> <string name="carregando">Carregando...</string> <string name="action_settings">Settings</string> </resources>
A interface é bem simples e não tem muito o que ser feito.
Uma coisa importante que deve ser levado em conta é que no layout temos um TextView e definimos o atributo android:id=”@+id/status” para que ele seja acessado via código.
Programando o app
Como esse app acessa uma API na web, devemos fazer o acesso HTTP de uma URL e o resultado será um JSON que devemos manipular para utilizar na nossa app.
Eu criei uma classe chamada JSONParser, utilizando partes de código que encontrei na Internet, para obter o JSON de uma URL e retornar um objeto do tipoJSONObject.
Abaixo o arquivo JSONParser.java:
package presba.com.br.letradamusica; import android.util.Log; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.conn.ClientConnectionManager; import org.apache.http.conn.scheme.PlainSocketFactory; import org.apache.http.conn.scheme.Scheme; import org.apache.http.conn.scheme.SchemeRegistry; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; import org.apache.http.params.BasicHttpParams; import org.apache.http.params.HttpConnectionParams; import org.apache.http.params.HttpParams; import org.json.JSONException; import org.json.JSONObject; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.security.KeyStore; public class JSONParser { static InputStream is = null; static JSONObject jObj = null; static String json = ""; HttpClient httpClient = createHttpClient(); public JSONParser() { } public static HttpClient createHttpClient() { try { KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); trustStore.load(null, null); HttpParams params = new BasicHttpParams(); HttpConnectionParams.setConnectionTimeout(params, 15000); HttpConnectionParams.setSoTimeout(params, 5000); SchemeRegistry registry = new SchemeRegistry(); registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry); return new DefaultHttpClient(ccm, params); } catch (Exception e) { return new DefaultHttpClient(); } } public JSONObject getJSONFromUrl(String url) { try { HttpGet httpGet = new HttpGet(url); HttpResponse httpResponse = httpClient.execute(httpGet); HttpEntity httpEntity = httpResponse.getEntity(); is = httpEntity.getContent(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } try { BufferedReader reader = new BufferedReader(new InputStreamReader( is, "iso-8859-1"), 8); StringBuilder sb = new StringBuilder(); String line = null; while ((line = reader.readLine()) != null) { sb.append(line + "n"); } is.close(); json = sb.toString(); } catch (Exception e) { Log.e("Buffer Error", "Error converting result " + e.toString()); } try { jObj = new JSONObject(json); } catch (JSONException e) { Log.e("JSON Parser", "Error parsing data " + e.toString()); } return jObj; } }
No arquivo MainActivity.java, que é responsável por controlar o ciclo de vida da app, é onde está nosso principal código da app.
package presba.com.br.letradamusica; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.media.AudioManager; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.widget.TextView; import org.json.JSONException; import org.json.JSONObject; public class MainActivity extends ActionBarActivity { TextView status = null; private BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); String cmd = intent.getStringExtra("command"); Log.d("Music", cmd + " : " + action); String artist = intent.getStringExtra("artist"); String album = intent.getStringExtra("album"); String track = intent.getStringExtra("track"); boolean playing = intent.getBooleanExtra("playing", false); Log.d("Music", artist + " : " + album + " : " + track); if (!playing) { status.setText("Nenhuma música tocando"); } else { status.setText(artist + "\n" + album + "\n" + track); String uri = Uri.parse("http://api.vagalume.com.br/search.php .buildUpon() .appendQueryParameter("mus", track) .appendQueryParameter("art", artist) .build().toString(); if (uri != null) { new VagalumeAsyncTask().execute(uri); } } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); IntentFilter iF = new IntentFilter(); iF.addAction("com.android.music.musicservicecommand"); iF.addAction("com.android.music.metachanged"); iF.addAction("com.android.music.playstatechanged"); iF.addAction("com.android.music.updateprogress"); this.status = (TextView) this.findViewById(R.id.status); registerReceiver(mReceiver, iF); AudioManager manager = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE); if (!manager.isMusicActive()) { status.setText("Nenhuma música tocando"); } } @Override protected void onPause() { super.onPause(); unregisterReceiver(mReceiver); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } private class VagalumeAsyncTask extends AsyncTask<String, Void, JSONObject> { @Override protected JSONObject doInBackground(String... params) { JSONParser jParser = new JSONParser(); return jParser.getJSONFromUrl(params[0]); } @Override protected void onPostExecute(JSONObject json) { super.onPostExecute(json); try { JSONObject mus = (JSONObject) json.getJSONArray("mus").get(0); status.setText(mus.getString("text")); } catch (JSONException e) { e.printStackTrace(); } } } }
Executando o app
Quando você clicar em executar (menu Run > Run…) no Android Studio, você vai ver uma tela como a que está abaixo para selecionar um device para executar sua app.
Caso você tenha um celular ou tablet Android, é só conectá-lo ao seu computar e habilitar o modo desenvolvedor no device. Com isso feito, seu device aparecerá na lista e você pode escolher ele para rodar a app.
Caso você não tenha um celular ou tablet, pode escolher a opção Launch emulator e testar seu código no emulador.
É sempre melhor testar num dispositivo real, porém o emulador ajuda bastante quando não temos um celular ou tablet disponível.
Após o app abrir no device ou emulador, você verá a tela abaixo:
Basta você escolher uma música e colocar para tocar no player padrão do seu Android:
E quando você voltar para o seu app, verá a letra da música pronta para você acompanhar seu artista favorito na cantoria.
Conclusão
Como sempre, gosto de utilizar um app para ver o que dá pra fazer com a API.
Neste artigo, fiz um app bem simples em Android onde foi utilizado um BroadcastReceiver para obter os dados da música atual e, com essa informação, solicitei à API a letra da música.
Foi feito uma solicitação assíncrona para a API com uma classe que estende a AsyncTask e faz tudo por baixo dos panos, para que a app fique acessível o tempo todo.
Caso tenha alguma dúvida sobre a implementação ou alguma crítica ou sugestão, envie uma mensagem que responderei com prazer.