Android

29 abr, 2015

Criando um App Android com a API do vagalume.com.br

Publicidade

best-android-music-apps

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:

captura-de-tela-2015-04-05-c3a0s-11-27-52

No tipo de instalação, escolhi a opção Standard, pois não preciso personalizar nada neste momento.

captura-de-tela-2015-04-05-c3a0s-11-28-01

Agora vem a parte mais demorada. Aceite as licenças e pode ir tomar um café.

captura-de-tela-2015-04-05-c3a0s-11-28-16

Ao terminar a instalação, inicie o Android Studio e você verá a tela abaixo:

captura-de-tela-2015-04-05-c3a0s-19-29-40

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).

captura-de-tela-2015-04-06-c3a0s-18-50-33

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.

captura-de-tela-2015-04-05-c3a0s-19-31-33

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.

captura-de-tela-2015-04-05-c3a0s-19-31-59

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.

captura-de-tela-2015-04-05-c3a0s-19-34-04

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.

captura-de-tela-2015-04-06-c3a0s-20-43-49

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.

captura-de-tela-2015-04-06-c3a0s-20-47-00

É 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:

tela1

Basta você escolher uma música e colocar para tocar no player padrão do seu Android:

tela2

E quando você voltar para o seu app, verá a letra da música pronta para você acompanhar seu artista favorito na cantoria.

tela3

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.