Swift版音乐播放器(简化版)

这几天闲着也是闲着,学习一下Swift的,于是到开源社区Download了个OC版的音乐播放器,练练手,在这里发扬开源精神,

希望对大家有帮助!

这个DEMO里,使用到了

AudioPlayer(对音频封装的库)

FreeStreamer(老外写的音频高效处理库)

LKDBHelper(将数据模型直接写到数据库中的库)

AFNetworking (网络库)

SDWebImage (图片获取库)

另外,我也把OC版的ProgressHUD转成了Swift版本的HYBProgressHUD,希望对大家有用啊!

目前只实现了这几个简单的功能,希望有时间且爱研究的同学,追加更多的功能再开源出来哦!

下面我说一下封装的网络请求类:

import Foundation

/// 请求成功与失败的回调
typealias requestSuccessCloser = (responseObject: AnyObject?) ->Void
typealias failCloser = (error: NSError?) ->Void

///
/// 描述:网络请求基础类,所有GET请求方式都是以GET开头的类方法,POST请求方式会以POST开头命名类方法
///
/// 作者:huangyibiao
class HYBBaseRequest: NSObject {
    struct BaseURL {
        static var baseURL: String = kServerBase
    }

    ///
    /// 描述:解析JSON数据
    ///
    /// 参数:jsonObject 网络请求获取下来数据
    ///
    /// 返回:如果解析成功,返回字典,否则返回nil
    class func parseJSON(#jsonObject: AnyObject?) ->NSDictionary? {
        if let result = jsonObject as? NSDictionary {
            return result
        }
        return nil
    }

    ///
    /// 描述: GET请求方式
    ///
    /// 参数: serverPath --请求路径,不包含基础路径
    ///       success    --请求成功时的回调闭包
    ///       fail       --请求失败时的回调闭包
    ///
    /// 返回: AFHTTPRequestOperation类型对象,外部可以通过引用此对象实例,在需要取消请求时,调用cancel()方法
    class func GETRequest(serverPath: String, success: requestSuccessCloser, fail: failCloser) ->AFHTTPRequestOperation {
        var op =  manager().GET(serverPath, parameters: nil, success: { (op, responseObject) -> Void in
            success(responseObject: responseObject)
            }, failure: { (op, error) -> Void in
                fail(error: error)
        })
        return op
    }

    class func downloadFile(serverPath: String, success: requestSuccessCloser, fail: failCloser) ->AFHTTPRequestOperation {
        var op =  AFHTTPRequestOperation(request: NSURLRequest(URL: NSURL(string: String(format: "%@%@", kServeBase1, serverPath))))
        op.setCompletionBlockWithSuccess({ (requestOp, responseObject) -> Void in
            success(responseObject: responseObject)
        }, failure: { (requestOP, error) -> Void in
            fail(error: error)
        })
        op.start()
        return op
    }

    ///
    /// 私有方法区
    ///
    private  class func manager() ->AFHTTPRequestOperationManager {
        var manager = AFHTTPRequestOperationManager(baseURL: NSURL(string: BaseURL.baseURL))

        manager.requestSerializer.setValue("application/json", forHTTPHeaderField: "Accept")
        manager.requestSerializer.setValue("application/json", forHTTPHeaderField: "content-type")
        manager.requestSerializer.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Accept")
        manager.requestSerializer.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")

        // 设置响应头支持的格式
        manager.responseSerializer.acceptableContentTypes = NSSet(array: ["application/json", "application/javascript", "application/lrc", "application/x-www-form-urlencoded"])
        return manager
    }
}

因为资源类型不同,所以要在请求头添加支持的格式才能访问到资源哦。

下面是封装歌词显示的UI,这里没有细化对时间的把握,只是粗略实现功能,有时间的同学可以对播放进度把握得更好!

import Foundation

///
/// 描述: 显示歌词控件
///
/// 作者: huangyibiao
class HYBSongLRCView: UIView {
    private var scrollView: UIScrollView!
    private var keyArray = NSMutableArray()
    private var titleArray = NSMutableArray()
    private var lineLabelArray = NSMutableArray()
    private var currentPlayingLineTime: float_t = 0.0

    ///
    /// 重写父类的方法
    ///
    override init(frame: CGRect) {
        super.init(frame: frame)

        self.scrollView = UIScrollView(frame: CGRectMake(0, 10, self.width(), self.height() - 20))
        // 暂时关闭可交互功能
        self.scrollView.userInteractionEnabled = false
        self.addSubview(self.scrollView)
    }

    required init(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    ///
    /// public方法区
    ///

    ///
    /// 描述:解析歌词
    ///
    /// 参数:lrcPath LRC歌词的路径
    func parseSong(lrcPath: String) {
        self.keyArray.removeAllObjects()
        self.titleArray.removeAllObjects()

        var content = NSString(contentsOfFile: lrcPath, encoding: NSUTF8StringEncoding, error: nil)
        var array = content.componentsSeparatedByString("\n")
        // 解析每一行
        for line in array {
            if let lrcLine = line as? NSString {
                if lrcLine.length != 0 {
                    self.parseLRCLine(lrcLine)
                }
            }
        }

        self.bubbleSortLrcLines(self.keyArray)

        self.scrollView.contentOffset = CGPointZero
        self.scrollView.contentSize = CGSizeMake(scrollView.width(), CGFloat(keyArray.count * 25))
        self.configureLRCLineLabels()
    }

    ///
    /// 描述:移除显示歌词的标签
    func removeAllSubviewsInScrollView() {
        for subview in self.scrollView.subviews {
            subview.removeFromSuperview()
        }

        self.lineLabelArray.removeAllObjects()
    }

    ///
    /// 描述:移除之前的歌词数据
    func clearLRCContents() {
        self.keyArray.removeAllObjects()
        self.titleArray.removeAllObjects()
    }

    ///
    /// 描述:指定歌词播放的时间,会根据时间滚动到对应的歌词行
    ///
    /// 参数:time 歌词行播放的时间
    func moveToLRCLine(#time: NSString) {
        if self.keyArray.count != 0 {
            var currentTimeValue = self.timeToFloat(time)

            var index = 0
            var hasFound = false
            for index = 0; index < self.keyArray.count; index++ {
                if let lrcTime = self.keyArray[index] as? NSString {
                    var tmpTimeValue = self.timeToFloat(lrcTime)
                    if fabs(tmpTimeValue - currentTimeValue) <= fabs(0.000000001) {
                        hasFound = true
                        currentPlayingLineTime = tmpTimeValue
                        break
                    }
                }
            }

            if hasFound || (!hasFound && currentPlayingLineTime < currentTimeValue) {
                if index < self.lineLabelArray.count {
                    if let label = self.lineLabelArray[index] as? UILabel {
                        updateCurrentTimeLRC(label)
                        self.scrollView.setContentOffset(CGPointMake(0.0, 25.0 * CGFloat(index)),
                            animated: true)
                    }
                }
            }
        }
    }

    ///
    /// private方法区
    ///

    ///
    /// 描述:解析歌词行
    ///
    /// 参数:lrcLine 该行歌词
    private func parseLRCLine(lrcLine: NSString) {
        if lrcLine.length == 0 {
            return
        }

        var array = lrcLine.componentsSeparatedByString("\n")
        for var i = 0; i < array.count; i++ {
            var tempString = array[i] as NSString
            var lineArray = tempString.componentsSeparatedByString("]")

            for var j = 0; j < lineArray.count - 1; j++ {
                var line = lineArray[j] as NSString

                if line.length > 8 {
                    var str1 = tempString.substringWithRange(NSMakeRange(3, 1))
                    var str2 = tempString.substringWithRange(NSMakeRange(6, 1))

                    if str1 == ":" && str2 == "." {
                        var lrc = lineArray.last as NSString
                        var time = lineArray[j].substringWithRange(NSMakeRange(1, 8)) as NSString
                        // 时间作为KEY
                        self.keyArray.addObject(time.substringToIndex(5))
                        // 歌词会为值
                        self.titleArray.addObject(lrc)
                    }
                }
            }
        }
    }

    ///
    /// 描述:对所有歌词行进行冒泡排序
    ///
    /// 参数:array 要进行冒泡排序的数组
    private func bubbleSortLrcLines(array: NSMutableArray) {
        for var i = 0; i < array.count; i++ {
            var firstValue = self.timeToFloat(array[i] as NSString)

            for var j = i + 1; j < array.count; j++ {
                var secondValue = self.timeToFloat(self.keyArray[j] as NSString)

                if firstValue > secondValue {
                    array.exchangeObjectAtIndex(i, withObjectAtIndex: j)
                    self.titleArray.exchangeObjectAtIndex(i, withObjectAtIndex: j)
                }

            }
        }
    }

    ///
    /// 描述:把时间字符串转换成浮点值
    ///
    /// 参数:time 时间字符串,格式为:"05:11"
    private func timeToFloat(time: NSString) ->float_t {
        var array = time.componentsSeparatedByString(":")

        var result: NSString = "\(array[0])"
        if array.count >= 2 {
            result = "\(array[0]).\(array[1])"
        }

        return result.floatValue
    }

    ///
    /// 描述:创建显示歌词的标签
    private func configureLRCLineLabels() {
        self.removeAllSubviewsInScrollView()

        for var i = 0; i < titleArray.count; i++ {
            var title = titleArray[i] as String
            var label = UIMaker.label(CGRectMake(0.0,
                25.0 * CGFloat(i) + scrollView.height() / 2.0,
                scrollView.width(),
                25.0),
                title: title)
            label.textColor = UIColor.lightGrayColor()
            label.font = UIFont.systemFontOfSize(14.0)

            scrollView.addSubview(label)
            lineLabelArray.addObject(label)
        }
    }

    ///
    /// 描述:更新当前显示的歌词
    private func updateCurrentTimeLRC(currentLabel: UILabel) {
        for label in self.lineLabelArray {
            if let item = label as? UILabel {
                if item == currentLabel {
                    item.textColor = kNavColor
                    item.font = UIFont.boldSystemFontOfSize(16.0)
                } else {
                    item.textColor = UIColor.lightGrayColor()
                    item.font = UIFont.systemFontOfSize(14.0)
                }
            }
        }
    }
}

Swift版的HYBProgressHUD控件,调用方式是非常简单的,使用的都是公开的类方法调用方式:

import Foundation
import UIKit

///
/// @brief 样式
enum HYBProgressHUDStyle {
    case BlackHUDStyle /// 黑色风格
    case WhiteHUDStyle /// 白色风格
}

///
/// @brief 定制显示通知的视图HUD
/// @author huangyibiao
class HYBProgressHUD: UIView {
    var hud: UIToolbar?
    var spinner: UIActivityIndicatorView?
    var imageView: UIImageView?
    var titleLabel: UILabel?

    ///
    /// private 属性
    ///
    private let statusFont = UIFont.boldSystemFontOfSize(16.0)
    private var statusColor: UIColor!
    private var spinnerColor: UIColor!
    private var bgColor: UIColor!
    private var successImage: UIImage!
    private var errorImage: UIImage!

    ///
    /// @brief 单例方法,只允许内部调用
    private class func sharedInstance() ->HYBProgressHUD {
        struct Instance {
            static var onceToken: dispatch_once_t = 0
            static var instance: HYBProgressHUD?
        }

        dispatch_once(&Instance.onceToken, { () -> Void in
            Instance.instance = HYBProgressHUD(frame: UIScreen.mainScreen().bounds)
            Instance.instance?.setStyle(HYBProgressHUDStyle.WhiteHUDStyle)
        })

        return Instance.instance!
    }

    override init(frame: CGRect) {
        super.init(frame: frame)

        hud = nil
        spinner = nil
        imageView = nil
        titleLabel = nil
        self.alpha = 0.0
    }

    required init(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    ///
    /// 公开方法
    ///

    /// 显示信息
    class func show(status: String) {
        sharedInstance().configureHUD(status, image: nil, isSpin: true, isHide: false)
    }

    /// 显示成功信息
    class func showSuccess(status: String) {
        sharedInstance().configureHUD(status, image: sharedInstance().successImage, isSpin: false, isHide: true)
    }

    /// 显示出错信息
    class func showError(status: String) {
        sharedInstance().configureHUD(status, image: sharedInstance().errorImage, isSpin: false, isHide: true)
    }

    /// 隐藏
    class func dismiss() {
        sharedInstance().hideHUD()
    }

    ///
    /// 私有方法
    ///

    ///
    /// @brief 创建并配置HUD
    private func configureHUD(status: String?, image: UIImage?, isSpin: Bool, isHide: Bool) {
        configureProgressHUD()

        /// 标题
        if status == nil {
            titleLabel!.hidden = true
        } else {
            titleLabel!.text = status!
            titleLabel!.hidden = false
        }
        // 图片
        if image == nil {
            imageView?.hidden = true
        } else {
            imageView?.hidden = false
            imageView?.image = image
        }

        // spin
        if isSpin {
            spinner?.startAnimating()
        } else {
            spinner?.stopAnimating()
        }

        rotate(nil)
        addjustSize()
        showHUD()

        if isHide {
            NSThread.detachNewThreadSelector("hideWhenTimeout", toTarget: self, withObject: nil)
        }
    }

    ///
    /// @brief 设置风格样式,默认使用的是黑色的风格,如果需要改成白色的风格,请在内部修改样式
    private func setStyle(style: HYBProgressHUDStyle) {
        switch style {
        case .BlackHUDStyle:
            statusColor = UIColor.whiteColor()
            spinnerColor = UIColor.whiteColor()
            bgColor = UIColor(white: 0, alpha: 0.8)
            successImage = UIImage(named: "ProgressHUD.bundle/success-white.png")
            errorImage = UIImage(named: "ProgressHUD.bundle/error-white.png")
            break
        case .WhiteHUDStyle:
            statusColor = UIColor.whiteColor()
            spinnerColor = UIColor.whiteColor()
            bgColor = UIColor(red: 192.0 / 255.0, green: 37.0 / 255.0, blue: 62.0 / 255.0, alpha: 1.0)
            successImage = UIImage(named: "ProgressHUD.bundle/success-white.png")
            errorImage = UIImage(named: "ProgressHUD.bundle/error-white.png")
            break
        default:
            break
        }
    }

    ///
    /// @brief 获取窗口window
    private func getWindow() ->UIWindow {
        if let delegate: UIApplicationDelegate = UIApplication.sharedApplication().delegate {
            if let window = delegate.window {
                return window!
            }
        }

        return UIApplication.sharedApplication().keyWindow
    }

    ///
    /// @brief 创建HUD
    private func configureProgressHUD() {
        if hud == nil {
            hud = UIToolbar(frame: CGRectZero)
            hud?.barTintColor = bgColor
            hud?.translucent = true
            hud?.layer.cornerRadius = 10
            hud?.layer.masksToBounds = true

            /// 监听设置方向变化
            NSNotificationCenter.defaultCenter().addObserver(self,
                selector: "rotate:",
                name: UIDeviceOrientationDidChangeNotification,
                object: nil)
        }

        if hud!.superview == nil {
            getWindow().addSubview(hud!)
        }

        if spinner == nil {
            spinner = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.WhiteLarge)
            spinner!.color = spinnerColor
            spinner!.hidesWhenStopped = true
        }

        if spinner!.superview == nil {
            hud!.addSubview(spinner!)
        }

        if imageView == nil {
            imageView = UIImageView(frame: CGRectMake(0, 0, 28, 28))
        }

        if imageView!.superview == nil {
            hud!.addSubview(imageView!)
        }

        if titleLabel == nil {
            titleLabel = UILabel(frame: CGRectZero)
            titleLabel?.backgroundColor = UIColor.clearColor()
            titleLabel?.font = statusFont
            titleLabel?.textColor = statusColor
            titleLabel?.baselineAdjustment = UIBaselineAdjustment.AlignCenters
            titleLabel?.numberOfLines = 0
            titleLabel?.textAlignment = NSTextAlignment.Center
            titleLabel?.adjustsFontSizeToFitWidth = false
        }

        if titleLabel!.superview == nil {
            hud!.addSubview(titleLabel!)
        }
    }

    ///
    /// @brief 释放资源
    private func destroyProgressHUD() {
        NSNotificationCenter.defaultCenter().removeObserver(self, name: UIDeviceOrientationDidChangeNotification, object: nil)

        titleLabel?.removeFromSuperview()
        titleLabel = nil

        spinner?.removeFromSuperview()
        spinner = nil

        imageView?.removeFromSuperview()
        imageView = nil

        hud?.removeFromSuperview()
        hud = nil
    }

    ///
    /// @brief 设置方向变化通知处理
    func rotate(sender: NSNotification?) {
        var rotation: CGFloat = 0.0
        switch UIApplication.sharedApplication().statusBarOrientation {
        case UIInterfaceOrientation.Portrait:
            rotation = 0.0
            break
        case .PortraitUpsideDown:
            rotation = CGFloat(M_PI)
            break
        case .LandscapeLeft:
            rotation = -CGFloat(M_PI_2)
            break
        case .LandscapeRight:
            rotation = CGFloat(M_PI_2)
            break
        default:
            break
        }

        hud?.transform = CGAffineTransformMakeRotation(rotation)
    }

    ///
    /// @brief 调整大小
    private func addjustSize() {
        var rect = CGRectZero
        var width: CGFloat = 100.0
        var height: CGFloat = 100.0

        /// 计算文本大小
        if titleLabel!.text != nil {
            var style = NSMutableParagraphStyle()
            style.lineBreakMode = NSLineBreakMode.ByCharWrapping
            var attributes = [NSFontAttributeName: statusFont, NSParagraphStyleAttributeName: style.copy()]
            var option = NSStringDrawingOptions.UsesLineFragmentOrigin
            var text: NSString = NSString(CString: titleLabel!.text!.cStringUsingEncoding(NSUTF8StringEncoding)!,
                encoding: NSUTF8StringEncoding)
            rect = text.boundingRectWithSize(CGSizeMake(160, 260), options: option, attributes: attributes, context: nil)
            rect.origin.x = 12
            rect.origin.y = 66

            width = rect.size.width + 24
            height = rect.size.height + 80

            if width < 100 {
                width = 100
                rect.origin.x = 0
                rect.size.width = 100
            }
        }

        hud!.center = CGPointMake(kScreenWidth / 2, kScreenHeight / 2)
        hud!.bounds = CGRectMake(0, 0, width, height)

        var h = titleLabel!.text == nil ? height / 2 : 36
        imageView!.center = CGPointMake(width / 2, h)
        spinner!.center = CGPointMake(width / 2, h)

        titleLabel!.frame = rect
    }

    ///
    /// @brief 显示
    private func showHUD() {
        if self.alpha == 0.0 {
            self.alpha = 1.0

            hud!.alpha  = 0.0
            self.hud!.transform = CGAffineTransformScale(self.hud!.transform, 1.4, 1.4)
            UIView.animateKeyframesWithDuration(0.15,
                delay: 0.0,
                options: UIViewKeyframeAnimationOptions.AllowUserInteraction,
                animations: { () -> Void in
                    self.hud!.transform = CGAffineTransformScale(self.hud!.transform, 1.0 / 1.4, 1.0 / 1.4)
                    self.hud!.alpha = 1.0
                }, completion: { (isFinished) -> Void in
            })
        }
    }

    ///
    /// @brief 隐藏
    private func hideHUD() {
        if self.alpha == 1.0 {
            UIView.animateKeyframesWithDuration(0.2,
                delay: 0.0,
                options: UIViewKeyframeAnimationOptions.AllowUserInteraction,
                animations: { () -> Void in
                    self.hud!.transform = CGAffineTransformScale(self.hud!.transform, 0.35, 0.35)
                    self.hud!.alpha = 0.0
                }, completion: { (isFinished) -> Void in
                    self.destroyProgressHUD()
                    self.alpha = 0.0
            })
        }
    }

    ///
    /// @brief 在指定时间内隐藏
    func hideWhenTimeout() {
        autoreleasepool { () -> () in
            var length = countElements(self.titleLabel!.text!)
            var sleepTime: NSTimeInterval = NSTimeInterval(length) * 0.04 + 0.5
            NSThread.sleepForTimeInterval(sleepTime)

            self.hideHUD()
        }
    }
}

剩下的部分, 就需要有耐心的同学们去研究代码了,点击这里可以下载到源代码

时间: 2024-09-16 00:30:00

Swift版音乐播放器(简化版)的相关文章

基于jQuery实现歌词滚动版音乐播放器的代码_jquery

先给大家看下效果图,感兴趣的朋友可以参考实现代码 核心代码如下所示: $.ajax({ url: "/music/music.txt", type: "get", success: function(data) { data = jQuery.parseJSON(data); var length = data.length; var now=0; for (i = 0; i < length; i++) { $("#musicText li&quo

Android 开源在线音乐播放器_Android

封面图:  简介 波尼音乐是一款开源Android在线音乐播放器. 播放本地音乐与在线音乐 在线音乐排行榜,如热歌榜.新歌榜等 高仿云音乐的黑胶唱片专辑封面 歌词显示,自动搜索歌词 夜间模式 定时关闭 更新说明 v 1.0 First Release TODO 在线音乐可以免下载加入我的音乐列表 在线音乐自动缓存 编辑音乐信息 项目公开API 在线音乐:百度音乐 天气数据:高德地图 开源技术 okhttp-utils Android-Universal-Image-Loader 关键代码 黑胶唱

仿酷狗音乐播放器开发日志二十二 动态调色板控件第二版(性能大幅提升附源码)

转载请说明原出处,谢谢~~         在上次写的博客<仿酷狗音乐播放器开发日志二十一 开发动态调色板控件(附源码)>发布后,我在群里和网友讨论这个控件的性能和优 缺点,发现了他很多不足,还有很多提升空间,之后我简单的修改了代码提升了控件的响应速度.        昨天网友"风之羽翼"联系到我,他在我原来写的控件基础上,对绘图的算法进行重写,大幅提升了控件的绘制速度,算法也精准了很多,最终的控 件效果要比原酷狗更加流畅,于是今天把新的控件代码上传,供感兴趣的朋友使用.在

2015音乐播放器排行榜

  1.酷狗音乐播放器: http://www.xpgod.com/soft/75.html (KuGou播放器)是国内最大的P2P音乐共享平台,采用了P2P的先进构架设计研发,为用户设计了高传输效果的文件下载功能,通过它能实现P2P数据分享传输;系统天堂为您提供最新版的酷狗音乐播放器2015官方下载. 2.酷我音乐盒:http://www.xpgod.com/soft/5506.html 酷我音乐盒是全球第一家集音乐的发现.获取和欣赏于一体的一站式个性化音乐服务平台.它运用世界最新的技术,为用

历上最强的音乐播放器(jetA…

原文地址:历上最强的音乐播放器(jetAudio-8.0.5.320-Plus-VX-完全汉化版)下载作者:盖世天星 历上最强的音乐播放器(jetAudio-8.0.5.320-Plus-VX-完全汉化版), 别不信,拥有它,你可以向你电脑中其他播放器拜拜了."当然仅限你是音乐烧友"       想听到理想的音乐与歌曲吗?可能你与我一样,说到音乐播放软件第一想到了"千千静听"或者"酷歌音乐"再则"Winamp"等等.    

苹果-iOS开发网络音乐播放器

问题描述 iOS开发网络音乐播放器 最近想做一个网络播放器,能播放网络音乐和本地音乐,请问有什么好的框架可以用,貌似苹果自带AVAudioPlayer自能播放本地音乐 解决方案 Audioqueue可以播放网络音乐,也能播放本地音乐. 解决方案二: 网络音乐播放器ios- 音乐播放器(1)19.网络音乐播放器,,Mediaplay 解决方案三: 楼主可以上code4cpp看看,我现在搞swift都没发现有啥好用的库

仿酷狗音乐播放器开发日志二十一 开发动态调色板控件(附源码)

转载请说明原出处,谢谢~~           上一篇仿酷狗日志结束后,整个换肤功能就只剩下调色板功能没有做了,我本以为会很简单,但是研究了酷狗的调色板功能后发现不是那么简单的事情.首先看一下酷狗的调色板的样子:         我原本以为酷狗的主界面只是一张图片,然后通过鼠标坐标来选择颜色,简单粗暴.等我开始做这部分时发现情况不一样.         可以看到,酷狗的调色板分为两部分,上半部分是调色板的主界面,下半部分是调整亮度的工具栏,我这里分别给他们起名为Pallet和Bar方便说明.这个

什么样数字音乐播放器才是目前最便捷的跨平台播放器

目前两大智能终端系统的对决已趋于白热化,但对于用户来说这其实代表了更多的可选择空间,而各大厂则其实更是纷纷于两大移动平台推出了自己的产品.这一点在目前的数字音乐领域最为明显.但目前数字音乐领域存在着多家不同的音乐播放器,甚至是同一家播放器也推出了多版本的音乐播放器. 什么样数字音乐播放器才是目前最便捷的跨平台播放器呢?下面就给大家简单分析下优秀播放器的几个重点要素. 第一:安全 众所周知的原因,安卓手机具备很多不安全的因素,各种木马.乱扣费借着客户端在手机上大行其道,吸引流量.扣话费,等等暗箱操

七大主流Android音乐播放器横向评测

核心功能对比随着智能手机和3G网络的普及,移动互联网日益成为人们生活娱乐的重心之一.在音乐领域,竞争也十分激烈,在PC之后,几大提供音乐服务的厂商正在加紧占据手机客户端.本期我们在 Android平台挑选了七家国内主流音乐播放器进行评测,主要针对核心功能.操作体验.曲库丰富程度.应用细节几方面进行横向对比.这七家主流音乐播放器分别是多米音乐.QQ音乐.酷我音乐.虾米音乐.酷狗音乐.天天动听和百度ting.以下是评测详情: 一.核心功能对比1.整合本地音乐本地音乐仍然是Android音乐播放器不可