Android程序的签名用户在开发时通过ADB接口上传的程序会自动被签有Debug权限的程序,但是在上传程序到Android Market上或者到设备上时则需要正式签名。
Android signed制作方法主要使用Keytool和Jarsigner两个工具制作。
1.第一种方法:利用keytool和jarsinger命令行签名
详细的签名步骤:
第一步 生成个人签名密钥库基础数据
用keytool生成证书:
-alias myAndroid 证书别名,-keyalg RSA 指的是采用的RSA算法,-keystore myandroid.keystore是指生成的证书存储的位置。回车后会提示你输入keystore password,这可以自己定,然后是一些个人信息及组织信息,可以轻松搞定。
-validity 缺省时间是90 天,建议设置一个较长的天数
具体实例如下:
keytool -genkey -alias myandroid -keyalg RSA -validity 10000 -keystore myAndroid.keystore
D:\Android\00STUDY\myandorid>keytool -genkey -alias myandroid -keyalg R
SA -validity 20000 -keystore myAndroid.keystore
输入keystore密码: *************
您的名字与姓氏是什么?
[Unknown]: monner
您的组织单位名称是什么?
[Unknown]: monner
您的组织名称是什么?
[Unknown]: monner
您所在的城市或区域名称是什么?
[Unknown]: gz
您所在的州或省份名称是什么?
[Unknown]: gd
该单位的两字母国家代码是什么
[Unknown]: cn
CN=monner, OU=monner, O=monner, L=gz, ST=gd, C=cn 正确吗?
[否]: y
输入<myAndroid.keystore>的主密码
(如果和 keystore 密码相同,按回车):
(注意事项:android工程的bin目录下的demo.apk默认是已经使用debug用户签名的,所以不能使用上述步骤对此文件再次签名。正确步骤应该是:在工程点击右键->Anroid Tools-Export Unsigned Application Package导出的apk采用上述步骤签名。)
第二步 apk文件签名命令
方法很简单,执行jarsigner命令行即可,基本命令格式如下:
jarsigner -verbose -keystore your-release-key.keystore your-release.apk your-alias-name
具体实例如下:
D:\Android\00STUDY\myandorid\bin>jarsigner -verbose -keystore .\myandroid.keysto
re myAndroid-singed.apk myAndroid-unsigned.apk myandroid
输入密钥库的口令短语: *************(程序提示输入的密码和keytool输入的一样即可成功。 )
正在添加: META-INF/MANIFEST.MF
正在添加: META-INF/MYANDROI.SF
正在添加: META-INF/MYANDROI.RSA
正在签名: res/layout/main.xml
正在签名: AndroidManifest.xml
正在签名: resources.arsc
正在签名: res/drawable-hdpi/icon.png
正在签名: res/drawable-ldpi/icon.png
正在签名: res/drawable-mdpi/icon.png
正在签名: classes.dex
警告: 签名者证书将在六个月内过期。
用户输入的未签名文件会自动变为已签名的apk文件,文件名不变。
========================================
附: keytool参数和jarsigner参数详解
keytool用法 :
-certreq [-v] [-protected]
[-alias <别名>] [-sigalg <sigalg>]
[-file <csr_file>] [-keypass <密钥库口令>]
[-keystore <密钥库>] [-storepass <存储库口令>]
[-storetype <存储类型>] [-providername <名称>]
[-providerclass <提供方类名称> [-providerarg <参数>]] ...
[-providerpath <路径列表>]
-changealias [-v] [-protected] -alias <别名> -destalias <目标别名>
[-keypass <密钥库口令>]
[-keystore <密钥库>] [-storepass <存储库口令>]
[-storetype <存储类型>] [-providername <名称>]
[-providerclass <提供方类名称> [-providerarg <参数>]] ...
[-providerpath <路径列表>]
-delete [-v] [-protected] -alias <别名>
[-keystore <密钥库>] [-storepass <存储库口令>]
[-storetype <存储类型>] [-providername <名称>]
[-providerclass <提供方类名称> [-providerarg <参数>]] ...
[-providerpath <路径列表>]
-exportcert [-v] [-rfc] [-protected]
[-alias <别名>] [-file <认证文件>]
[-keystore <密钥库>] [-storepass <存储库口令>]
[-storetype <存储类型>] [-providername <名称>]
[-providerclass <提供方类名称> [-providerarg <参数>]] ...
[-providerpath <路径列表>]
-genkeypair [-v] [-protected]
[-alias <别名>]
[-keyalg <keyalg>] [-keysize <密钥大小>]
[-sigalg <sigalg>] [-dname <dname>]
[-validity <valDays>] [-keypass <密钥库口令>]
[-keystore <密钥库>] [-storepass <存储库口令>]
[-storetype <存储类型>] [-providername <名称>]
[-providerclass <提供方类名称> [-providerarg <参数>]] ...
[-providerpath <路径列表>]
-genseckey [-v] [-protected]
[-alias <别名>] [-keypass <密钥库口令>]
[-keyalg <keyalg>] [-keysize <密钥大小>]
[-keystore <密钥库>] [-storepass <存储库口令>]
[-storetype <存储类型>] [-providername <名称>]
[-providerclass <提供方类名称> [-providerarg <参数>]] ...
[-providerpath <路径列表>]
-help
-importcert [-v] [-noprompt] [-trustcacerts] [-protected]
[-alias <别名>]
[-file <认证文件>] [-keypass <密钥库口令>]
[-keystore <密钥库>] [-storepass <存储库口令>]
[-storetype <存储类型>] [-providername <名称>]
[-providerclass <提供方类名称> [-providerarg <参数>]] ...
[-providerpath <路径列表>]
-importkeystore [-v]
[-srckeystore <源密钥库>] [-destkeystore <目标密钥库>]
[-srcstoretype <源存储类型>] [-deststoretype <目标存储类型>]
[-srcstorepass <源存储库口令>] [-deststorepass <目标存储库口令>]
[-srcprotected] [-destprotected]
[-srcprovidername <源提供方名称>]
[-destprovidername <目标提供方名称>]
[-srcalias <源别名> [-destalias <目标别名>]
[-srckeypass <源密钥库口令>] [-destkeypass <目标密钥库口令>]]
[-noprompt]
[-providerclass <提供方类名称> [-providerarg <参数>]] ...
[-providerpath <路径列表>]
-keypasswd [-v] [-alias <别名>]
[-keypass <旧密钥库口令>] [-new <新密钥库口令>]
[-keystore <密钥库>] [-storepass <存储库口令>]
[-storetype <存储类型>] [-providername <名称>]
[-providerclass <提供方类名称> [-providerarg <参数>]] ...
[-providerpath <路径列表>]
-list [-v | -rfc] [-protected]
[-alias <别名>]
[-keystore <密钥库>] [-storepass <存储库口令>]
[-storetype <存储类型>] [-providername <名称>]
[-providerclass <提供方类名称> [-providerarg <参数>]] ...
[-providerpath <路径列表>]
-printcert [-v] [-file <认证文件>]
-storepasswd [-v] [-new <新存储库口令>]
[-keystore <密钥库>] [-storepass <存储库口令>]
[-storetype <存储类型>] [-providername <名称>]
[-providerclass <提供方类名称> [-providerarg <参数>]] ...
[-providerpath <路径列表>]
jarsigner用法 :
[选项] jar 文件别名
jarsigner -verify [选项] jar 文件
[-keystore <url>] 密钥库位置
[-storepass <口令>] 用于密钥库完整性的口令
[-storetype <类型>] 密钥库类型
[-keypass <口令>] 专用密钥的口令(如果不同)
[-sigfile <文件>] .SF/.DSA 文件的名称
[-signedjar <文件>] 已签名的 JAR 文件的名称
[-digestalg <算法>] 摘要算法的名称
[-sigalg <算法>] 签名算法的名称
[-verify] 验证已签名的 JAR 文件
[-verbose] 签名/验证时输出详细信息
[-certs] 输出详细信息和验证时显示证书
[-tsa <url>] 时间戳机构的位置
[-tsacert <别名>] 时间戳机构的公共密钥证书
[-altsigner <类>] 替代的签名机制的类名
[-altsignerpath <路径列表>] 替代的签名机制的位置
[-internalsf] 在签名块内包含 .SF 文件
[-sectionsonly] 不计算整个清单的散列
[-protected] 密钥库已保护验证路径
[-providerName <名称>] 提供者名称
[-providerClass <类> 加密服务提供者的名称
[-providerArg <参数>]] ... 主类文件和构造函数参数
************************************************************************************************************************************************************
C:\Users\Pauson>cd C:\Program Files\Java\jdk1.6.0_01\bin
C:\Program Files\Java\jdk1.6.0_01\bin>keytool -genkey -v -keystore my.keystore -alias key_name -keyalg RSA -validity 50000
输入keystore密码:paulson
再次输入新密码: paulson
您的名字与姓氏是什么?
[Unknown]: yan
您的组织单位名称是什么?
[Unknown]: 上海典酷信息有限公司
您的组织名称是什么?
[Unknown]: 典酷
您所在的城市或区域名称是什么?
[Unknown]: 上海
您所在的州或省份名称是什么?
[Unknown]: 上海
该单位的两字母国家代码是什么
[Unknown]: 86
CN=yan, OU=上海典酷信息有限公司, O=典酷, L=上海, ST=上海, C=86 正确吗?
[否]: 是
正在为以下对象生成 1,024 位 RSA 密钥对和自签名证书 (SHA1withRSA)(有效期为 50,00
0 天):
CN=yan, OU=上海典酷信息有限公司, O=典酷, L=上海, ST=上海, C=86
输入<key_name>的主密码
(如果和 keystore 密码相同,按回车):paulson
[正在存储 my.keystore]
完成签名:
jarsigner -verbose -keystore my.keystore pedometer.apk key_name
C:\Program Files\Java\jdk1.6.0_01\bin>jarsigner -keystore my.keystore D:\Pedometer.apk key_name
输入密钥库的口令短语:
C:\Program Files\Java\jdk1.6.0_01\bin>
jarsigner -keystore E:\android\my01.keystore E:\android\lotterygift(android).apk key_name01
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2.第二种方法:使用Eclipse完成签名
Eclipse直接能导出带签名的最终apk,非常方便,推荐使用,步骤如下:
第一步:导出。
第二步:创建密钥库keystore,输入密钥库导出位置和密码,记住密码,下次Use existing keystore会用到。
第三步:填写密钥库信息,填写一些apk文件的密码,使用期限和组织单位的信息。
第四步:生成带签名的apk文件,到此就结束了。
第五步:如果下次发布版本的时候,使用前面生成的keystore再签名。
第六步:Next,Next,结束!
3.签名之后,用zipalign(压缩对齐)优化你的APK文件。
未签名的apk不能使用,也不能优化。签名之后的apk谷歌推荐使用zipalign.exe(位于android-sdk-windows\tools目录下)工具对其优化:
Java代码
1. D:\>zipalign -v 4 demo_signed.apk final .apk
D:\>zipalign -v 4 demo_signed.apk final.apk
如上,zipalign能够使apk文件中未压缩的数据在4个字节边界上对齐(4个字节是一个性能很好的值),这样android系统就可以使用mmap()(请自行查阅这个函数的用途)函数读取文件,可以在读取资源上获得较高的性能,
PS:1.在4个字节边界上对齐的意思就是,一般来说,是指编译器吧4个字节作为一个单位来进行读取的结果,这样的话,CPU能够对变量进行高效、快速的访问(较之前不对齐)。
2.对齐的根源:android系统中的Davlik虚拟机使用自己专有的格式DEX,DEX的结构是紧凑的,为了让运行时的性能更好,可以进一步用"对齐"进一步优化,但是大小一般会有所增加。
4.签名对你的App的影响。
谷歌建议你把你所有的APP都使用同一个签名证书。
使用你自己的同一个签名证书,就没有人能够覆盖你的应用程序,即使包名相同,影响有:
1) App升级。 使用相同签名的升级软件可以正常覆盖老版本的软件,否则系统比较发现新版本的签名证书和老版本的签名证书不一致,不会允许新版本安装成功的。
2) App模块化。android系统允许具有相同的App运行在同一个进程中,如果运行在同一个进程中,则他们相当于同一个App,但是你可以单独对他们升级更新,这是一种App级别的模块化思路。
3) 允许代码和数据共享。android中提供了一个基于签名的Permission标签。通过允许的设置,我们可以实现对不同App之间的访问和共享,如下:
Java代码
1. AndroidManifest.xml:<permission android:protectionLevel= "normal" />
AndroidManifest.xml:<permission android:protectionLevel="normal" />
其中protectionLevel标签有4种值:normal(缺省值),dangerous, signature,signatureOrSystem。简单来说,normal是低风险的,所有的App不能访问和共享此App。dangerous是高风险的,所有的App都能访问和共享此App。signature是指具有相同签名的App可以访问和共享此App。signatureOrSystem是指系统image中App和具有相同签名的App可以访问和共享此App,谷歌建议不要使用这个选项,因为签名就足够了,一般这个许可会被用在在一个image中需要共享一些特定的功能的情况下。
-----------------------------------------------------------------------------------以下为转载---------------------------------------------------
Android编译、打包的步骤: |
--------------------------------------------------------------------------------------------以下内容为转载---------------------
----------------build.xml-------------------
<?xml version="1.0"?>
<!--(1) default表示默认的运行目标,这个属性是必须的。
(2) basedir表示项目的基准目录。
(3) name表示项目名。
(4) description表示项目的描述。
每个构建文件都对应于一个项目,但是大型项目经常包含大量的子项目,每一个子项目都可以有自己的构建文件。
-->
- <project name="TestProject" default="all" basedir="." description="test_project">
- <property name="src.dir" value="src" />
- <property name="classes.dir" value="WEB-INF/classes" />
- <property name="lib.dir" value="WEB-INF/lib" />
<!--用于输出打包的文件夹-->
- <property name="temp.dir" value="${java.io.tmpdir}/${ant.project.name}" />
- <property name="target.dir" value="target" />
- <!-- 定义classpath -->
- <path id="master-classpath">
- <fileset file="${lib.dir}/*.jar" />
- <pathelement path="${classes.dir}" />
- </path>
<!--
- 一个项目标签下可以有一个或多个target标签。一个target标签可以依赖其他的target标签。例如,有一个target用于编译程序,另一个target用于声称可执行文件。在生成可执行文件之前必须先编译该文件,因策可执行文件的target依赖于编译程序的target。
- Target的所有属性如下。
(1) name表示标明,这个属性是必须的。
(2) depends表示依赖的目标。
(3) if表示仅当属性设置时才执行。
(4) unless表示当属性没有设置时才执行。
(5) description表示项目的描述 - Ant的depends属性指定了target的执行顺序。Ant会依照depends属性中target出现顺序依次执行每个target。在执行之前,首先需要执行它所依赖的target。程序中的名为run的target的depends属性compile,而名为compile的target的depends属性是prepare,所以这几个target执行的顺序是prepare->compile->run。一个target只能被执行一次,即使有多个target依赖于它。如果没有if或unless属性,target总会被执行。
-->
- <target name="clean">
- <delete dir="${classes.dir}" />
- <delete dir="${temp.dir}" />
- <delete file="${target.dir}/${ant.project.name}.jar"/>
- <delete file="${target.dir}/${ant.project.name}.war"/>
- <delete dir="${target.dir}" />
- </target>
<!-- 初始化任务
(<mkdir )该标签用于创建一个目录,它有一个属性dir用来指定所创建的目录名,其代码如下:<mkdir dir=”${class.root}”/>通过以上代码就创建了一个目录,这个目录已经被前面的property标签所指定。
-->
- <target name="init" depends="clean">
- <mkdir dir="${target.dir}" />
- <mkdir dir="${temp.dir}" />
- <mkdir dir="${classes.dir}" />
- </target>
<!-- 编译 -->
- <target name="compile" depends="init" description="compile the source files">
- <javac srcdir="${src.dir}" destdir="${classes.dir}" debug="true" encoding="GB2312">
- <classpath refid="master-classpath" />
- </javac>
- <copy todir="${classes.dir}" overwrite="true">
- <fileset dir="${src.dir}">
- <include name="**/*.xml" />
- <include name="**/*.properties" />
- </fileset>
- </copy>
- </target>
<!--打jar包-->
- <target name="jar" depends="compile">
- <jar jarfile="${target.dir}/${ant.project.name}.jar">
- <fileset dir="${classes.dir}">
- <include name="**/*" />
- </fileset>
- </jar>
- </target>
- <target name="preWar" depends="jar">
- <copy todir="${temp.dir}/WEB-INF/lib" overwrite="true">
- <fileset dir="${target.dir}">
- <include name="${ant.project.name}.jar"/>
- </fileset>
- </copy>
- <copy todir="${temp.dir}" overwrite="true">
- <fileset dir="${basedir}">
- <include name="${lib.dir}/*.jar" />
- <include name="index.html" />
- <include name="page/**/*.*" />
- <include name="WEB-INF/*.xml" />
- </fileset>
- </copy>
- </target>
<!--打war包-->
- <target name="war" depends="preWar">
- <jar jarfile="${target.dir}/${ant.project.name}.war">
- <fileset dir="${temp.dir}">
- <include name="**/*.*"/>
- </fileset>
- </jar>
- </target>
- <target name="all" depends="war">
- <delete dir="${temp.dir}"/>
- </target>
- </project>