65.9K
CodeProject 正在变化。 阅读更多。
Home

使用BroadcastReceiver获取当前播放的歌曲

2015年5月19日

CPOL

3分钟阅读

viewsIcon

22414

在本帖中,我将展示如何获取当前播放歌曲的歌词。

引言

我在网上找到的另一个 API 是 http://api.vagalume.com.br,它的文档和易用性令我惊讶。

这个 API 提供关于歌曲和艺术家的信息;我们可以通过歌曲名称或短语搜索歌曲。

在这篇文章中,我将展示如何使用 BroadcastReceiver 获取当前播放歌曲的歌词。

您可以在 https://github.com/rpresb/android-letradamusica 获取源代码。

准备界面

我不想创建一个非常复杂的界面,因为我只需要一个区域来显示歌曲的歌词。

/res/layout/activity_main.xml 文件中,我们必须创建一个 ScrollView 以便为长歌词启用滚动。

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


/res/values/strings.xml 文件中,有应用程序中使用的所有字符串。 此文件用于轻松创建应用程序的翻译版本,而无需更改任何代码,但我不会在这篇文章中介绍这种情况。

<resources>
 <string name="app_name">Letra da Música</string>

 <string name="carregando">Carregando...</string>
 <string name="action_settings">Settings</string>
</resources>


界面非常简单,没有什么可做的。

需要注意的一个重要事项是,我们有一个 TextView,并且有一个属性 android:id="@+id/status" 允许在代码中访问它。

编写应用程序

从 API 获取数据

因为此应用程序通过互联网访问 API,所以我们必须向 URL 发送 get 请求,结果是一个 JSON,我们必须对其进行操作才能在应用程序中使用。

我创建了一个名为 JSONParser 的类,其中包含一些我在互联网上找到的代码,用于从 URL 获取 JSON 并返回一个 JSONObject 类型的对象。

以下是 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;
    }
}

 

使用 BroadCastReceiver 获取当前播放歌曲

在 MainActivity.java 文件中,它负责控制应用程序的生命周期,这是我们主要代码所在的位置。

为了获取当前播放的歌曲,我们必须使用 BroadCastReceiver。

BroadCastReceiver 基本上是一个响应系统事件的组件,例如当屏幕关闭、电池电量低或像在本例中音乐的播放状态发生变化时。

有很多系统广播通知,您可以通过阅读 https://developer.android.com.cn/reference/android/content/BroadcastReceiver.html 上的文档来深入了解它

onCreate 方法中定义了我们要从广播接收的动作;我们必须注册广播意图,将刚创建的接收器和带有动作的意图过滤器作为参数传递。

然后我们可以使用 AudioManager 检查是否有音乐正在播放。 如果没有播放任何内容,我们会向用户显示没有任何内容在播放。

我创建了一个名为 mReceiver 的 BroadcastReceiver,在 onReceive 方法中,我们可以获取系统发送给我们的信息。 现在我们可以创建 URI 以从 API 获取数据。

VagalumeAsyncTask 通过向 API 发送请求、将响应解析为 JSONObject 并获取歌词文本来完成所有魔法。

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();
            }
        }
    }
}

将应用程序安装在设备或模拟器上后,您将看到以下屏幕

现在取决于您,播放您喜欢的歌曲并欣赏歌词。

当您返回应用程序时,歌词就在那里供您大声歌唱。

结论

在这篇文章中,我制作了一个非常小的应用程序,我使用 BroadcastReceiver 获取当前播放歌曲的数据,并使用此信息从 API 接收歌词。

该应用程序使用扩展 AsyncTask 的类异步调用 API,并在后台完成所有操作,而不会阻塞应用程序。

如果您有任何问题、意见或建议,请在下面留言。

 

© . All rights reserved.