Skip to content
This repository has been archived by the owner on Aug 23, 2024. It is now read-only.

Commit

Permalink
Update README.md
Browse files Browse the repository at this point in the history
  • Loading branch information
Moriafly committed Feb 1, 2021
1 parent 7742ecc commit 636add7
Show file tree
Hide file tree
Showing 18 changed files with 117 additions and 88 deletions.
1 change: 1 addition & 0 deletions .idea/dictionaries/24568.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Kotlin 开发的美观的安卓音乐软件。本软件仅由开发者提供的

# 声明

软件安装包不接受他人的任何转发(发布到其他应用、推广网站、公众号、博客等)。
### `软件安装包不接受他人的任何转发(发布到其他应用、推广网站、公众号、博客等)。`

# 应用下载

Expand Down
2 changes: 1 addition & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ android {
applicationId "com.dirror.music"
minSdkVersion 21
targetSdkVersion 30
versionCode 313
versionCode 314
versionName "2.6.1"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import com.dirror.music.data.PLAYLIST_TAG_NORMAL
import com.dirror.music.music.standard.data.StandardSongData
import com.dirror.music.ui.activity.PlayerActivity
import com.dirror.music.ui.dialog.SongMenuDialog
import com.dirror.music.util.Config
import com.dirror.music.util.parseArtist
import com.dirror.music.util.toast

Expand All @@ -36,6 +37,8 @@ class DetailPlaylistAdapter
val tvName: TextView = view.findViewById(R.id.tvName)
val tvArtist: TextView = view.findViewById(R.id.tvArtist)
val ivMore: ImageView = view.findViewById(R.id.ivMore)

val isAnimation = MyApplication.mmkv.decodeBool(Config.PLAYLIST_SCROLL_ANIMATION, true)
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
Expand All @@ -47,7 +50,9 @@ class DetailPlaylistAdapter
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.apply {
// 动画
clSong.animation = AnimationUtils.loadAnimation(holder.itemView.context, R.anim.anim_recycle_item)
if (isAnimation) {
clSong.animation = AnimationUtils.loadAnimation(holder.itemView.context, R.anim.anim_recycle_item)
}
// 获取当前 song
val song = songDataList[position]
if (song.neteaseInfo?.pl == 0) {
Expand Down
101 changes: 47 additions & 54 deletions app/src/main/java/com/dirror/music/music/local/LocalMusic.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,39 @@ package com.dirror.music.music.local

import android.app.Activity
import android.content.ContentResolver
import android.content.ContentUris
import android.content.Context
import android.database.Cursor
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.media.MediaMetadataRetriever
import android.net.Uri
import android.provider.MediaStore
import androidx.core.content.ContextCompat
import androidx.core.graphics.drawable.toBitmap
import com.dirror.music.MyApplication
import com.dirror.music.R
import com.dirror.music.music.standard.data.SOURCE_LOCAL
import com.dirror.music.music.standard.data.StandardSongData
import com.dirror.music.music.standard.data.StandardSongData.LocalInfo
import com.dirror.music.music.standard.data.StandardSongData.StandardArtistData
import com.dirror.music.util.Config
import com.dirror.music.util.toast
import java.io.*
import java.net.URL

import java.lang.Exception

/**
* 本地音乐
*/
object LocalMusic {

fun scanLocalMusic(activity: Activity, success: (ArrayList<StandardSongData>) -> Unit, failure: () -> Unit) {


val songList = ArrayList<StandardSongData>()

val resolver: ContentResolver = activity.contentResolver
val uri = android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
val uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
// val songSortOrder = MediaStore.Audio.Media.DEFAULT_SORT_ORDER
val cursor: Cursor? = resolver.query(uri, null, null, null, null)
when {
cursor == null -> {
Expand All @@ -38,21 +48,27 @@ object LocalMusic {
failure.invoke()
}
else -> {
val titleColumn: Int = cursor.getColumnIndex(android.provider.MediaStore.Audio.Media.TITLE)
val idColumn: Int = cursor.getColumnIndex(android.provider.MediaStore.Audio.Media._ID)
val artistColumn: Int = cursor.getColumnIndex(android.provider.MediaStore.Audio.Media.ARTIST)
val titleColumn: Int = cursor.getColumnIndex(MediaStore.Audio.Media.TITLE)
val idColumn: Int = cursor.getColumnIndex(MediaStore.Audio.Media._ID)
val artistColumn: Int = cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST)

val dataColumn: Int = cursor.getColumnIndex(android.provider.MediaStore.Audio.Media.DATA)
val dataColumn: Int = cursor.getColumnIndex(MediaStore.Audio.Media.DATA)
val albumIdColumn = cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID)
// val albumArtColumn = cursor.getColumnIndex("album_art")
// val bitrateColumn: Int = cursor.getColumnIndex(android.provider.MediaStore.Audio.Media.BITRATE) // 码率
val sizeColumn: Int = cursor.getColumnIndex(android.provider.MediaStore.Audio.Media.SIZE) // 码率
val sizeColumn: Int = cursor.getColumnIndex(MediaStore.Audio.Media.SIZE) // 大小
// val titleColumn: Int = cursor.getColumnIndex(android.provider.MediaStore.Audio.Media.VOLUME_NAME)
do {
val id = cursor.getLong(idColumn) // 音乐 id
val path = cursor.getString(dataColumn)
val dataPath = cursor.getString(dataColumn)
val albumId = cursor.getLong(albumIdColumn) // 专辑 id
val title = cursor.getString(titleColumn) // 音乐名称
var artist = cursor.getString(artistColumn) // 艺术家
// val bitrate = cursor.getString(bitrateColumn)
// val bitrate = cursor.getLong(bitrateColumn)
val size = cursor.getLong(sizeColumn)


val coverUri = getAlbumCover(albumId)
// 过滤无法播放的歌曲
if (title == "" && artist == "<unknown>") {
continue
Expand Down Expand Up @@ -89,7 +105,7 @@ object LocalMusic {
SOURCE_LOCAL,
id.toString(),
title,
path,
coverUri.toString(),
artistList,
null,
LocalInfo(size),
Expand All @@ -106,53 +122,30 @@ object LocalMusic {

}

/**
* 得到本地或者网络上的bitmap url - 网络或者本地图片的绝对路径,比如:
* A.网络路径: url="http://blog.foreverlove.us/girl2.png" ;
* B.本地路径: url="file://mnt/sdcard/photo/image.png";
* C.支持的图片格式 png jpg bmp gif 等等
* @param url
* @return
*/
@JvmStatic
fun getLocalOrNetBitmap(url: String?): Bitmap? {
val inputStream: InputStream?
val bufferedOutputStream: BufferedOutputStream?

return try {
inputStream = BufferedInputStream(URL(url).openStream(), 1024)

val dataStream = ByteArrayOutputStream()
bufferedOutputStream = BufferedOutputStream(dataStream, 1024)
private fun getAlbumCover(albumId: Long): Uri {
return ContentUris.withAppendedId(Uri.parse("content://media/external/audio/albumart"), albumId);
}

copy(inputStream, bufferedOutputStream)
bufferedOutputStream.flush()
/**
* 从 Uri 获取音乐
* @param albumUri 专辑封面
*/
fun getBitmapFromUir(context: Context, albumUri: Uri): Bitmap? {
val `in`: InputStream?
var bmp: Bitmap? = null
try {
`in` = context.contentResolver.openInputStream(albumUri)
val sBitmapOptions = BitmapFactory.Options()
bmp = BitmapFactory.decodeStream(`in`, null, sBitmapOptions)
`in`?.close()
} catch (e: Exception) {

val data = dataStream.toByteArray()
BitmapFactory.decodeByteArray(data, 0, data.size)
} catch (e: IOException) {
e.printStackTrace()
null
}

}

@Throws(IOException::class)
private fun copy(inputStream: InputStream, out: OutputStream) {
val bytes = ByteArray(1024)
var read: Int
while (inputStream.read(bytes).also { read = it } != -1) {
out.write(bytes, 0, read)
if (bmp == null) {
bmp = ContextCompat.getDrawable(context, R.drawable.bq_no_data_song)?.toBitmap()
}
}

fun loadCover(path: String): Bitmap {
val mediaMetadataRetriever = MediaMetadataRetriever()
mediaMetadataRetriever.setDataSource(path)
val cover = mediaMetadataRetriever.embeddedPicture
val bitmap = BitmapFactory.decodeByteArray(cover, 0, cover!!.size)
// image.setImageBitmap(bitmap)
return bitmap
return bmp
}

}
39 changes: 25 additions & 14 deletions app/src/main/java/com/dirror/music/music/standard/SongPicture.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
package com.dirror.music.music.standard

import android.annotation.SuppressLint
import android.content.ContentResolver
import android.content.ContentUris
import android.content.Context
import android.database.Cursor
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
import androidx.core.content.ContextCompat
import androidx.core.graphics.drawable.toBitmap
import androidx.core.net.toUri
import com.dirror.music.MyApplication
import com.dirror.music.R
import com.dirror.music.api.API_FCZBL_VIP
Expand All @@ -11,25 +19,30 @@ import com.dirror.music.music.standard.data.*
import com.dirror.music.util.GlideUtil
import com.dirror.music.util.dp
import com.dirror.music.util.loge
import com.dirror.music.util.toast
import org.jetbrains.annotations.TestOnly
import java.io.FileDescriptor
import java.io.FileNotFoundException
import java.io.IOException
import java.io.InputStream

object SongPicture {

const val TYPE_LARGE = 1
const val TYPE_SMALL = 2


/**
* 标准
*/
@SuppressLint("UseCompatLoadingForDrawables")
// @Deprecated("过时,等待新方法")
fun getSongPicture(songData: StandardSongData, type: Int, success: (Bitmap) -> Unit) {
fun getSongPicture(context: Context, songData: StandardSongData, type: Int, success: (Bitmap) -> Unit) {
// 普通背景
if (songData.source == SOURCE_LOCAL) {
val commonBitmap: Bitmap? = MyApplication.context.getDrawable(R.drawable.bq_no_data_song)?.toBitmap()
if (commonBitmap != null) {
success.invoke(commonBitmap)
songData.imageUrl?.let {
LocalMusic.getBitmapFromUir(context, it.toUri())?.let { it1 ->
success(it1)
}
}
} else {
val url = getSongPictureUrl(songData, type)
Expand Down Expand Up @@ -61,7 +74,7 @@ object SongPicture {
"https://y.gtimg.cn/music/photo_new/T002R300x300M000${songData.imageUrl as String}.jpg?max_age=2592000"
}
SOURCE_KUWO -> {
songData.imageUrl?:""
songData.imageUrl ?: ""
}
else -> {
"https://s4.music.126.net/style/web2/img/default/default_album.jpg"
Expand All @@ -75,12 +88,13 @@ object SongPicture {
*/
@SuppressLint("UseCompatLoadingForDrawables")
@TestOnly
fun getPlayerActivityCoverBitmap(songData: StandardSongData, size: Int, success: (Bitmap) -> Unit) {
when(songData.source) {
fun getPlayerActivityCoverBitmap(context: Context, songData: StandardSongData, size: Int, success: (Bitmap) -> Unit) {
when (songData.source) {
SOURCE_NETEASE -> {
loge("getPlayerActivityCoverBitmap网易云图片原url【${songData.imageUrl}")
val url = if (songData.imageUrl == "https://p2.music.126.net/6y-UleORITEDbvrOLV0Q8A==/5639395138885805.jpg"
|| songData.imageUrl == "https://p1.music.126.net/6y-UleORITEDbvrOLV0Q8A==/5639395138885805.jpg") {
|| songData.imageUrl == "https://p1.music.126.net/6y-UleORITEDbvrOLV0Q8A==/5639395138885805.jpg"
) {
"$API_FCZBL_VIP/?type=cover&id=${songData.id}"
} else {
"${songData.imageUrl}?param=${size}y${size}"
Expand Down Expand Up @@ -108,13 +122,10 @@ object SongPicture {
}
SOURCE_LOCAL -> {
songData.imageUrl?.let {
try {
val bitmap = LocalMusic.loadCover(it)
val bitmap = LocalMusic.getBitmapFromUir(context, it.toUri())
if (bitmap != null) {
success.invoke(bitmap)
} catch (e: Exception) {

}

}
}
else -> {
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/java/com/dirror/music/service/MusicService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -780,7 +780,7 @@ class MusicService : Service() {
.setMediaSession(mediaSession?.sessionToken)
.setShowActionsInCompactView(0, 1, 2)
if (song != null) {
SongPicture.getPlayerActivityCoverBitmap(song, 100.dp()) { bitmap ->
SongPicture.getPlayerActivityCoverBitmap(this, song, 100.dp()) { bitmap ->
showNotification(mediaStyle, song, bitmap)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ class LocalMusicActivity : AppCompatActivity() {
MyApplication.musicBinderInterface?.getNowSongData()?.let { standardSongData ->
binding.includePlayer.tvName.text = standardSongData.name
binding.includePlayer.tvArtist.text = standardSongData.artists?.let { parseArtist(it) }
SongPicture.getSongPicture(standardSongData, SongPicture.TYPE_LARGE) {
SongPicture.getSongPicture(this, standardSongData, SongPicture.TYPE_LARGE) {
binding.includePlayer.ivCover.setImageBitmap(it)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ class MainActivity : AppCompatActivity() {
}

// 适配导航栏
val navigationBarHeight = if (MyApplication.mmkv.decodeBool(Config.PARSE_HOME_NAVIGATION, true)) {
val navigationBarHeight = if (MyApplication.mmkv.decodeBool(Config.PARSE_NAVIGATION, true)) {
getNavigationBarHeight(this)
} else {
0
Expand Down Expand Up @@ -248,7 +248,7 @@ class MainActivity : AppCompatActivity() {
binding.includePlayer.tvName.text = song.name
binding.includePlayer.tvArtist.text = song.artists?.let { parseArtist(it) }
// 这里应该用小的,等待修改
SongPicture.getSongPicture(song, SongPicture.TYPE_LARGE) {
SongPicture.getSongPicture(this@MainActivity, song, SongPicture.TYPE_LARGE) {
binding.includePlayer.ivCover.setImageBitmap(it)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ class PlayHistoryActivity : AppCompatActivity() {
binding.miniPlayer.tvName.text = song.name
binding.miniPlayer.tvArtist.text = song.artists?.let { parseArtist(it) }
// 这里应该用小的,等待修改
SongPicture.getSongPicture(song, SongPicture.TYPE_LARGE) {
SongPicture.getSongPicture(this@PlayHistoryActivity, song, SongPicture.TYPE_LARGE) {
binding.miniPlayer.ivCover.setImageBitmap(it)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ class PlayerActivity : SlideBackActivity() {
parseArtist(artists)
}
// val url = MyApplication.cloudMusicManager.getPicture(imageUrl, CD_SIZE.dp())
SongPicture.getPlayerActivityCoverBitmap(it, CD_SIZE.dp()) { bitmap ->
SongPicture.getPlayerActivityCoverBitmap(this@PlayerActivity, it, CD_SIZE.dp()) { bitmap ->
// 设置 CD 图片
binding.ivCover.setImageBitmap(bitmap)
// 设置 背景 图片
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ import com.dirror.music.util.GlideUtil
import com.google.gson.Gson
import jp.wasabeef.glide.transformations.BlurTransformation
import java.lang.Exception
import kotlin.system.measureTimeMillis

/**
* 歌单 Activity
Expand Down Expand Up @@ -78,7 +77,7 @@ class PlaylistActivity : AppCompatActivity() {
(binding.titleBar.layoutParams as ConstraintLayout.LayoutParams).apply {
topMargin = getStatusBarHeight(window, this@PlaylistActivity)
}
val navigationHeight = if (MyApplication.mmkv.decodeBool(Config.PARSE_HOME_NAVIGATION, true)) {
val navigationHeight = if (MyApplication.mmkv.decodeBool(Config.PARSE_NAVIGATION, true)) {
getNavigationBarHeight(this)
} else {
0
Expand Down Expand Up @@ -249,7 +248,7 @@ class PlaylistActivity : AppCompatActivity() {
MyApplication.musicBinderInterface?.getNowSongData()?.let { standardSongData ->
binding.includePlay.tvName.text = standardSongData.name
binding.includePlay.tvArtist.text = standardSongData.artists?.let { parseArtist(it) }
SongPicture.getSongPicture(standardSongData, SongPicture.TYPE_LARGE) {
SongPicture.getSongPicture(this, standardSongData, SongPicture.TYPE_LARGE) {
binding.includePlay.ivCover.setImageBitmap(it)
}
}
Expand Down
Loading

0 comments on commit 636add7

Please sign in to comment.