php 写apk/zip注释comment标记推广渠道

apk本来就是一个zip压缩包,要写推广渠道标记,写入comment注释是个好办法

不过在sign2.0时,这方法会破坏apk无法运行,操作方法为

修改build.gradle文件,新增如下v2SigningEnabled false

signingConfigs {
        release {
            storeFile file('.\\keystore\\keystore.jks')
            storePassword "pass123"
            keyAlias "agent"
            keyPassword "pass123"
            v2SigningEnabled false
        }
    }

那么生成的apk就是未签名的文件,在下面php打包时方便使用

在android studio界面最左侧Build Variants修改为release

接下来我们写php,方法有两种,一种是开源项目

https://github.com/chenzi/php-apk-packer

使用方法如下

<?PHP
include "php-apk-packer/ApkPacker.php";
$会员编号 = isset($_GET['ref'])?$_GET['ref']:null;
if(!empty($会员编号)){
	$appfilepath="test{$会员编号}.apk";
	if(!file_exists($appfilepath)){
		$apkPacker = new \ApkPacker\ApkPacker();
		$apkPacker->packerSingleApk('test.apk',$会员编号,$appfilepath);
	}
	header("HTTP/1.1 301 Moved Permanently");
	header("Location: $appfilepath");
}

另一种方法,是php自带的ziparchive

<?PHP
$会员编号 = isset($_GET['ref'])?$_GET['ref']:null;
if(!empty($会员编号)){
	$appfilepath="test{$会员编号}.apk";
	if(!file_exists($appfilepath)){
		if(copy("test.apk",$appfilepath)){
    		$zip = new ZipArchive;
            $res = $zip->open($appfilepath, ZipArchive::CREATE);
            if ($res === TRUE) {
                //$zip->addFromString('test.txt', 'file content goes here');
                $zip->setArchiveComment($会员编号);
                $zip->close();
                //echo 'ok';
            } else {
                //echo 'failed';
            }
		}
	}
	header("HTTP/1.1 301 Moved Permanently");
	header("Location: $appfilepath");
}

写入apk以上方法任选一种,我觉得自带ziparchive较简单。

写了以后怎么读呢?看以下java代码,创建一个zipcomment.java的class

import java.io.File;
import java.io.FileInputStream;

public class zipcomment {
    public static String extractZipComment (String filename) {
        String retStr = null;
        try {
            File file = new File(filename);
            int fileLen = (int)file.length();

            FileInputStream in = new FileInputStream(file);

            /* The whole ZIP comment (including the magic byte sequence)
             * MUST fit in the buffer
             * otherwise, the comment will not be recognized correctly
             *
             * You can safely increase the buffer size if you like
             */
            byte[] buffer = new byte[Math.min(fileLen, 8192)];
            int len;

            in.skip(fileLen - buffer.length);

            if ((len = in.read(buffer)) > 0) {
                retStr = getZipCommentFromBuffer (buffer, len);
            }

            in.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return retStr;
    }

    private static String getZipCommentFromBuffer (byte[] buffer, int len) {
        byte[] magicDirEnd = {0x50, 0x4b, 0x05, 0x06};
        int buffLen = Math.min(buffer.length, len);
        //Check the buffer from the end
        for (int i = buffLen-magicDirEnd.length-22; i >= 0; i--) {
            boolean isMagicStart = true;
            for (int k=0; k < magicDirEnd.length; k++) {
                if (buffer[i+k] != magicDirEnd[k]) {
                    isMagicStart = false;
                    break;
                }
            }
            if (isMagicStart) {
                //Magic Start found!
                int commentLen = buffer[i+20] + buffer[i+22]*256;
                int realLen = buffLen - i - 22;
                System.out.println ("ZIP comment found at buffer position " + (i+22) + " with len="+commentLen+", good!");
                if (commentLen != realLen) {
                    System.out.println ("WARNING! ZIP comment size mismatch: directory says len is "+
                            commentLen+", but file ends after " + realLen + " bytes!");
                }
                String comment = new String (buffer, i+22, Math.min(commentLen, realLen));
                return comment;
            }
        }
        System.out.println ("ERROR! ZIP comment NOT found!");
        return null;
    }

}

怎么读呢?比如如下代码

@JavascriptInterface
public String getref()
{
	String referer="";
	//获取该程序的安装包路径
	//String zipPathdiy=context.getApplicationContext().getPackageResourcePath();
	String zipPathdiy = context.getApplicationContext().getPackageCodePath();
	String commentStr = new zipcomment().extractZipComment(zipPathdiy);
	if(commentStr!="" && commentStr!=null) {
		referer=commentStr;
	}
	return referer;
}

就是如此简单。

如果是b4a的例子在旧文章有提过

b4a 读取压缩包的注释comment

点赞

发表评论

电子邮件地址不会被公开。必填项已用 * 标注