全民k歌如何升级怎么升级

热门搜索:
您的位置: -&
软件教程分类查找
非常抱歉!2345软件大全没能为您提供完善服务,万分感谢能得到您的指点!
您的建议:
精品软件课程
人气:4791968
photoshop教程让你从入门到精通,从新手快
人气:1320606
Excel是office的重要组成部分。多特Excel教
人气:3946117
WPS是金山公司的中文办公软件,包含文字,
人气:306957
Word是由Microsoft公司出版的文字处理器应
小游戏推荐
教程周榜教程总榜
12345678910
全民k歌怎么升级
出处:2345软件大全
人气:11571
核心提示:全民k歌怎么升级?一起看看吧!
  全民k歌等级怎么快速提升?全民k歌是一款由腾讯公司出品的,目前已经开放了下载。经过小编简单的试用,发现了全民k歌等级系统,那么小编接下来就给大家带来全民k歌等级快速提升攻略,希望可以帮助到大家。  1.智能打分,多唱多练  动听的歌声是快速升级的前提,多用全民k歌来练练歌把。  2.好歌配好图  给作品配上好看的封面吸引跟多人来看你的作品。  3.让好友来加油  多发表作品并分享给好友,让好友都来给你加油。  4.积极互动  积极和好友、粉丝互动,争取大家的支持。  目前来说全民k歌等级可以通过以上的方法来提升并没有更多捷径,所以想要快速升级就多来全民k歌唱歌吧,我们的作品多了,试听你歌曲的人多了,你的等级自然就会提升了。
相关教程推荐
相关软件推荐
资源统计:无插件软件:96591个 无病毒软件:96893个 昨日已处理135个带插件、病毒的软件
本站总软件:96893个 软件总下载次数:22.46亿次
软件教程文章:100944篇 总浏览次数:3.233亿次全民k歌等级怎么分_全民k歌怎么刷等级 提升等级技巧
全民k歌怎么升级快?首先呢,为大家介绍一下全民k歌的等级划分。
全民k歌等级怎么分?
评分级别分别为,SSS,SS,S,A,B,C,D。音准越高评级越高。
平均单句得分&=90 sss
平均单句得分&=80 ss
平均单句得分&=70 s
平均单句得分&=60 A
全民k歌怎么刷等级 提升等级技巧
等级根据用户获得的积分总数而定,积分与用户作品获得的关注度相关。用户发布的作品的被播放次数、获得的评论量、获得的鲜花数量越多,其总积分越高。
1,多唱一些歌,尽量拿高分。
2,每天登陆也能升级,只是不多。
3,多评论和互动。
4,关注更多人,并且尽量互粉,这样别人才能来听你的歌。(最好不要关注那些粉丝很多的人,因为他们不会互粉)。
以上就是小编的方法。。
热门安卓游戏排行
类别:休闲游戏
类别:休闲游戏
类别:角色扮演
47644人推荐55960人推荐65424人推荐75212人推荐84965人推荐94915人推荐104818人推荐
最新安卓游戏排行
类别:休闲游戏
类别:动作游戏
类别:动作游戏
40人推荐50人推荐60人推荐70人推荐80人推荐90人推荐100人推荐全民K歌增量升级方案_QQ音乐技术团队_传送门
全民K歌增量升级方案
QQ音乐技术团队
  本文主要介绍一种增量升级方案。用户在升级版本时,不需要下载完整的安装包,只需下载增加的部分即可体验新版本完整功能,即节约用户流量,也减少服务器流量,并解决了多渠道问题,值得尝试。一、背景  随着全民K歌版本不断迭代,安装包大小也不断增大,现在每次版本更新,用户都需要下载最新版本安装包,如果使用增量更新的方式,用户每次更新只下载新版本和旧版本差异的部分,将会为用户和服务器节约大量流量。以全民K歌3.2和3.3版本为例:| 文件名
| 文件大小 ||———-
|| karaoke_3.2.apk
| 30.4M || karaoke_3.3.apk
| 27.6M || 3.2_3.3.patch
|  3.2_3.3.patch文件是3.2和3.3版本的差异部分,大小为7.3M,如果用户使用增量升级方案,相对于下载完整的3.3版本27.6M,用户将节约20.3M。下面我将介绍如何使用用户本地已安装的版本karaoke_3.2.apk + 差异包3.2_3.3.patch生成最新版本karaoke_3.3.apk。二、实现原理1、服务器端:2、客户端:  增量更新的原理是将旧版本的apk和新版本的apk进行二进制对比,得到差异包,用户升级更新时,根据本地版本从服务器下载需要的差分包,使用本地版本+差分包生成新版apk。而差异包需要提前由服务器生成,用户在升级时,服务器根据用户当前版本下发差异包。列如:用户从全民K歌3.2版本升级到3.3版本,需要从服务器下载差异包(3.2_3.3.patch),再使用用户正在使用的全民K歌3.2版本apk(karaoke_3.2.apk),即可生成全民K歌3.3版本(karaoke_3.3.apk)。三、实现步骤1、生成差异包  apk文件的差分和合并都是使用的开源的二进制比较工具 bsdiff 实现。下载的bsdiff-4.3版本中有几个文件,其中bsdiff.c用于生成差异包的源码,bspatch.c用于合成apk的源码,makefile是生成可执行文件的脚本。亲测在linux系统中,执行makefile文件,可生成一个bsdiff工具,使用该工具即可生成差异包。  在服务器端使用bsdiff工具生成差异包。其中karaoke_3.2.apk和karaoke_3.3.apk是我们的老版本和新版本安装包(都未写入渠道号)。在命令行执行./bsdiff karaoke_3.2.apk karaoke_3.3.apk 3.2_3.3.patch 命令即可生成差异包3.2_3.3.patch。2、解决多渠道问题(1)多渠道说明  多渠道是指根据不同的市场打不同的安装包包,比如应用宝,安卓市场,百度市场,Google市场,360市场等等。分渠道打包目的是为了针对不同市场做出不同的一些统计,数据分析,收集用户信息。多渠道的实现通常是在生成安装包的时候,把渠道号写入安装包的渠道文件中,用户在使用app时,读取安装包的渠道文件内容,并上传服务器。例如应用宝渠道,则在安装包中有一个qua.ini文件,里面内容是YYB_D,用户在使用APP时,读取qua.ini文件内容,把YYB_D上传服务器。  由实现原理可以看出,服务器端需要两个安装包对比,然后才能生成差异包。在生成安装包的时候,不同渠道的安装包内容是不一样的(文件md5值不一样),不同渠道的新老版本生成的差异包也不一样。解决这个问题比较粗暴的方案是:每个渠道都生成一个差异包,客户端合成的时候,根据用户使用的渠道安装包下载对应渠道的差异包,再合成对应渠道最新的安装包。这时如果有50个渠道,就需要50个差异包,这个方案实现复杂,不利于差异包的维护。  这里微信团队提出了另一种实现方案:把渠道号写入安装包的注释字段。该方案不会破坏安装包,经验证,android手机可以正常安装使用。Android apk安装包是zip格式文件,在zip文件的最后有一个记录说明。格式如下:  从表中可以看出,在文件的末尾有两个字段:Comment length和Comment,分别表示注释长度(2个字节)和注释内容(N个字节)。apk安装包打包完成后, Comment length默认为0,comment为空,我们可以把入渠道号写入comment字段。app启动后,读取Comment内容即可获取渠道号。(2)安装包未写入渠道号时:  从图中可以看出,Comment length=0,说明这个安装包未写入任何注释。在使用gradle编译打包生成的apk默认是没有写入任何注释信息的。(3)安装包写入应用宝(YYB_D)渠道号时:  从图中可以看出,Comment length=12,说明这个安装包的注释长度为12个字节。(为了方便定位渠道号,除了渠道号,在文件末尾多写了7个字节内容)12 = 5 + 2 + 5 { 5个字节渠道号(YYB_D)+ 2个字节的MAGIC字符长度说明 + 5个字节的MAGIC(!ZXK!)}。(4)写渠道号关键代码:// ZIP文件注释长度字段和MAGIC的字节数
static final int SHORT_LENGTH = 2;
//注释字符编码
static final String UTF_8 = "UTF-8";
// 文件最后用于定位的MAGIC字节
static final byte[] MAGIC = new byte[]{0x21, 0x5a, 0x58, 0x4b, 0x21}; //!ZXK!
//写入渠道号
public static void writeQUA(File file, String comment) throws IOException {
byte[] data = comment.getBytes(UTF_8);
final RandomAccessFile raf = new RandomAccessFile(file, "rw");
//定位到文件有效内容的末尾(文件长度-注释长度)
raf.seek(file.length() - SHORT_LENGTH);
//写入注释字节数{注释字节数+2(MAGIC长度说明)+MAGIC长度}
writeShort(data.length + SHORT_LENGTH + MAGIC.length, raf);
//写入注释内容
writeBytes(data, raf);
//写入MAGIC字节数
writeShort(data.length, raf);
//写入MAGIC
writeBytes(MAGIC, raf);
raf.close();
private static void writeBytes(byte[] data, DataOutput out) throws IOException {
out.write(data);
private static void writeShort(int i, DataOutput out) throws IOException {
ByteBuffer bb = ByteBuffer.allocate(SHORT_LENGTH).order(ByteOrder.LITTLE_ENDIAN);
bb.putShort((short) i);
out.write(bb.array());
}  在安装包Comment字段写入渠道号的方式,经过测试,并没有修改安装包的内容,用户能成功安装并且使用。(5)读渠道号关键代码://读取源apk的路径
public static String getSourceApkPath(Context context, String packageName) {
if (TextUtils.isEmpty(packageName))
ApplicationInfo appInfo = context.getPackageManager().getApplicationInfo(packageName, 0);
return appInfo.sourceD
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}//读取渠道号
public static String readQUA(File file) throws IOException {
RandomAccessFile raf =
raf = new RandomAccessFile(file, "r");
long index = raf.length();
byte[] buffer = new byte[MAGIC.length];
index -= MAGIC.
//定位到MAGIC处
raf.seek(index);
//读取MAGIC
raf.readFully(buffer);
//判断文件末尾是否存在MAGIC字符
if (isMagicMatched(buffer)) {
index -= SHORT_LENGTH;
raf.seek(index);
//读取渠道号长度
int length = readShort(raf);
if (length > 0) {
raf.seek(index);
//读取渠道号
byte[] bytesComment = new byte[length];
raf.readFully(bytesComment);
return new String(bytesComment, UTF_8);
} finally {
if (raf != null) {
raf.close();
//判断是否存在渠道号
private static boolean isMagicMatched(byte[] buffer) {
if (buffer.length != MAGIC.length) {
for (int i = 0; i < MAGIC. ++i) {
if (buffer[i] != MAGIC[i]) {
}读取渠道号有两个步骤:  1、获取安装包的绝对路径。Android系统在用户安装app时,会把用户安装的apk拷贝一份到/data/apk/路径下,通过getSourceApkPath 可以获取该apk的绝对路径。  2、读取渠道号。先定位到文件末尾,判断该文件是否存在写入的MAGIC字符,如果存在再读取渠道号。这时,我们多渠道的问题也解决了。我们把代码渠道号写入apk的comment字段,也通过代码成功读取到了渠道号。3、合成新安装包(1)删除原APK的渠道号  由于我们在生成差异包的时候,两个新旧版本的安装包都是没有渠道号的,而用户在应用市场下载的安装包是我们写入渠道号的安装包,所以我们要把用户正在使用的版本删除渠道号。由于/data/apk/路径,我们只有读取的权限,所以需要把删除渠道号的安装包临时保存起来。  删除渠道号的关键代码://删除渠道号
public static int deleteQua(File src, File dest) throws IOException{
if(!src.exists()){
return DELETE_QUA_FAILE_SOURCE_FILE_NOT_EXIST;
long contenLength = getContentLength(src);
if(contenLength < 0){
return DELETE_QUA_FAILE_QUA_NOT_EXIST;
FileInputStream in = new FileInputStream(src.getAbsolutePath());
File file =
if(!file.exists())
file.createNewFile();
FileOutputStream out = new FileOutputStream(file);
long copyed = contenL
byte buffer[] = new byte[1024];
while ((c = in.read(buffer)) != -1) {
if(copyed != c && c == buffer.length){
copyed = copyed -
out.write(buffer, 0, c);
//还原源文件,需要把最后两个字节置为0
表示apk没有注释
buffer[(int) (copyed - 1)] = 0;
buffer[(int) (copyed - 2)] = 0;
out.write(buffer, 0, (int)copyed);
close(in);
close(out);
return SUCCESS;
}(2)合成新APK  通过上面步骤,我们可以得到没有渠道号的临时本地安装包,并且和服务器的原始包一致,我们可以使用这个没有渠道号的安装包和已下载的差异包合成新版安装包。由于用户使用的版本可能是破解版,或者下载差异包下载不完整,所以在合成的前需要做文件一致性检验。可以比较文件的md5值,如果MD5值一致,才能进行合成,否则合成失败,直接下载完整的安装包升级。流程如下图:  我们需要把bsdiff中的bspatch.c整合到我们C代码中,并将其编译生so供Android手机使用,其中bspatch依赖bzip2,需要自己下载依赖的c文件。C关键代码:#include
#include "bzip2/bzlib.c"
#include "bzip2/crctable.c"
#include "bzip2/compress.c"
#include "bzip2/decompress.c"
#include "bzip2/randtable.c"
#include "bzip2/blocksort.c"
#include "bzip2/huffman.c"
#include "com_tencent_smartpatch_utils_PatchUtils.h"
static off_t offtin(u_char *buf) {
y = buf[7] & 0x7F;
y = y * 256;
y += buf[6];
y = y * 256;
y += buf[5];
y = y * 256;
y += buf[4];
y = y * 256;
y += buf[3];
y = y * 256;
y += buf[2];
y = y * 256;
y += buf[1];
y = y * 256;
y += buf[0];
if (buf[7] & 0x80)
int applypatch(int argc, char * argv[]) {
FILE * f, *cpf, *dpf, *
BZFILE * cpfbz2, *dpfbz2, *epfbz2;
int cbz2err, dbz2err, ebz2
ssize_t oldsize,
ssize_t bzctrllen,
u_char essay-header[32], buf[8];
u_char *old, *
off_t oldpos,
off_t ctrl[3];
if (argc != 4)
errx(1, "usage: %s oldfile newfile patchfile\n", argv[0]);
/* Open patch file */
if ((f = fopen(argv[3], "r")) == NULL)
err(1, "fopen(%s)", argv[3]);
File format:
"BSDIFF40"
sizeof(newfile)
bzip2(control block)
bzip2(diff block)
bzip2(extra block)
with control block a set of triples (x,y,z) meaning "add x bytes
from oldfile to x bytes copy y bytes from the
seek forwards in oldfile by z bytes".
/* Read essay-header */
if (fread(essay-header, 1, 32, f) < 32) {
if (feof(f))
errx(1, "Corrupt patch\n");
err(1, "fread(%s)", argv[3]);
/* Check for appropriate magic */
if (memcmp(essay-header, "BSDIFF40", 8) != 0)
errx(1, "Corrupt patch\n");
/* Read lengths from essay-header */
bzctrllen = offtin(essay-header + 8);
bzdatalen = offtin(essay-header + 16);
newsize = offtin(essay-header + 24);
if ((bzctrllen < 0) || (bzdatalen < 0) || (newsize < 0))
errx(1, "Corrupt patch\n");
/* Close patch file and re-open it via libbzip2 at the right places */
if (fclose(f))
err(1, "fclose(%s)", argv[3]);
if ((cpf = fopen(argv[3], "r")) == NULL)
err(1, "fopen(%s)", argv[3]);
if (fseeko(cpf, 32, SEEK_SET))
err(1, "fseeko(%s, %lld)", argv[3], (long long) 32);
if ((cpfbz2 = BZ2_bzReadOpen(&cbz2, cpf, 0, 0, NULL, 0)) == NULL)
errx(1, "BZ2_bzReadOpen, bz2err = %d", cbz2err);
if ((dpf = fopen(argv[3], "r")) == NULL)
err(1, "fopen(%s)", argv[3]);
if (fseeko(dpf, 32 + bzctrllen, SEEK_SET))
err(1, "fseeko(%s, %lld)", argv[3], (long long) (32 + bzctrllen));
if ((dpfbz2 = BZ2_bzReadOpen(&dbz2, dpf, 0, 0, NULL, 0)) == NULL)
errx(1, "BZ2_bzReadOpen, bz2err = %d", dbz2err);
if ((epf = fopen(argv[3], "r")) == NULL)
err(1, "fopen(%s)", argv[3]);
if (fseeko(epf, 32 + bzctrllen + bzdatalen, SEEK_SET))
err(1, "fseeko(%s, %lld)", argv[3],
(long long) (32 + bzctrllen + bzdatalen));
if ((epfbz2 = BZ2_bzReadOpen(&ebz2, epf, 0, 0, NULL, 0)) == NULL)
errx(1, "BZ2_bzReadOpen, bz2err = %d", ebz2err);
if (((fd = open(argv[1], O_RDONLY, 0)) < 0)
|| ((oldsize = lseek(fd, 0, SEEK_END)) == -1)
|| ((old = malloc(oldsize + 1)) == NULL)
|| (lseek(fd, 0, SEEK_SET) != 0)
|| (read(fd, old, oldsize) != oldsize) || (close(fd) == -1))
err(1, "%s", argv[1]);
if ((new = malloc(newsize + 1)) == NULL)
err(1, NULL);
oldpos = 0;
newpos = 0;
while (newpos < newsize) {
/* Read control data */
for (i = 0; i <= 2; i++) {
lenread = BZ2_bzRead(&cbz2, cpfbz2, buf, 8);
if ((lenread
errx(1, "Corrupt patch\n");
/* Read diff string */
lenread = BZ2_bzRead(&dbz2, dpfbz2, new + newpos, ctrl[0]);
if ((lenread < ctrl[0])
|| ((dbz2err != BZ_OK) && (dbz2err != BZ_STREAM_END)))
errx(1, "Corrupt patch\n");
/* Add old data to diff string */
for (i = 0; i = 0) && (oldpos + i
errx(1, "Corrupt patch\n");
/* Read extra string */
lenread = BZ2_bzRead(&ebz2, epfbz2, new + newpos, ctrl[1]);
if ((lenread < ctrl[1])
|| ((ebz2err != BZ_OK) && (ebz2err != BZ_STREAM_END)))
errx(1, "Corrupt patch\n");
/* Adjust pointers */
newpos += ctrl[1];
oldpos += ctrl[2];
/* Clean up the bzip2 reads */
BZ2_bzReadClose(&cbz2, cpfbz2);
BZ2_bzReadClose(&dbz2, dpfbz2);
BZ2_bzReadClose(&ebz2, epfbz2);
if (fclose(cpf) || fclose(dpf) || fclose(epf))
err(1, "fclose(%s)", argv[3]);
/* Write the new file */
if (((fd = open(argv[2], O_CREAT | O_TRUNC | O_WRONLY, 0666)) GetStringUTFChars(env, old_apk, 0));
ch[2] = (char*) ((*env)->GetStringUTFChars(env, new_apk, 0));
ch[3] = (char*) ((*env)->GetStringUTFChars(env, patch, 0));
int ret = applypatch(4, ch);
(*env)->ReleaseStringUTFChars(env, old_apk, ch[1]);
(*env)->ReleaseStringUTFChars(env, new_apk, ch[2]);
(*env)->ReleaseStringUTFChars(env, patch, ch[3]);
}  java关键代码:/**
* apk 合成类
public class PatchUtils {
public static final String TAG = "PatchUtils";
System.loadLibrary("apksmartpatchlibrary");
* native方法 使用路径为oldApkPath的apk与路径为patchPath的补丁包,合成新的apk,并存储于newApkPath
* 返回:0,说明操作成功
* @param oldApkPath 示例:/sdcard/old.apk
* @param newApkPath 示例:/sdcard/new.apk
* @param patchPath
示例:/sdcard/xx.patch
public static native int patch(String oldApkPath, String newApkPath, String patchPath);
}  至此,我们调用 PatchUtile.patch方法即可生成最新的安装包。三、小结  再重复一下完整过程:  1、编译打包APK(未写入渠道号)  2、服务器用新旧APK(未写入渠道号)生成差异包  3、APK写入渠道号,供用户下载使用  4、用户本地APK删除渠道号  5、根据用户使用版本下载差异包  6、用本地删除渠道号的APK+下载的差异包生成最新版本APK四、参考资料  1、http://www.daemonology.net/bsdiff  2、https://en.wikipedia.org/wiki/Zip_(file_format)  3、/cundong/SmartAppUpdates  4、/mcxiaoke/packer-ng-plugin
觉得不错,分享给更多人看到
QQ音乐技术团队 微信二维码
分享这篇文章
QQ音乐技术团队 最新文章
QQ音乐技术团队 热门文章}

我要回帖

更多关于 全民k歌怎么刷粉丝 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信