APlayer icon indicating copy to clipboard operation
APlayer copied to clipboard

[Feature Discuss]修改专辑封面到底应该修改什么?

Open cyanlink opened this issue 5 years ago • 7 comments

现在APlayer在这个功能上的实现表现很奇怪。

用例1:

  • 打开“忽视MediaStore缓存”。
  • 修改某个带有多首歌曲的专辑的封面

预期结果:

  • 这张专辑所有的歌曲都应该显示这个新的自定义封面。

实际结果:

  • 专辑中只有某首乐曲被修改了封面,且从外层界面看是新的封面,其他仍然保持内嵌。

用例2:

  • 在用例1的基础上,关闭“忽视MediaStore缓存”,然后杀死Activity,冷启动APlayer。

  • (如果Merge了我的PR)发现专辑下所有歌曲封面统一为自定义封面。

  • 但是,如果再将“忽视MediaStore缓存”打开,结果与用例1相同。

  • 那个唯一的被修改了封面的某首乐曲的Tag被永久更改了,而其他同专辑乐曲并未级联更改。

这种实现上的不一致性个人认为是需要解决的。

cyanlink avatar Oct 19 '20 08:10 cyanlink

@cyanlink 忽略媒体缓存,读取的就是歌曲的内嵌封面,完全有可能两首歌是同一专辑,但是用户分别修改了他们的内嵌封面。 而自定义封面如你所说,修改的是整个专辑的封面。

rRemix avatar Oct 19 '20 08:10 rRemix

@rRemix 那么依旧存在一个问题,打开“忽略MediaStore缓存”,先修改某个专辑的封面,然后尝试修改这个专辑下没有显示成新封面的单独乐曲的封面,冷重启APlayer之后,这个单独乐曲封面并未生效,还是老的内嵌封面。等于:一个专辑下,只有一首能被设置成自定义封面,而且不受控制,剩下的铁打不动是老内嵌封面,不听用户设置。还是存在行为不一致性。 按照你说的意思我总结一下behavior你看对不对:

  • 忽略MS缓存开启 ——>只去优先读取每首歌曲的内嵌封面。
  • 用户修改封面——>修改单首歌曲的内嵌封面。//这点目前就是上面说的那个问题。
  • 忽略MS缓存关闭——>读取用户设定的“全专辑”封面,应用到每首歌曲。

也就是说,内嵌封面是内嵌封面,是文件自带的;而我们的“软封面”是APlayer自己的cacheDir里存的缓存,那用户修改封面这个功能又去修改了内嵌封面,又影响了“软封面”,而且如上述,这个功能实现还有问题(尚未定位)。

而且在API 30,google已经不让我们直接访问MediaStore的AlbumArt那个Column了,可能读写权限都不给了(没有测试),我猜hack底层content://往albumarts里直接insert values可能都不行了;只能通过一个函数拿到thumbnail。我猜测这么做的用意就是让我们一切听从内嵌?到时候我们该怎么实现呢?

cyanlink avatar Oct 19 '20 09:10 cyanlink

关键问题出在MediaStoreUtil.saveArtwork这里。这个函数的行为解释了我上面列出的所有问题。

  @WorkerThread
  public static void saveArtwork(Context context, long albumId, File artFile)
      throws TagException, ReadOnlyFileException, CannotReadException, InvalidAudioFrameException, IOException, CannotWriteException {
    Song song = MediaStoreUtil.getSongByAlbumId(albumId);//这里面只返回了一个象征AlbumID的一个歌曲实例,取songs[0]
    if (song == null) {
      return;
    }
    AudioFile audioFile = AudioFileIO.read(new File(song.getUrl()));
    Tag tag = audioFile.getTagOrCreateAndSetDefault();
    Artwork artwork = ArtworkFactory.createArtworkFromFile(artFile);
    tag.deleteArtworkField();
    tag.setField(artwork);//这里也就只修改了这一个用户无法控制具体是哪个的、象征这个专辑的歌曲实例的Tag
    audioFile.commit();
    insertAlbumArt(context, albumId, artFile.getAbsolutePath());//这里又往MediaStore数据库里写“缓存”,其index是每个albumID
  }

我估计您当时实现的时候思路混乱了。

cyanlink avatar Oct 19 '20 09:10 cyanlink

关键问题出在MediaStoreUtil.saveArtwork这里。这个函数的行为解释了我上面列出的所有问题。

  @WorkerThread
  public static void saveArtwork(Context context, long albumId, File artFile)
      throws TagException, ReadOnlyFileException, CannotReadException, InvalidAudioFrameException, IOException, CannotWriteException {
    Song song = MediaStoreUtil.getSongByAlbumId(albumId);//这里面只返回了一个象征AlbumID的一个歌曲实例,取songs[0]
    if (song == null) {
      return;
    }
    AudioFile audioFile = AudioFileIO.read(new File(song.getUrl()));
    Tag tag = audioFile.getTagOrCreateAndSetDefault();
    Artwork artwork = ArtworkFactory.createArtworkFromFile(artFile);
    tag.deleteArtworkField();
    tag.setField(artwork);//这里也就只修改了这一个用户无法控制具体是哪个的、象征这个专辑的歌曲实例的Tag
    audioFile.commit();
    insertAlbumArt(context, albumId, artFile.getAbsolutePath());//这里又往MediaStore数据库里写“缓存”,其index是每个albumID
  }

我估计您当时实现的时候思路混乱了。

这个地方确实是,不应该去修改内嵌或者MS,毕竟是自定义的,应该是app自有的封面。我当时好像是听了用户的建议,设置封面的时候就直接修改了内嵌和MS了,这样哪怕app删了或者清除了数据,以前设置的封面还能有效。

rRemix avatar Oct 19 '20 09:10 rRemix

关键问题出在MediaStoreUtil.saveArtwork这里。这个函数的行为解释了我上面列出的所有问题。

  @WorkerThread
  public static void saveArtwork(Context context, long albumId, File artFile)
      throws TagException, ReadOnlyFileException, CannotReadException, InvalidAudioFrameException, IOException, CannotWriteException {
    Song song = MediaStoreUtil.getSongByAlbumId(albumId);//这里面只返回了一个象征AlbumID的一个歌曲实例,取songs[0]
    if (song == null) {
      return;
    }
    AudioFile audioFile = AudioFileIO.read(new File(song.getUrl()));
    Tag tag = audioFile.getTagOrCreateAndSetDefault();
    Artwork artwork = ArtworkFactory.createArtworkFromFile(artFile);
    tag.deleteArtworkField();
    tag.setField(artwork);//这里也就只修改了这一个用户无法控制具体是哪个的、象征这个专辑的歌曲实例的Tag
    audioFile.commit();
    insertAlbumArt(context, albumId, artFile.getAbsolutePath());//这里又往MediaStore数据库里写“缓存”,其index是每个albumID
  }

我估计您当时实现的时候思路混乱了。

整个函数都是不需要的,保存了自定义封面就只需要刷新就行了。这个函数应该是用于编辑标签的时候,编辑内嵌封面的。

rRemix avatar Oct 19 '20 09:10 rRemix

@rRemix 我找到这个函数就是因为之前弹出Toast里说octet-stream cannot be inserted……,然后通过/audio/albumart那个URI找到的,现在“修改专辑封面”的确会调用这个。换句话说,这函数操作不正交,有副作用hhhh

cyanlink avatar Oct 19 '20 10:10 cyanlink

@rRemix 我找到这个函数就是因为之前弹出Toast里说octet-stream cannot be inserted……,然后通过/audio/albumart那个URI找到的,现在“修改专辑封面”的确会调用这个。换句话说,这函数操作不正交,有副作用hhhh

已经提交了。现在的表现应该正常了。

rRemix avatar Oct 19 '20 11:10 rRemix