您的位置:首页 > 移动开发 > Android开发

Android应用程序的签名

2012-01-29 15:45 302 查看
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编译、打包的步骤:

2.1第一步 生成R.java类文件:

Eclipse中会自动生成R.java,ant和命令行使用android SDK提供的aapt.ext程序生成R.java。

2.2第二步 将.aidl文件生成.java类文件:

Eclipse中自动生成,ant和命令行使用android SDK提供的aidl.exe生成.java文件。

2.3第三步 编译.java类文件生成class文件:

Eclipse中自动生成,ant和命令行使用jdk的javac编译java类文件生成class文件。

2.4第四步 将class文件打包生成classes.dex文件:

Eclipse中自动生成,ant和命令行使用android SDK提供的dx.bat命令行脚本生成classes.dex文件。

2.5第五步 打包资源文件(包括res、assets、androidmanifest.xml等):

Eclipse中自动生成,ant和命令行使用Android SDK提供的aapt.exe生成资源包文件。

2.6第六步 生成未签名的apk安装文件:

Eclipse中自动生成debug签名文件存放在bin目录中,ant和命令行使用android SDK提供的apkbuilder.bat命令脚本生成未签名的apk安装文件。

2.7第七步 对未签名的apk进行签名生成签名后的android文件:

Eclipse中使用Android Tools进行签名,ant和命令行使用jdk的jarsigner对未签名的包进行apk签名。



3.命令行手动编译打包详解

详见:http://jojol-zhou.javaeye.com/blog/729254


4.ant自动打包android程序详解

4.1生成R.java类文件:

<!-- Generate the R.java file for this project's resources. -->

<target name="resource-src" depends="copy">

<echo>Generating R.java / Manifest.java from the resources...</echo>

<exec executable="${aapt}" failonerror="true">

<arg value="package" />

<arg value="-m" />

<arg value="-J" />

<arg value="${outdir-gen}" />

<arg value="-M" />

<arg value="AndroidManifest.xml" />

<arg value="-S" />

<arg value="${resource-dir}" />

<arg value="-I" />

<arg value="${android-jar}" />

</exec>

</target>

4.2将.aidl文件生成.java类文件:

<!-- Generate java classes from .aidl files. -->

<target name="aidl" depends="copy">

<echo>Compiling aidl files into Java classes...</echo>

<apply executable="${aidl}" failonerror="true">

<arg value="-p${android-framework}" />

<arg value="-I${srcdir}" />

<fileset dir="${srcdir}">

<include name="**/*.aidl"/>

</fileset>

</apply>

</target>

4.3编译.java类文件生成class文件:

<!-- Compile this project's .java files into .class files. -->

<target name="compile" depends="copy, resource-src, aidl">

<javac encoding="GB18030" target="1.5" debug="true" extdirs=""

srcdir="."

destdir="${outdir-classes}"

bootclasspath="${android-jar}">

<classpath>

<fileset dir="${external-libs}" includes="*.jar"/>

</classpath>

</javac>

</target>



4.4第四步 将class文件打包生成classes.dex文件:

<!-- Convert this project's .class files into .dex files. -->

<target name="dex" depends="compile">

<echo>Converting compiled files and external libraries into ${outdir}/${dex-file}...</echo>

<apply executable="${dx}" failonerror="true" parallel="true">

<arg value="--dex" />

<arg value="--output=${intermediate-dex-ospath}" />

<arg path="${outdir-obfuscate-classes-ospath}" />

<fileset dir="${external-libs}" includes="*.jar"/>

</apply>

</target>

4.5第五步 打包资源文件(包括res、assets、androidmanifest.xml等):

<!-- Put the project's resources into the output package file. -->

<target name="package-res-and-assets">

<echo>Packaging resources and assets...</echo>

<exec executable="${aapt}" failonerror="true">

<arg value="package" />

<arg value="-f" />

<arg value="-M" />

<arg value="AndroidManifest.xml" />

<arg value="-S" />

<arg value="${resource-dir}" />

<arg value="-A" />

<arg value="${asset-dir}" />

<arg value="-I" />

<arg value="${android-jar}" />

<arg value="-F" />

<arg value="${resources-package}" />

</exec>

</target>

4.6第六步 生成未签名的apk安装文件:

<target name="package" depends="dex, package-res">

<echo>Packaging ${out-unsigned-package} for release...</echo>

<exec executable="${apk-builder}" failonerror="true">

<arg value="${out-unsigned-package-ospath}" />

<arg value="-u" />

<arg value="-z" />

<arg value="${resources-package-ospath}" />

<arg value="-f" />

<arg value="${intermediate-dex-ospath}" />

<arg value="-rf" />

<arg value="${srcdir-ospath}" />

<arg value="-rj" />

<arg value="${external-libs-ospath}" />

</exec>

<echo>It will need to be signed with jarsigner before being published.</echo>

</target>



4.7第七步 对未签名的apk进行签名生成签名后的android文件:

<target name="jarsigner" depends="package">

<echo>Packaging ${out-unsigned-package} for release...</echo>

<exec executable="${jarsigner}" failonerror="true">

<arg value="-verbose" />

<arg value="-storepass" />

<arg value="byread002" />

<arg value="-keypass" />

<arg value="byread002" />

<arg value="-keystore" />

<arg value="bbyread.keystore" />

<arg value="-signedjar" />

<arg value="${out-signed-package-ospath}" />

<arg value="${out-unsigned-package-ospath}" />

<arg value="byread" />

</exec>

</target>

--------------------------------------------------------------------------------------------以下内容为转载---------------------

----------------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>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: