众所周知(屁),Easy163通过拦截网易云的流量请求,从而实现一些比较NB的效果,比如无版权歌曲下载和付费歌曲下载。可是笔者更喜欢用倒带,而Easy163却不支持倒带,于是决定自己来试试适配倒带。
适配倒带
先在Github仓库搜下网易云的包名,结果如下:
吆西,AS启动!
打开LocalVPNServices.java,定位到如下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { try { builder.addAllowedApplication("com.netease.cloudmusic"); }catch (PackageManager.NameNotFoundException e) { Log.d(TAG, "未检测到网易云音乐"); } try { builder.addAllowedApplication("com.netease.cloudmusic.lite"); }catch (PackageManager.NameNotFoundException e) { Log.d(TAG, "未检测到网易云音乐极速版"); } }
|
在这一段结尾加上倒带包名:
1 2 3 4 5 6 7 8
| try { builder.addAllowedApplication("com.kuss.rewind"); } catch (PackageManager.NameNotFoundException e) { Log.d(TAG,"未检测到倒带"); }
|
然后就是对数据包的处理了,这里本来是想着播放列表的请求也要拦截的,最好发现倒带对歌曲播放链接的请求机制和网易云不太一样,于是放弃对Playlist.java的修改,直接修改SongPlayHook.java。之间又发现一个小细节,倒带的请求头host是小写,而网易云请求头Host是大写,就因为这个小细节不知道浪费了我多少时间…
在SongPlayHook.java的请求判断加上下面的代码:
1 2 3 4 5 6 7 8 9
| if(host != null) { if(method.equals("GET") && host.endsWith("music.163.com") && path.contains("/song/enhance/player/url")) { Log.d("check rule","Rewind"); isRewind = true; return true; } }
|
同时,倒带的请求没有AES加密,而网易云都有AES加密,所以在hookResponse方法内加上判断,如果是倒带的请求则不采用AES加解密,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| super.hookResponse(response); byte[] bytes = response.getContent(); Log.d("ResponseSong:",new String(bytes)); if (!isRewind) { bytes = Crypto.aesDecrypt(bytes); } JSONObject jsonObject = JSONObject.parseObject(new String(bytes)); handleNoFreeSong(jsonObject); bytes = JSONObject.toJSONString(jsonObject, SerializerFeature.WriteMapNullValue).getBytes(); if(!isRewind) { bytes = Crypto.aesEncrypt(bytes); } Log.d("ResponseSong hooked:",new String(bytes)); response.setContent(bytes); }
|
其中的isRewind是在BaseHook.java添加的布尔值变量。
还有一个小问题,倒带的请求结果JSON与网易云的也有区别,比如data数组里请求码套在了外面,所以还要在handleNoFreeSong方法里加上判断,代码跟上面判断差不多,就不放了。
看下效果:
添加通知栏快捷设置
这个应该比上面的简单一点。新建类QuickTileService继承自TileService。由于Service内不能直接创建新VPN,所以要先判断是否已经创建过,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| public void onClick() { super.onClick(); Tile tile = getQsTile(); int State = tile.getState(); if(State == Tile.STATE_INACTIVE) { Intent vpnIntent = VpnService.prepare(this); if (vpnIntent != null) { Intent intent = new Intent(this, MainActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); Toast.makeText(this,"请先在软件内开启一次VPN!",Toast.LENGTH_LONG).show(); return; } else { Intent intent = new Intent(this, LocalVPNService.class); startService(intent); } tile.setState(Tile.STATE_ACTIVE); } else { Intent intent = new Intent("activity"); intent.putExtra("cmd", "stop"); LocalBroadcastManager.getInstance(this).sendBroadcast(intent); Log.d("stopVPN"); } }
|
然后在AndroidManifest.xml里面添加服务,代码如下:
1 2 3 4 5 6 7 8 9 10
| <service android:name=".utils.QuickTileService" android:label="@string/app_name" android:icon="@drawable/ic_netease_cloud_music" android:permission="android.permission.BIND_QUICK_SETTINGS_TILE"> <intent-filter> <action android:name="android.service.quicksettings.action.QS_TILE"/> </intent-filter> <meta-data android:name="android.service.quicksettings.ACTIVE_TILE" android:value="true"/> </service>
|
编译运行看一下效果:
效果还不错,然后就可以正式打包成APK文件了。
结尾
写这篇文章加上写代码总共花了大半天时间吧,更改后的代码我会放在GitHub,并且尝试合并到原作者的项目。
下载地址:点这里
安装不上的请先卸载旧版本
已知Bug:部分情况下网易云会无法播放歌曲,清除缓存即可还是用原版吧。
都看到这里了,还不去酷安给个三连支持一下?