Android应用程序的签名

 

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}" failοnerrοr="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}" failοnerrοr="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}" failοnerrοr="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}" failοnerrοr="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}" failοnerrοr="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}" failοnerrοr="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表示项目的描述。 
  每个构建文件都对应于一个项目,但是大型项目经常包含大量的子项目,每一个子项目都可以有自己的构建文件。 
        -->

  1. <project name="TestProject" default="all" basedir="."  description="test_project">  
  2.   
  3.     <property name="src.dir"       value="src" />  
  4.     <property name="classes.dir"   value="WEB-INF/classes" />  
  5.     <property name="lib.dir"       value="WEB-INF/lib" />  
  6.   

    <!--用于输出打包的文件夹-->  

  1.     <property name="temp.dir"      value="${java.io.tmpdir}/${ant.project.name}" />  
  2.     <property name="target.dir"    value="target" />  
  3.   
  4.     <!-- 定义classpath -->  
  5.     <path id="master-classpath">  
  6.         <fileset file="${lib.dir}/*.jar" />  
  7.         <pathelement path="${classes.dir}" />  
  8.     </path>  
  9.   

<!-- 

  1. 一个项目标签下可以有一个或多个target标签。一个target标签可以依赖其他的target标签。例如,有一个target用于编译程序,另一个target用于声称可执行文件。在生成可执行文件之前必须先编译该文件,因策可执行文件的target依赖于编译程序的target。
  2. Target的所有属性如下。 
    (1) name表示标明,这个属性是必须的。 
    (2) depends表示依赖的目标。 
    (3) if表示仅当属性设置时才执行。 
    (4) unless表示当属性没有设置时才执行。 
    (5) description表示项目的描述
  3. 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总会被执行。

-->

  1.     <target name="clean">  
  2.         <delete dir="${classes.dir}" />  
  3.         <delete dir="${temp.dir}" />  
  4.         <delete file="${target.dir}/${ant.project.name}.jar"/>  
  5.         <delete file="${target.dir}/${ant.project.name}.war"/>  
  6.         <delete dir="${target.dir}" />  
  7.     </target>  
  8.   

   <!-- 初始化任务 

(<mkdir )该标签用于创建一个目录,它有一个属性dir用来指定所创建的目录名,其代码如下:<mkdir dir=”${class.root}”/>通过以上代码就创建了一个目录,这个目录已经被前面的property标签所指定。 

-->  

  1.     <target name="init" depends="clean">  
  2.         <mkdir dir="${target.dir}" />  
  3.         <mkdir dir="${temp.dir}" />  
  4.         <mkdir dir="${classes.dir}" />  
  5.     </target>  
  6.   

   <!-- 编译 -->  

  1.     <target name="compile" depends="init" description="compile the source files">  
  2.         <javac srcdir="${src.dir}" destdir="${classes.dir}"  debug="true" encoding="GB2312">  
  3.             <classpath refid="master-classpath" />  
  4.         </javac>  
  5.         <copy todir="${classes.dir}" overwrite="true">  
  6.             <fileset dir="${src.dir}">  
  7.                 <include name="**/*.xml" />  
  8.                 <include name="**/*.properties" />  
  9.             </fileset>  
  10.         </copy>  
  11.     </target>  
  12.   

 <!--打jar包-->  

  1.     <target name="jar" depends="compile">  
  2.         <jar jarfile="${target.dir}/${ant.project.name}.jar">  
  3.             <fileset dir="${classes.dir}">  
  4.                 <include name="**/*" />  
  5.             </fileset>  
  6.         </jar>  
  7.     </target>  
  8.   
  9.     <target name="preWar" depends="jar">  
  10.         <copy todir="${temp.dir}/WEB-INF/lib" overwrite="true">  
  11.             <fileset dir="${target.dir}">  
  12.                 <include name="${ant.project.name}.jar"/>  
  13.             </fileset>  
  14.         </copy>  
  15.         <copy todir="${temp.dir}" overwrite="true">  
  16.             <fileset dir="${basedir}">  
  17.                 <include name="${lib.dir}/*.jar" />  
  18.                 <include name="index.html" />  
  19.                 <include name="page/**/*.*" />  
  20.                 <include name="WEB-INF/*.xml" />  
  21.             </fileset>  
  22.         </copy>  
  23.     </target>  
  24.        

  <!--打war包-->  

  1.     <target name="war" depends="preWar">  
  2.         <jar jarfile="${target.dir}/${ant.project.name}.war">  
  3.             <fileset dir="${temp.dir}">  
  4.                 <include name="**/*.*"/>  
  5.             </fileset>  
  6.         </jar>       
  7.     </target>  
  8.   
  9.     <target name="all" depends="war">  
  10.         <delete dir="${temp.dir}"/>  
  11.     </target>  
  12.   
  13. </project>  




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值