从Shoutcast流中获取元数据Android

问题描述:

我正在为Android设备开发一个应用程序的Radio应用程序,该应用程序应该从Shoutcast服务器获取流媒体。从Shoutcast流中获取元数据Android

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

我使用了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; 
} 

} 

感谢您的帮助!

由于@ William-Seemann答案中的类不再可用。这是一个替代方案(其好处是不需要任何库):

将以下class添加到您的项目中。您现在可以如图所示使用它here。您也可以使用这样的:

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创建项目。

+0

但是,我怎么能听到“跟踪更改”事件来更新标签,例如? – johnnyshrewd 2018-01-30 14:02:32

+0

@johnnyshrewd这个类没有监听器。通过每隔x秒运行一次上述代码片段,直到在标题中检测到更改,您可以调用您的侦听器,可能会创建您自己的“事件侦听器”。 – Mdlc 2018-02-01 09:59:40

我创建了我自己的类来检索基于修改后的版本streamscraper的元数据。使用​​3210 jar(streamscraper),this jar(jsoup)和this类来检索元数据。该界面类似于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一样的元数据支持专辑封面,所以你将无法检索。

+0

SHOUTcast v1甚至不支持艺术家或标题。这只是一个通常被格式化为“艺术家 - 标题”的字符串。 SHOUTcast v2确实提供专辑封面,如果它可以从编码器中获得的话。 – Brad 2013-05-11 14:28:53

+0

http://wiki.winamp.com/wiki/SHOUTcast_XML_Metadata_Specification – Brad 2013-05-11 17:45:03

+1

现在你是自相矛盾的。你的帖子说专辑封面不在那里。您从我发布的链接中引用的报价表示数据正在流中。 – Brad 2013-05-13 03:40:48