从Shoutcast流中获取元数据Android

4

我正在为Android设备开发一款收音机应用程序,该应用程序应从Shoutcast服务器获取流。

声音正常工作,但我也想检索元数据,以便能够显示当前播放的歌曲标题、艺术家以及专辑图片。

我使用了MediaMetaDataRetriever,但似乎根本没有起作用!

这是我使用的代码:

public class MainActivity extends FragmentActivity {

private ImageView bannerView;
private int[] pub = {R.drawable.banner, R.drawable.pubnautic, R.drawable.pubquad};
private int i = 0;

private ImageView play;
private ImageView pause;
private TextView title;
private MediaPlayer mediaPlayer;
private MediaMetadataRetriever retriever;
private String out;
private String url = "http://streamplus8.leonex.de:14910";
//adele-someonelikeyou
//Accordossie
//http://support.k-designed.net/test-z/music/adele-someonelikeyou.mp3
private ImageView albumpic; 
private byte[] image;
private boolean paused = false;

private ImageView exit;

private ImageView wish;

private ImageView reservation;

private ImageView contact;

private ImageView facebook;

private ImageView twitter;

@Override
protected void onCreate(final Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    bannerView = (ImageView) findViewById(R.id.banner);

    play = (ImageView) findViewById(R.id.play);
    pause = (ImageView) findViewById(R.id.pause);
    exit = (ImageView) findViewById(R.id.exit);
    albumpic = (ImageView) findViewById(R.id.artist);
    title = (TextView) findViewById(R.id.title);
    retriever = new MediaMetadataRetriever();
    mediaPlayer = new MediaPlayer();

    wish = (ImageView) findViewById(R.id.wish);

    reservation = (ImageView) findViewById(R.id.shop);

    contact = (ImageView) findViewById(R.id.contact);

    facebook = (ImageView) findViewById(R.id.facebook);

    twitter = (ImageView) findViewById(R.id.twitter);

    this.setVolumeControlStream(AudioManager.STREAM_MUSIC);  

    try {
        mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
        mediaPlayer.setDataSource(url);
        retriever.setDataSource(url);
        mediaPlayer.prepareAsync();
    } catch (Exception e) {
        Toast.makeText(getApplicationContext(), "Please check your connection!", Toast.LENGTH_LONG).show();
        e.printStackTrace();
    }

    play.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            try {
                if(paused == true) {
                    mediaPlayer.start();
                } else {
                    mediaPlayer.setOnPreparedListener(new OnPreparedListener() {

                        @Override
                        public void onPrepared(MediaPlayer mp) {
                            mediaPlayer.start();

                        }
                    });
                }
                paused = false;
                image = retriever.getEmbeddedPicture();
                if(image != null) {
                    albumpic.setImageBitmap(BitmapFactory.decodeByteArray(image, 0, image.length));
                }
                out =  "Title: " + retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE) + " \nArtist: " + retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST);
                title.setText(out);
                play.setVisibility(ImageView.GONE);
                pause.setVisibility(ImageView.VISIBLE);

            } catch(Exception e) {
                e.printStackTrace();
            }
        }
    });

    pause.setClickable(true);

    pause.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            pause.setVisibility(ImageView.GONE);
            play.setVisibility(ImageView.VISIBLE);
            mediaPlayer.pause();
            paused = true;
        }
    });

    wish.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            Intent wishIntent = new Intent(MainActivity.this, Wish.class);
            startActivity(wishIntent);

        }
    });

    reservation.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            Intent reservIntent = new Intent(MainActivity.this, Reservation.class);
            startActivity(reservIntent);
        }
    });

    contact.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            Intent contactIntent = new Intent(MainActivity.this, Contact.class);
            startActivity(contactIntent);
        }
    });

    facebook.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {

            Intent facebookIntent = new Intent(MainActivity.this, FacebookActivity.class);
            facebookIntent.putExtra("name", "Just now listening to: " + retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE) + " by " + retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST));
            facebookIntent.putExtra("caption", "On AgadirAdventure Radio");
            facebookIntent.putExtra("description", "A Radio App for Android Devices by K-Designed");
            facebookIntent.putExtra("link", "http://www.agadiradventure.com/");
            facebookIntent.putExtra("picture", "http://agadiradventure.com/images/logo/logo1.png");
            startActivity(facebookIntent);

        }
    });

    twitter.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            initShareIntent("twi");

        }
    });

    exit.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            mediaPlayer.stop();
            onBackPressed();
        }
    });

    bannerView.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            Uri uri = Uri.parse("http://www.agadiradventure.com");
            Intent launchBrowser = new Intent(Intent.ACTION_VIEW, uri);
            startActivity(launchBrowser);
        }
    });

    Runnable r = new Runnable() {

        @Override
        public void run() {
            bannerView.setImageResource(pub[i]);
            i++;
            if(i >= pub.length) {
                i = 0;
            }
            bannerView.postDelayed(this, 3000);
        }
    }; 
    bannerView.postDelayed(r, 3000);

}

private void initShareIntent(String type) {
    boolean found = false;
    Intent share = new Intent(android.content.Intent.ACTION_SEND);
    share.setType("text/plain");

    // gets the list of intents that can be loaded.
    List<ResolveInfo> resInfo = getPackageManager().queryIntentActivities(share, 0);
    if (!resInfo.isEmpty()){
        for (ResolveInfo info : resInfo) {
            if (info.activityInfo.packageName.toLowerCase().contains(type) || 
                    info.activityInfo.name.toLowerCase().contains(type) ) {
                String sharedText = "Just now listening to: " + retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE) + " by " + retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST) + "\nOn AgadirAdventure\nwww.agadiradventure.com";
                share.putExtra(Intent.EXTRA_TEXT, sharedText);
                share.setPackage(info.activityInfo.packageName);
                found = true;
                break;
            }
        }
        if (!found)
            return;

        startActivity(Intent.createChooser(share, "Select"));
    }
}

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_BACK) {
        moveTaskToBack(true);
        return true;
    }
    return super.onKeyDown(keyCode, event);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.activity_main, menu);
    return true;
}

}

感谢您的帮助!
2个回答

6

我创建了自己的类来检索元数据,这是基于streamscraper的修改版本。使用这个 jar(streamscraper),这个 jar(jsoup)和这个类来检索元数据。接口与MediaMetadataRetriever相似:

ShoutCastMetadataRetriever smr = new ShoutCastMetadataRetriever();
smr.setDataSource(<some url>);
String artist = smr.extractMetadata(ShoutCastMetadataRetriever.METADATA_KEY_ARTIST);
String title = smr.extractMetadata(ShoutCastMetadataRetriever.METADATA_KEY_TITLE);

我不相信 SHOUTcast 元数据支持专辑封面,因此您将无法检索到它。

1
现在你自相矛盾。你的帖子说专辑封面不在那里。你从我发布的链接中引用的语句说数据是内置的。 - Brad
1
完美运行!@WilliamSeeman 谢谢! 它只需要从这里下载jsoup jar包http://sourceforge.net/p/servestream/code/HEAD/tree/trunk/libs/jsoup-1.7.2.jar - user1885868
1
@WilliamSeeman,现在我们将拥有2个setDataSources(path)吗?一个用于媒体播放器,另一个用于元数据?每当我在smr上调用setDataSources时,我都会收到net.moraleboost.streamscraper.ScrapeException异常。有什么想法吗? - tony9099
@williamSeemann 我使用这个网址:http://streaming-live.es:8188 也遇到了 ScrapeException。 - Aracem
2
嗨,William Seemann,你能再次添加到你的ShoutCastMetadataRetriever类的链接吗?因为链接已经失效了。谢谢。 - pavol.franek
显示剩余3条评论

5
由于@William-Seemann的类已不再可用。这里提供了一种替代方案(它的好处是不需要任何库):
将以下添加到您的项目中。您现在可以像这里所示那样使用它。您也可以像这样使用它:
    String title = "";
    IcyStreamMeta meta = new IcyStreamMeta();
    try {
        meta.setStreamUrl(new URL(YOURURL));
        title = meta.getStreamTitle();
    } catch (MalformedURLException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

非常感谢dazza5000创建了这个项目。


但是我该如何监听“曲目更改”事件以更新标签,例如? - johnnyshrewd
@johnnyshrewd,这个类没有监听器。可能需要通过每隔 x 秒运行上面的代码片段创建自己的 “事件监听器”,直到在标题中检测到更改,然后您可以调用自己的监听器。 - Mdlc

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接