Android多渠道打包工具–MoeApkTool(通过assets目录内文件来区分渠道)

该工具参考自:RyApkTool特在此表示感谢~

1.原理

已签名APK文件==>ShakaApktool解压APK文件==>添加MOE_CHANNEL文件到assets目录

==>ShakaApktool重新打包APK文件==>jarsigner签名

MOE_CHANNEL文件里的内容就是渠道信息

2.用法

将APK文件放入工具包文件夹

CD到文件夹所在目录:java -jar MoeApkTool.jar keyFile keyName keyPasswd

3.编辑渠道信息

编辑工具包文件夹下的info文件夹里的channel.txt文件,一行一个渠道号

4.在程序里使用

点我看如何在程序里获取渠道号

5.下载地址

点我下载工具包

点我下载源码

【转】Java应用打包后运行需要注意编码问题

转载自:Java应用打包后运行需要注意编码问题

文章针对作者原文略有修改,以下是正文。

最近在做一个项目,项目总的来说就是和数据库打交道,取出数据来通过HTTP协议提交到一个接口上去。具体功能不多说了,只是讲这里面的一点——编码问题
项目当中,涉及到取所有数据的MD5值。
在Java项目中,个人喜欢将项目的默认编码改为UTF-8。使用的开发工具以Eclipse为主。然而,奇怪的问题出现了。当我在IDE中对项目进行调试的时候没有任何问题,但是打成了jar包后再通过

java -jar project.jar

运行的时候,每次提交数据,接口都会返回数据说我的签名不正确。换句话说就是我的最后一步,做MD5运算的时候出了问题。

为什么打了jar包就不行呢?几经波折,又是查看参数的hashCode,又是检查所有提交内容的十六进制数据,发现是文本编码出了问题。在Eclipse中是正确的,但是打出jar包后,启动命令行一直没设置字符串默认编码,因此java虚拟机就按照所在系统的默认编码运行了。我使用的是Windows环境,那么自然是GBK编码。

后来通过查阅资料,解决的办法就是加一个参数指定编码:

java -Dfile.encoding=utf-8 -jar project.jar

这样就可以了。工具正常运行了。

调用移动接口遇到的问题总结

方向一旦跑偏,造成的影响是非常大的。

1、请求地址问题

问题描述:移动接口的请求地址是IP地址,需要在header中设置host参数。测试过程中一直遇到400错误而不知道原因,于是决定在PC上面使用fidder进行抓包查看。抓到的包一直有问题,host地址始终是ip地址而不是设置好的域名。

问题原因:fidder抓手机包采用的是代理方式。抓包后对header中的host信息进行了改动。更深层次的原因是fidder采用了PC端的DNS解析。

问题解决:使用fidder抓包时,PC上面修改hosts文件,手机端请求地址改为域名方式。

2、Base64编码问题

问题描述:使用fidder抓包后发现,header信息中有一个参数不正确。移动方提示参数未设置。

问题原因:程序中使用了android.util.Base64进行Base64加密。该包进行加密的时候默认进行了自动换行操作。

问题解决:使用android.util.Base64包进行加密的时候,第二个参数需要改为Base64.NO_WRAP。

写一点关于安全的东西:)

一、双向消息加密

RSA,非对称加密算法。

DES,AES,对称加密算法。

用于服务端和客户端通讯。

客户端向服务端发送数据,采用RSA算法,使用公钥进行加密。服务端使用私钥进行解密。

服务端向客户端发送数据,采用DES或AES算法进行加密。客户端进行解密。

二、用户登录验证

谷歌验证 (Google Authenticator)

用于用户登录二次验证。

m3u8格式文件解析

public class VideoUtil {
    /**
     * 根据电影的m3u8_url解析出ts_url即xxx.ts形式url为元素的集合
     *
     * @param m3u8_url m3u8文件地址
     * @return 返回ts_url集合
     */
    public static ArrayList m3u8Parser(String m3u8_url) {
        try {
            ArrayList list_ts = new ArrayList();
            URL url = new URL(m3u8_url);
            HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
            InputStream in = urlConn.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
            String line = "";
            while ((line = reader.readLine()) != null) {
                if (line.startsWith("#")) {
                    //这里是Metadata信息
                } else if (line.length() > 0) {
                        //这里是一个指向的视频流路径 ,可能是绝对地址,也可能是相对地址
                    if (line.startsWith("http")) {
                        //如果以http开头,一定是绝对地址了
                        list_ts.add(line);
                    } else {
                        //不以http开头,是相对地址,需要进行拼接。
                        String m3u8_pre = m3u8_url.substring(0, m3u8_url.lastIndexOf("/") + 1);
                        list_ts.add(m3u8_pre + line);
                    }
                }
            }
            in.close();
            return list_ts;

        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}

Android自定义ToggleButton

1、设置自定义背景,设置on、off文案都为空

<ToggleButton
    android:id="@+id/lockBtn"
    android:background="@drawable/lock_me"
    android:textOn=""
    android:textOff=""/>

2、自定义背景文件

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_checked="true"
        android:drawable="@drawable/lock_me_on" /> <!-- pressed -->
    <item android:drawable="@drawable/lock_me_off" /> <!-- default/unchecked -->
</selector>

3、按钮的监听

mLockBtn.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        if (mLockBtn.isChecked()) {
            //锁定
            mLockFlag = true;
            mSeekBar.setEnabled(false);
            mTopView.setVisibility(View.GONE);
            mBottomView.setVisibility(View.GONE);
        } else {
            //取消锁定
            mLockFlag = false;
            mSeekBar.setEnabled(true);
            mTopView.setVisibility(View.VISIBLE);
            mBottomView.setVisibility(View.VISIBLE);
        }
    }
});

【转】修改Android签名证书keystore的密码、别名alias以及别名密码

转载自:修改Android签名证书keystore的密码、别名alias以及别名密码

之前在测试Eclipse ADT的Custom debug keystore自定义调试证书的时候,发过一篇关于调试证书规格的博文:Eclipse ADT的Custom debug keystore所需证书规格,提到过自定义调试证书的密码和alias命名以及alias密码都是有规矩的。其实Android应用开发接入各种SDK时会发现,有很多SDK是需要靠package name和keystore的指纹hash来识别的(百度地图SDK、Facebook SDK等等…),这样如果使用默认自动生成的debug keystore的话就会给开发调试工作带来一些麻烦。这时可以通过修改正式的release keystore,生成一份“遵守规矩”的临时自定义调试证书给开发时用,就方便多了,具体方法如下:
继续阅读【转】修改Android签名证书keystore的密码、别名alias以及别名密码

【转】Eclipse ADT的Custom debug keystore所需证书规格

转载自:Eclipse ADT的Custom debug keystore所需证书规格

最近开始研究Google Play的In-app Billing IAB内置计费API,发现一个比较烦人的问题就是测试时应用必须经过正式签名,而默认Eclipse ADT调试运行使用的是临时生成的Debug专用证书,默认为

C:\Users\XXX\.android\debug.keystore

于是每次调试内置计费必须使用ADT的Export Signed Application Package打带正式签名的包,比较麻烦。后来发现ADT允许自定义调试用证书,在Window->Preferences->Android->Build->Custom debug keystore这里,试了一下选择正式证书后提示:”Keystore was tampered with, or password was incorrect”,如下图所示:

QQ20130308142554
其实这个界面并没有提供输入Keystore密码,选择别名之类的地方,所以就感到非常奇怪了,查了一下官方文档发现,即使是自定义的调试证书,也需要保证和默认证书一样的密码,别名alias和别名密码。

文档中提到的默认证书信息如下:

Keystore name: “debug.keystore”
Keystore password: “android
Key alias: “androiddebugkey”
Key password: “android”
CN: “CN=Android Debug,O=Android,C=US”

遵循这个规则就可以用自定义调试证书了。不过仔细想想感觉这功能这样很是鸡肋,希望以后版本的ADT会改进吧。