最近.Net开源着实让C#火了一把,好久就听说Mono for Android一直没静下心来看,上周末找来看看,确实不错,前台界面axml编写跟Java安卓开发毫无区别,后台用C#其实很多windows下的方法都可以用,做一个安卓音乐播放器,主要实现音乐播放,上一曲下一曲,音乐播放列表,随机播放,扫描SD卡内所有音乐。
先show一组界面啊,话说有图有真相啊:
项目结构如图:
Lrc是歌词处理方法
MusicService是安卓服务播放音乐,服务Broadcast,以及界面接收Receiver
SqlHelper是歌曲扫描后寸本地数据库Sqlite的一些方法
说说几个难点:
音乐扫描:
主要就是遍历目录,代码如下
IList<FileSystemInfo> visibleThings = new List<FileSystemInfo> (); var dir = new DirectoryInfo (directory); try { foreach (var item in dir.GetFileSystemInfos().Where(item => item.IsVisible())) { visibleThings.Add (item); if (item.IsDirectory ()) { RefreshFilesList (item.FullName); } if (item.IsFile () && (item.FullName.Substring (item.FullName.LastIndexOf (".") + 1)) == "mp3") { //是音乐文件 }
ListView添加数据,这个主要用到ListAdapter,ListAdapter是新建一个前台xaml界面,每个界面存放一首歌曲,然后最后把遍历所有歌曲加入N个界面,这N个界面加入ListView,
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/linearLayout1" android:layout_width="fill_parent" android:layout_height="fill_parent"> <TextView android:id="@+id/songid" android:layout_width="wrap_content" android:layout_height="0dip" android:textColor="#FF7F3300" android:textSize="0dip" android:textStyle="italic" android:visibility="invisible" /> <TextView android:id="@+id/songtitle" android:layout_width="wrap_content" android:layout_height="50dip" android:textSize="20dip" android:textColor="#FFFFFF" android:paddingLeft="5dip" android:gravity="center_vertical|left" /> <TextView android:id="@+id/songurl" android:layout_width="wrap_content" android:layout_height="0dip" android:visibility="invisible" /> </LinearLayout>
后台代码:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Android.App; using Android.Content; using Android.OS; using Android.Runtime; using Android.Views; using Android.Widget; using Android.Util; namespace MusicPlayer { public class SongListAdapter: BaseAdapter<SongDetail> { List<SongDetail> items; Activity context; public SongListAdapter (Activity context, List<SongDetail> items) : base() { this.context = context; this.items = items; } public override long GetItemId(int position) { return position; } public override SongDetail this[int position] { get { return items[position]; } } public override int Count { get { return items.Count; } } public override View GetView(int position, View convertView, ViewGroup parent) { var item = items[position]; View view = convertView; if (view == null) view = context.LayoutInflater.Inflate(Resource.Layout.SongItem, null); view.FindViewById<TextView>(Resource.Id.songid).Text = item.ID.ToString(); view.FindViewById<TextView>(Resource.Id.songtitle).Text = item.Title; view.FindViewById<TextView>(Resource.Id.songurl).Text=(item.Path); return view; } } }
listView加入方式:
Lv = FindViewById<ListView> (Resource.Id.listView1); Lv.Adapter = new SongListAdapter (this, SonList);
其中sonlist是遍历除了所有歌曲List集合
至于安卓服务,主要就是继承Service,主要代码:
[Service] public class MainService : Service { public override void OnCreate() { base.OnCreate(); Log.Debug("xamarin", "创建服务"); } public override StartCommandResult OnStartCommand(Android.Content.Intent intent, StartCommandFlags flags, int startId) { Log.Debug("xamarin", "启动服务"); return StartCommandResult.Sticky; } public override void OnDestroy() { base.OnDestroy(); Log.Debug("xamarin", "关闭服务"); } public override Android.OS.IBinder OnBind(Android.Content.Intent intent) { return null; } }
最后歌词显示,主要用到就是解析歌词,解析歌词C#下面有代码可参考,不知道具体怎么解析的搜搜winform做音乐播放器歌词是怎么做的,其实就是一个播放但钱position和播放时间转换成position的一个匹配,下面看解析歌词的方法:
public class Lrc { /// <summary> /// 歌曲 /// </summary> public string Title { get; set; } /// <summary> /// 艺术家 /// </summary> public string Artist { get; set; } /// <summary> /// 专辑 /// </summary> public string Album { get; set; } /// <summary> /// 歌词作者 /// </summary> public string LrcBy { get; set; } /// <summary> /// 偏移量 /// </summary> public string Offset { get; set; } /// <summary> /// 歌词 /// </summary> public Dictionary<double, string> LrcWord = new Dictionary<double, string>(); /// <summary> /// 获得歌词信息 /// </summary> /// <param name="LrcPath">歌词路径</param> /// <returns>返回歌词信息(Lrc实例)</returns> public static Lrc InitLrc(string LrcPath) { Lrc lrc = new Lrc(); using (FileStream fs = new FileStream(LrcPath, FileMode.Open, FileAccess.Read, FileShare.Read)) { string line; using (StreamReader sr = new StreamReader(fs, Encoding.Default)) { while ((line = sr.ReadLine()) != null) { if (line.StartsWith("[ti:")) { lrc.Title = SplitInfo(line); } else if (line.StartsWith("[ar:")) { lrc.Artist = SplitInfo(line); } else if (line.StartsWith("[al:")) { lrc.Album = SplitInfo(line); } else if (line.StartsWith("[by:")) { lrc.LrcBy = SplitInfo(line); } else if (line.StartsWith("[offset:")) { lrc.Offset = SplitInfo(line); } else { Regex regex = new Regex(@"\[([0-9.:]*)\]+(.*)", RegexOptions.Compiled); MatchCollection mc = regex.Matches(line); double time = TimeSpan.Parse("00:" + mc[0].Groups[1].Value).TotalSeconds; string word = mc[0].Groups[2].Value; lrc.LrcWord.Add(time, word); } } } } return lrc; } /// <summary> /// 处理信息(私有方法) /// </summary> /// <param name="line"></param> /// <returns>返回基础信息</returns> static string SplitInfo(string line) { return line.Substring(line.IndexOf(":") + 1).TrimEnd(‘]‘); } } 一行代码:Lrc lrc= Lrc.InitLrc("test.lrc");
差不多就这样,最后还有一个菜单创建
public override bool OnCreateOptionsMenu(IMenu menu) { var m1 = menu.Add(0, 1, 0, "歌曲列表"); var m2 = menu.Add (0,2,0,"退出"); return base.OnCreateOptionsMenu(menu); } public override bool OnOptionsItemSelected(IMenuItem item) { switch (item.ItemId) { case 1: break; case 2: break; } return base.OnOptionsItemSelected(item); }
好啦,差不多就是这些,至于音乐播放都是用Mediaplaye系统提供Api搞定
时间: 2024-10-03 14:28:41