Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android開發常用功能

Android開發常用功能

編輯:關於Android編程

1.定時器的實現

(1)采用Handler的postDelayed(Runnable, long)方法

 

Handler handler = new Handler();  
Runnable runnable = new Runnable() {  
      
    @Override  
    public void run() {  
        //你要做的事  
        //......  
        System.out.println(Thread.currentThread().getName());  
        handler.postDelayed(runnable, 1000);  
    }  
};

public final booleanpostDelayed(Runnabler, long delayMillis)Added inAPI level 1

Causes the Runnable r to be added to the message queue, to be run after the specified amount of time elapses. The runnable will be run on the thread to which this handler is attached.The time-base isuptimeMillis().Time spent in deep sleep will add an additional delay to execution.

後調用handler.post(runnable);就能啟動定時器,這裡是每隔1s打印線程名字,從打印中我們可以知道,他並沒有另開線程,而是運行在UI線程當中,當你要取消定時器的時候,只需要調用handler.removeCallbacks(runnable)就可以了。

上面中有一個問題,有時候你會發現removeCallbacks有時候會失效,不能從消息隊列中移除,看下面的demo

\

 

圖:兩個按鈕,一個將Runnable加到消息隊列中,一個將Runnable從消息隊列中移除。該Runnable每1秒鐘打印一次日志。

 

public class TimerActivity extends Activity{  
    Handler handler = new Handler();  
    Runnable runnable = new Runnable() {  
          
        @Override  
        public void run() {  
            System.out.println("update...");  
            handler.postDelayed(runnable, 1000);  
        }  
    };  
  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.timer);  
          
        Button mButtonStart = (Button) findViewById(R.id.button1);  
        Button mButtonStop = (Button) findViewById(R.id.button2);  
          
        mButtonStart.setOnClickListener(new OnClickListener() {  
              
            @Override  
            public void onClick(View v) {  
                handler.post(runnable);  
            }  
        });  
          
        mButtonStop.setOnClickListener(new OnClickListener() {  
              
            @Override  
            public void onClick(View v) {  
                handler.removeCallbacks(runnable);  
            }  
        });  
    }  
      
}

結果:
(1)start –> 輸出 –> stop–> 停止輸出
(2)start –> 輸出 –> Background –> Front –> stop->繼續輸出

當Activity進入後台運行後再轉入前台運行,removeCallbacks無法將updateThread從message queue中移除。
這是為什麼呢?
在Activity由前台轉後台過程中,線程是一直在運行的,但是當Activity轉入前台時會重新定義Runnable runnable;也就是說此時從message queue移除的runnable與原先加入message queue中的runnable並非是同一個對象。如果把runnable定義為靜態的則removeCallbacks不會失效,對於靜態變量在內存中只有一個拷貝(節省內存),JVM只為靜態分配一次內存,在加載類的過程中完成靜態變量的內存分配,我們做如下修改就能解決上面的這個問題.

static Handler handler = new Handler();  
static Runnable runnable = new Runnable() {  
      
    @Override  
    public void run() {  
        System.out.println("update...");  
        handler.postDelayed(runnable, 1000);  
    }  
}; 

(2)采用Handler與timer及TimerTask結合的方法。

1.定義定時器、定時器任務及Handler句柄

private final Timer timer = new Timer();
private TimerTask task;
Handler handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        // TODO Auto-generated method stub
        //要做的事情
        super.handleMessage(msg);
    }

};

2.初始化定時器任務。

task=new TimerTask() {
    @Override
    public void run () {
        // TODO Auto-generated method stub
        Message message = new Message();
        message.what = 1;
        handler.sendMessage(message);
    }
};

3.啟動定時器

timer.schedule(task, 2000, 2000);

簡要說一下上面三步提到的一些內容。
1.定時器任務(TimerTask)顧名思義,就是說當定時器到達指定的時間時要做的工作,這裡是想Handler發送一個消息,由Handler類進行處理。
2. java.util.Timer.schedule(TimerTask task, long delay):這個方法是說,dalay/1000秒後執行task.只執行一次。
java.util.Timer.schedule(TimerTask task, long delay, long period):這個方法是說,delay/1000秒後執行task,然後進過period/1000秒再次執行task,這個用於循環任務,執行無數次,當然,你可以用timer.cancel();取消定時器的執行。

(3)采用Handle與線程的sleep(long )方法

1.定義一個Handler類,用於處理接受到的Message

Handler handler = new Handler() {  
        public void handleMessage(Message msg) {  
            super.handleMessage(msg);  
            System.out.println("update...");  
        }  
    }  

2.新建一個實現Runnable接口的線程類,用一個boolean 來控制線程開始和結束 boolean isLive = true如下:

public class MyThread implements Runnable {  
        @Override  
        public void run() {  
            while (isLive) {  
                try {  
                    Thread.sleep(1000);// 線程暫停1秒,單位毫秒  
                    Message message = new Message();  
                    message.what = 1;  
                    handler.sendMessage(message);// 發送消息  
                } catch (InterruptedException e) {  
                    e.printStackTrace();  
                }  
            }  
        }  
    }  
3.在需要啟動線程的地方加入下面語句
new Thread(new MyThread()).start();  

4.取消的話將isLive設置為false就行了

2.Android延時操作

下面是三種方法:

跟上面的定時操作異曲同工

一、線程

 new Thread(new Runnable(){    
     public void run(){    
         Thread.sleep(XXXX);    
         handler.sendMessage();----告訴主線程執行任務    
     }    
 }).start   

二、延時器

TimerTask task = new TimerTask(){    
     public void run(){    
     //execute the task     
     }    
 };    
 Timer timer = new Timer();  
 timer.schedule(task, delay);  

三、android消息處理

new Handler().postDelayed(new Runnable(){    
    public void run() {    
    //execute the task    
    }    
 }, delay); 

3.數據加密

參考:

android 隱私數據加密方法

Facebook推出用於android數據加密的開源API

Java常用的加密方法

Android應用安全開發之淺談加密算法的坑

為了確保數據傳輸和數據存儲的安全,我們可以通過特定的算法,將數據明文加密成復雜的密文。
眾多的加密手段大致可以分為單項加密雙向加密單向加密指通過對數據進行摘要計算生成密文,密文不可逆推還原,比如有Base64、MD5、SHA等;雙向加密則相反,指可以把密文逆推還原成明文,其中雙向加密又分為對稱加密非對稱加密對稱加密是指數據使用者必須擁有同樣的密鑰才可以進行加密解密,就像大家共同約定了一組暗號一樣,對稱加密的手段有DES、3DES、AES、IDEA、RC4、RC5等;而非對稱加密相對於對稱加密而言,無需擁有同一組密鑰,它是一種“信息公開的密鑰交換協議”。非對稱加密需要公開密鑰和私有密鑰兩組密鑰,公開密鑰和私有密鑰是配對起來的,也就是說使用公開密鑰進行數據加密,只有對應的私有密鑰才能進行解密。此類的加密手段有RSA、DSA等。


【密碼學常用術語】
明文:未加密的數據
密文:明文經過加密後的數據
加密:將明文轉換為密文的過程
解密:將密文轉換為明文的過程
加密算法:將明文轉換為密文的轉換算法
解密算法:將密文轉換為明文的轉換算法
加密密鑰:用於加密算法進行加密操作的密鑰
解密密鑰:用於解密算法進行解密操作的密鑰

 

單向加密(信息摘要)

 

Java一般需要獲取對象MessageDigest來實現單項加密(信息摘要)。
1.MD5

即Message-Digest Algorithm 5(信息-摘要算法 5),用於確保信息傳輸完整一致。是計算機廣泛使用的雜湊算法之一(又譯摘要算法、哈希算法),主流編程語言普遍已有MD5實現。將數據(如漢字)運算為另一固定長度值,是雜湊算法的基礎原理,MD5的前身有MD2、MD3和MD4。MD5的作用是讓大容量信息在用數字簽名軟件簽署私人密鑰前被"壓縮"成一種保密的格式(就是把一個任意長度的字節串變換成一定長的十六進制數字串)。
除了MD5以外,其中比較有名的還有sha-1、RIPEMD以及Haval等

import java.security.MessageDigest;  
import java.security.NoSuchAlgorithmException;  
  
public class EncrypMD5 {  
      
    public byte[] eccrypt(String info) throws NoSuchAlgorithmException{  
        //根據MD5算法生成MessageDigest對象  
        MessageDigest md5 = MessageDigest.getInstance("MD5");  
        byte[] srcBytes = info.getBytes();  
        //使用srcBytes更新摘要  
        md5.update(srcBytes);  
        //完成哈希計算,得到result  
        byte[] resultBytes = md5.digest();  
        return resultBytes;  
    }  
       
    public static void main(String args[]) throws NoSuchAlgorithmException{  
        String msg = "郭XX-精品相聲技術";  
        EncrypMD5 md5 = new EncrypMD5();  
        byte[] resultBytes = md5.eccrypt(msg);  
          
        System.out.println("密文是:" + new String(resultBytes));  
        System.out.println("明文是:" + msg);  
    }  
  
}


2.SHA

是一種數據加密算法,該算法經過加密專家多年來的發展和改進已日益完善,現在已成為公認的最安全的散列算法之一,並被廣泛使用。該算法的思想是接收一段明文,然後以一種不可逆的方式將它轉換成一段(通常更小)密文,也可以簡單的理解為取一串輸入碼(稱為預映射或信息),並把它們轉化為長度較短、位數固定的輸出序列即散列值(也稱為信息摘要或信息認證代碼)的過程。散列函數值可以說時對明文的一種“指紋”或是“摘要”所以對散列值的數字簽名就可以視為對此明文的數字簽名。

import java.security.MessageDigest;  
import java.security.NoSuchAlgorithmException;  
  
public class EncrypSHA {  
      
    public byte[] eccrypt(String info) throws NoSuchAlgorithmException{  
        MessageDigest md5 = MessageDigest.getInstance("SHA");  
        byte[] srcBytes = info.getBytes();  
        //使用srcBytes更新摘要  
        md5.update(srcBytes);  
        //完成哈希計算,得到result  
        byte[] resultBytes = md5.digest();  
        return resultBytes;  
    }  
  
    /** 
     * @param args 
     * @throws NoSuchAlgorithmException  
     */  
    public static void main(String[] args) throws NoSuchAlgorithmException {  
        String msg = "郭XX-精品相聲技術";  
        EncrypSHA sha = new EncrypSHA();  
        byte[] resultBytes = sha.eccrypt(msg);  
        System.out.println("明文是:" + msg);  
        System.out.println("密文是:" + new String(resultBytes));  
          
    }  
  
} 

雙向加密

(一)、對稱加密

采用單鑰密碼系統的加密方法,同一個密鑰可以同時用作信息的加密和解密,這種加密方法稱為對稱加密,也稱為單密鑰加密。需要對加密和解密使用相同密鑰的加密算法。由於其速度,對稱性加密通常在消息發送方需要加密大量數據時使用。

對稱性加密也稱為密鑰加密。所謂對稱,就是采用這種加密方法的雙方使用方式用同樣的密鑰進行加密和解密。密鑰是控制加密及解密過程的指令。

算法是一組規則,規定如何進行加密和解密。因此對稱式加密本身不是安全的。
常用的對稱加密有:DES、IDEA、RC2、RC4、SKIPJACK、RC5、AES算法等

對稱加密一般java類中中定義成員

Java代碼

//KeyGenerator 提供對稱密鑰生成器的功能,支持各種算法  
private KeyGenerator keygen;  
//SecretKey 負責保存對稱密鑰  
private SecretKey deskey;  
//Cipher負責完成加密或解密工作  
private Cipher c;  
//該字節數組負責保存加密的結果  
private byte[] cipherByte;  

在構造函數中初始化

Java代碼

1.Security.addProvider(new com.sun.crypto.provider.SunJCE());  
2.//實例化支持DES算法的密鑰生成器(算法名稱命名需按規定,否則拋出異常)  
3.keygen = KeyGenerator.getInstance("DES");//  
4.//生成密鑰  
5.deskey = keygen.generateKey();  
6.//生成Cipher對象,指定其支持的DES算法  
7.c = Cipher.getInstance("DES");  

1.DES算法為密碼體制中的對稱密碼體制,又被成為美國數據加密標准,是1972年美國IBM公司研制的對稱密碼體制加密算法。 明文按64位進行分組, 密鑰長64位,密鑰事實上是56位參與DES運算(第8、16、24、32、40、48、56、64位是校驗位, 使得每個密鑰都有奇數個1)分組後的明文組和56位的密鑰按位替代或交換的方法形成密文組的加密方法。

Java代碼

import java.security.InvalidKeyException;  
import java.security.NoSuchAlgorithmException;  
import java.security.Security;  

import javax.crypto.BadPaddingException;  
import javax.crypto.Cipher;  
import javax.crypto.IllegalBlockSizeException;  
import javax.crypto.KeyGenerator;  
import javax.crypto.NoSuchPaddingException;  
import javax.crypto.SecretKey;  

public class EncrypDES {  

    //KeyGenerator 提供對稱密鑰生成器的功能,支持各種算法  
    private KeyGenerator keygen;  
    //SecretKey 負責保存對稱密鑰  
    private SecretKey deskey;  
    //Cipher負責完成加密或解密工作  
    private Cipher c;  
    //該字節數組負責保存加密的結果  
    private byte[] cipherByte;  

    public EncrypDES() throws NoSuchAlgorithmException, NoSuchPaddingException{  
        Security.addProvider(new com.sun.crypto.provider.SunJCE());  
        //實例化支持DES算法的密鑰生成器(算法名稱命名需按規定,否則拋出異常)  
        keygen = KeyGenerator.getInstance("DES");  
        //生成密鑰  
        deskey = keygen.generateKey();  
        //生成Cipher對象,指定其支持的DES算法  
        c = Cipher.getInstance("DES");  
    }  

    /** 
     * 對字符串加密 
     *  
     * @param str 
     * @return 
     * @throws InvalidKeyException 
     * @throws IllegalBlockSizeException 
     * @throws BadPaddingException 
     */  
    public byte[] Encrytor(String str) throws InvalidKeyException,  
            IllegalBlockSizeException, BadPaddingException {  
    // 根據密鑰,對Cipher對象進行初始化,ENCRYPT_MODE表示加密模式  
        c.init(Cipher.ENCRYPT_MODE, deskey);  
        byte[] src = str.getBytes();  
        // 加密,結果保存進cipherByte  
        cipherByte = c.doFinal(src);  
        return cipherByte;  
    }  

    /** 
     * 對字符串解密 
     *  
     * @param buff 
     * @return 
     * @throws InvalidKeyException 
     * @throws IllegalBlockSizeException 
     * @throws BadPaddingException 
     */  
    public byte[] Decryptor(byte[] buff) throws InvalidKeyException,  
        IllegalBlockSizeException, BadPaddingException {  
        // 根據密鑰,對Cipher對象進行初始化,DECRYPT_MODE表示加密模式  
        c.init(Cipher.DECRYPT_MODE, deskey);  
        cipherByte = c.doFinal(buff);  
        return cipherByte;  
    }  

    /** 
     * @param args 
     * @throws NoSuchPaddingException  
     * @throws NoSuchAlgorithmException  
     * @throws BadPaddingException  
     * @throws IllegalBlockSizeException  
     * @throws InvalidKeyException  
     */  
    public static void main(String[] args) throws Exception {  
        EncrypDES de1 = new EncrypDES();  
        String msg ="郭XX-搞笑相聲全集";  
        byte[] encontent = de1.Encrytor(msg);  
        byte[] decontent = de1.Decryptor(encontent);  
        System.out.println("明文是:" + msg);  
        System.out.println("加密後:" + new String(encontent));  
        System.out.println("解密後:" + new String(decontent));  
    }   
}

2.3DES

3DES(即Triple DES)是DES向AES過渡的加密算法(1999年,NIST將3-DES指定為過渡的加密標准),是DES的一個更安全的變形。它以DES為基本模塊,通過組合分組方法設計出分組加密算法,其具體實現如下:
設Ek()和Dk()代表DES算法的加密和解密過程,K代表DES算法使用的密鑰,P代表明文,C代表密文,
這樣,   
3DES加密過程為:C=Ek3(Dk2(Ek1(P)))
3DES解密過程為:P=Dk1((EK2(Dk3(C)))

又稱Triple DES,是DES加密算法的一種模式,它使用3條56位的密鑰對3DES 數據進行三次加密。數據加密標准(DES)是美國的一種由來已久的加密標准,它使用對稱密鑰加密法,並於1981年被ANSI組織規范為ANSI X.3.92。DES使用56位密鑰和密碼塊的方法,而在密碼塊的方法中,文本被分成64位大小的文本塊然後再進行加密。比起最初的DES,3DES更為安全。   

import java.security.InvalidKeyException;  
import java.security.NoSuchAlgorithmException;  
import java.security.Security;  

import javax.crypto.BadPaddingException;  
import javax.crypto.Cipher;  
import javax.crypto.IllegalBlockSizeException;  
import javax.crypto.KeyGenerator;  
import javax.crypto.NoSuchPaddingException;  
import javax.crypto.SecretKey;  

public class EncrypDES3 {  

    // KeyGenerator 提供對稱密鑰生成器的功能,支持各種算法  
    private KeyGenerator keygen;  
    // SecretKey 負責保存對稱密鑰  
    private SecretKey deskey;  
    // Cipher負責完成加密或解密工作  
    private Cipher c;  
    // 該字節數組負責保存加密的結果  
    private byte[] cipherByte;  

    public EncrypDES3() throws NoSuchAlgorithmException, NoSuchPaddingException {  
        Security.addProvider(new com.sun.crypto.provider.SunJCE());  
        // 實例化支持DES算法的密鑰生成器(算法名稱命名需按規定,否則拋出異常)  
        keygen = KeyGenerator.getInstance("DESede");  
        // 生成密鑰  
        deskey = keygen.generateKey();  
        // 生成Cipher對象,指定其支持的DES算法  
        c = Cipher.getInstance("DESede");  
    }  

    /** 
     * 對字符串加密 
     *  
     * @param str 
     * @return 
     * @throws InvalidKeyException 
     * @throws IllegalBlockSizeException 
     * @throws BadPaddingException 
     */  
    public byte[] Encrytor(String str) throws InvalidKeyException,  
            IllegalBlockSizeException, BadPaddingException {  
        // 根據密鑰,對Cipher對象進行初始化,ENCRYPT_MODE表示加密模式  
        c.init(Cipher.ENCRYPT_MODE, deskey);  
        byte[] src = str.getBytes();  
        // 加密,結果保存進cipherByte  
        cipherByte = c.doFinal(src);  
        return cipherByte;  
    }  

    /** 
     * 對字符串解密 
     *  
     * @param buff 
     * @return 
     * @throws InvalidKeyException 
     * @throws IllegalBlockSizeException 
     * @throws BadPaddingException 
     */  
    public byte[] Decryptor(byte[] buff) throws InvalidKeyException,  
            IllegalBlockSizeException, BadPaddingException {  
        // 根據密鑰,對Cipher對象進行初始化,DECRYPT_MODE表示加密模式  
        c.init(Cipher.DECRYPT_MODE, deskey);  
        cipherByte = c.doFinal(buff);  
        return cipherByte;  
    }  

    /** 
     * @param args 
     * @throws NoSuchPaddingException  
     * @throws NoSuchAlgorithmException  
     * @throws BadPaddingException  
     * @throws IllegalBlockSizeException  
     * @throws InvalidKeyException  
     */  
    public static void main(String[] args) throws Exception {  
        EncrypDES3 des = new EncrypDES3();  
        String msg ="郭XX-搞笑相聲全集";  
        byte[] encontent = des.Encrytor(msg);  
        byte[] decontent = des.Decryptor(encontent);  
        System.out.println("明文是:" + msg);  
        System.out.println("加密後:" + new String(encontent));  
        System.out.println("解密後:" + new String(decontent));  

    }  

}

3.AES

密碼學中的高級加密標准(Advanced Encryption Standard,AES),又稱 高級加密標准 Rijndael加密法,是美國聯邦政府采用的一種區塊加密標准。這個標准用來替代原先的DES,已經被多方分析且廣為全世界所使用。經過五年的甄選流程,高級加密標准由美國國家標准與技術研究院(NIST)於2001年11月26日發布於FIPS PUB 197,並在2002年5月26日成為有效的標准。2006年,高級加密標准已然成為對稱密鑰加密中最流行的算法之一。   

該算法為比利時密碼學家Joan Daemen和Vincent Rijmen所設計,結合兩位作者的名字,以Rijndael之命名之,投稿高級加密標准的甄選流程。(Rijdael的發音近於 "Rhinedoll"。)

import java.security.InvalidKeyException;  
import java.security.NoSuchAlgorithmException;  
import java.security.Security;  

import javax.crypto.BadPaddingException;  
import javax.crypto.Cipher;  
import javax.crypto.IllegalBlockSizeException;  
import javax.crypto.KeyGenerator;  
import javax.crypto.NoSuchPaddingException;  
import javax.crypto.SecretKey;  

public class EncrypAES {  

    //KeyGenerator 提供對稱密鑰生成器的功能,支持各種算法  
    private KeyGenerator keygen;  
    //SecretKey 負責保存對稱密鑰  
    private SecretKey deskey;  
    //Cipher負責完成加密或解密工作  
    private Cipher c;  
    //該字節數組負責保存加密的結果  
    private byte[] cipherByte;  

    public EncrypAES() throws NoSuchAlgorithmException, NoSuchPaddingException{  
        Security.addProvider(new com.sun.crypto.provider.SunJCE());  
        //實例化支持DES算法的密鑰生成器(算法名稱命名需按規定,否則拋出異常)  
        keygen = KeyGenerator.getInstance("AES");  
        //生成密鑰  
        deskey = keygen.generateKey();  
        //生成Cipher對象,指定其支持的DES算法  
        c = Cipher.getInstance("AES");  
    }  

    /** 
     * 對字符串加密 
     *  
     * @param str 
     * @return 
     * @throws InvalidKeyException 
     * @throws IllegalBlockSizeException 
     * @throws BadPaddingException 
     */  
    public byte[] Encrytor(String str) throws InvalidKeyException,  
        IllegalBlockSizeException, BadPaddingException {  
        // 根據密鑰,對Cipher對象進行初始化,ENCRYPT_MODE表示加密模式  
        c.init(Cipher.ENCRYPT_MODE, deskey);  
        byte[] src = str.getBytes();  
        // 加密,結果保存進cipherByte  
        cipherByte = c.doFinal(src);  
        return cipherByte;  
    }  

    /** 
     * 對字符串解密 
     *  
     * @param buff 
     * @return 
     * @throws InvalidKeyException 
     * @throws IllegalBlockSizeException 
     * @throws BadPaddingException 
     */  
    public byte[] Decryptor(byte[] buff) throws InvalidKeyException,  
        IllegalBlockSizeException, BadPaddingException {  
        // 根據密鑰,對Cipher對象進行初始化,DECRYPT_MODE表示加密模式  
        c.init(Cipher.DECRYPT_MODE, deskey);  
        cipherByte = c.doFinal(buff);  
        return cipherByte;  
    }  

    /** 
     * @param args 
     * @throws NoSuchPaddingException  
     * @throws NoSuchAlgorithmException  
     * @throws BadPaddingException  
     * @throws IllegalBlockSizeException  
     * @throws InvalidKeyException  
     */  
    public static void main(String[] args) throws Exception {  
        EncrypAES de1 = new EncrypAES();  
        String msg ="郭XX-搞笑相聲全集";  
        byte[] encontent = de1.Encrytor(msg);  
        byte[] decontent = de1.Decryptor(encontent);  
        System.out.println("明文是:" + msg);  
        System.out.println("加密後:" + new String(encontent));  
        System.out.println("解密後:" + new String(decontent));  
    }  

}

(二)、非對稱加密

1976年,美國學者Dime和Henman為解決信息公開傳送和密鑰管理問題,提出一種新的密鑰交換協議,允許在不安全的媒體上的通訊雙方交換信息,安全地達成一致的密鑰,這就是“公開密鑰系統”。相對於“對稱加密算法”這種方法也叫做“非對稱加密算法”。 與對稱加密算法不同,非對稱加密算法需要兩個密鑰:公開密鑰(publickey)和私有密鑰 (privatekey)。公開密鑰與私有密鑰是一對,如果用公開密鑰對數據進行加密,只有用對應的私有密鑰才能解密;如果用私有密鑰對數據進行加密,那麼只有用對應的公開密鑰才能解密。因為加密和解密使用的是兩個不同的密鑰,所以這種算法叫作非對稱加密算法。

1.RSA

公鑰加密算法是1977年由Ron Rivest、Adi Shamirh和LenAdleman在(美國麻省理工學院)開發的。RSA取名來自開發他們三者的名字。RSA是目前最有影響力的公鑰加密算法,它能夠抵抗到目前為止已知的所有密碼攻擊,已被ISO推薦為公鑰數據加密標准。RSA算法基於一個十分簡單的數論事實:將兩個大素數相乘十分容易,但那時想要對其乘積進行因式分解卻極其困難,因此可以將乘積公開作為加密密鑰。

import java.security.InvalidKeyException;  
import java.security.KeyPair;  
import java.security.KeyPairGenerator;  
import java.security.NoSuchAlgorithmException;  
import java.security.interfaces.RSAPrivateKey;  
import java.security.interfaces.RSAPublicKey;  

import javax.crypto.BadPaddingException;  
import javax.crypto.Cipher;  
import javax.crypto.IllegalBlockSizeException;  
import javax.crypto.NoSuchPaddingException;  

public class EncrypRSA {  

    /** 
     * 加密 
     * @param publicKey 
     * @param srcBytes 
     * @return 
     * @throws NoSuchAlgorithmException 
     * @throws NoSuchPaddingException 
     * @throws InvalidKeyException 
     * @throws IllegalBlockSizeException 
     * @throws BadPaddingException 
     */  
    protected byte[] encrypt(RSAPublicKey publicKey,byte[] srcBytes) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException{  
        if(publicKey!=null){  
            //Cipher負責完成加密或解密工作,基於RSA  
            Cipher cipher = Cipher.getInstance("RSA");  
            //根據公鑰,對Cipher對象進行初始化  
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);  
            byte[] resultBytes = cipher.doFinal(srcBytes);  
            return resultBytes;  
        }  
        return null;  
    }  

    /** 
     * 解密  
     * @param privateKey 
     * @param srcBytes 
     * @return 
     * @throws NoSuchAlgorithmException 
     * @throws NoSuchPaddingException 
     * @throws InvalidKeyException 
     * @throws IllegalBlockSizeException 
     * @throws BadPaddingException 
     */  
    protected byte[] decrypt(RSAPrivateKey privateKey,byte[] srcBytes) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException{  
        if(privateKey!=null){  
            //Cipher負責完成加密或解密工作,基於RSA  
            Cipher cipher = Cipher.getInstance("RSA");  
            //根據公鑰,對Cipher對象進行初始化  
            cipher.init(Cipher.DECRYPT_MODE, privateKey);  
            byte[] resultBytes = cipher.doFinal(srcBytes);  
            return resultBytes;  
        }  
        return null;  
    }  

    /** 
     * @param args 
     * @throws NoSuchAlgorithmException  
     * @throws BadPaddingException  
     * @throws IllegalBlockSizeException  
     * @throws NoSuchPaddingException  
     * @throws InvalidKeyException  
     */  
    public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {  
        EncrypRSA rsa = new EncrypRSA();  
        String msg = "郭XX-精品相聲";  
        //KeyPairGenerator類用於生成公鑰和私鑰對,基於RSA算法生成對象  
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");  
        //初始化密鑰對生成器,密鑰大小為1024位  
        keyPairGen.initialize(1024);  
        //生成一個密鑰對,保存在keyPair中  
        KeyPair keyPair = keyPairGen.generateKeyPair();  
        //得到私鑰  
        RSAPrivateKey privateKey = (RSAPrivateKey)keyPair.getPrivate();               
        //得到公鑰  
        RSAPublicKey publicKey = (RSAPublicKey)keyPair.getPublic();  

        //用公鑰加密  
        byte[] srcBytes = msg.getBytes();  
        byte[] resultBytes = rsa.encrypt(publicKey, srcBytes);  

        //用私鑰解密  
        byte[] decBytes = rsa.decrypt(privateKey, resultBytes);  

        System.out.println("明文是:" + msg);  
        System.out.println("加密後是:" + new String(resultBytes));  
        System.out.println("解密後是:" + new String(decBytes));  
    }  
}

2.DSA

Digital Signature Algorithm (DSA)是Schnorr和ElGamal簽名算法的變種,被美國NIST作為DSS(DigitalSignature Standard)。(感覺有點復雜,沒有附代碼)
詳見http://63938525.iteye.com/blog/1051565

參考:
android 隱私數據加密方法
Facebook推出用於android數據加密的開源API
Java常用的加密方法
Android應用安全開發之淺談加密算法的坑

4.設置圓角按鈕和邊框

圓角的按鈕實現扁平化的UI很有美感,但是實現起來也不算太難。

在res目錄下的drawable-mdpi建立xml文件shape.xml,如下圖所示:


\


Shapeone.xml(圓角)

 
 
     
     
     
     
     
 
 
 

Shapetwo.xml (邊框)

  

2.在要設置邊框的控件xml命令裡加入:android:background=“@drawable/boder

 

main.xml

在android:background="@drawable/shape"就使用了shape.xml資源

 
 

strings.xml

 
 
    Hello World, RoundButtonDemoActivity! 
    RoundButtonDemo 
 

 

5.android studio 設備調試及Logcat查看

 

現在android的開發工具基本上都改用android studio而慢慢棄用eclipse了,那麼android studio的調試設備該怎麼設置和查看程序的Logcat呢?

首先點擊項目上方app右邊的小箭頭,然後選擇"Edit Configurations...",如下圖:

\

然後選擇
\

Show chooser dialog : 彈出窗口,可選擇真機調試或虛擬機調試。

Use same device for futrue launches : 選中的話,當下次調試時,會使用之前相同的調試方式。

USB device : 使用真機調試。

Emulator : 使用虛擬機調試。

Prefer Android Virtual Device : 可選擇已經存在的虛擬機,點擊右邊"..." 彈出AVD Manager(要在選擇Emulator後才可點擊)。

當程序運行後,我們需要在調試的時候查看Logcat的信息,點擊android studio 底部的Android按鈕,會彈出一個調試的窗口。

\

在Device欄中,可以看到當前連接的可調試的設備,有時候設備連接USB後,並沒有顯示出來,這個時候可以在這裡查看。

當需要查看程序運行的Logcat時,可以點擊窗口右上角的android圖標,程序運行的信息都在這裡。

\

Android 中的日志工具類是 Log(android.util.Log),這個類中提供了如下幾個方法來供我們打印日志。

1. Log.v()這個方法用於打印那些最為瑣碎的,意義最小的日志信息。對應級別 verbose,是 Android日志裡面級別最低的一種。

2. Log.d()這個方法用於打印一些調試信息,這些信息對你調試程序和分析問題應該是有幫助 的。對應級別 debug,比 verbose高一級。

3. Log.i()這個方法用於打印一些比較重要的數據,這些數據應該是你非常想看到的,可以幫你分析用戶行為的那種。對應級別 info,比 debug高一級。

4. Log.w()這個方法用於打印一些警告信息,提示程序在這個地方可能會有潛在的風險,最好 去修復一下這些出現警告的地方。對應級別 warn,比 info高一級。

5. Log.e()這個方法用於打印程序中的錯誤信息,比如程序進入到了 catch語句當中。當有錯 誤信息打印出來的時候,一般都代表你的程序出現嚴重問題了,必須盡快修復。

對應級別 error,比 warn高一級。 其實很簡單,一共就五個方法,當然每個方法還會有不同的重載,但那對你來說肯定不 是什麼難理解的地方了。我們現在就在 HelloWorld項目中試一試日志工具好不好用吧。 打開 HelloWorldActivity,在 onCreate()方法中添加一行打印日志的語句,如下所示:

 

protected void onCreate(Bundle savedInstanceState) { 
super.onCreate(savedInstanceState); 
setContentView(R.layout.hello_world_layout); 
Log.d("HelloWorldActivity", "onCreate execute"); 
} 

 

Log.d方法中傳入了兩個參數,第一個參數是 tag,一般傳入當前的類名就好,主要用於對打印信息進行過濾。第二個參數是 msg,即想要打印的具體的內容.

6.雙擊退出程序

通過計算時間差實現

這裡是通過控制時間差來實現功能的,在首次按下返回鍵時,將會將當期時間賦值給mPressedTime並通過Toast提示用戶,在第二次按下返回鍵時,如果與 mPressedTime記錄的時間差值大於2秒則重新刷新mPressedTime的時間,如果小於2秒則執行else的語句退出程序。

private long mPressedTime = 0;

@Override
public void onBackPressed() {
    long mNowTime = System.currentTimeMillis();//獲取第一次按鍵時間
    if ((mNowTime - mPressedTime) > 2000) {//比較兩次按鍵時間差
        Toast.makeText(this, "再按一次退出程序", Toast.LENGTH_SHORT).show();
        mPressedTime = mNowTime;
    }else{//退出程序
        this.finish();
        System.exit(0);
    }
}

7.線程

7.1Android中檢測當前是否為主線程

如果在Android中判斷某個線程是否是主線程?對於這個問題,你可能說根據線程的名字,當然這個可以解決問題,但是這樣是最可靠的麼?萬一某天Google一下子將線程的名字改稱其他神馬東西呢。

方法揭曉

下面的方法是最可靠的解決方案。

\

原理都一樣:

\

7.2線程的狀態(State)

新生狀態(New):當一個線程的實例被創建即使用new關鍵字和Thread類或其子類創建一個線程對象後,此時該線程處於新生(new)狀態,處於新生狀態的線程有自己的內存空間,但該線程並沒有運行,此時線程還不是活著的(not alive);

就緒狀態(Runnable):通過調用線程實例的start()方法來啟動線程使線程進入就緒狀態(runnable);處於就緒狀態的線程已經具備了運行條件,但還沒有被分配到CPU即不一定會被立即執行,此時處於線程就緒隊列,等待系統為其分配CPCU,等待狀態並不是執行狀態;此時線程是活著的(alive);

運行狀態(Running):一旦獲取CPU(被JVM選中),線程就進入運行(running)狀態,線程的run()方法才開始被執行;在運行狀態的線程執行自己的run()方法中的操作,直到調用其他的方法而終止、或者等待某種資源而阻塞、或者完成任務而死亡;如果在給定的時間片內沒有執行結束,就會被系統給換下來回到線程的等待狀態;此時線程是活著的(alive);

阻塞狀態(Blocked):通過調用join()、sleep()、wait()或者資源被暫用使線程處於阻塞(blocked)狀態;處於Blocking狀態的線程仍然是活著的(alive)

死亡狀態(Dead)當一個線程的run()方法運行完畢或被中斷或被異常退出,該線程到達死亡(dead)狀態。此時可能仍然存在一個該Thread的實例對象,當該Thread已經不可能在被作為一個可被獨立執行的線程對待了,線程的獨立的call stack已經被dissolved。一旦某一線程進入Dead狀態,他就再也不能進入一個獨立線程的生命周期了。對於一個處於Dead狀態的線程調用start()方法,會出現一個運行期(runtime exception)的異常;處於Dead狀態的線程不是活著的(not alive)。

線程狀態圖

\

 

7.3線程的方法(Method)、屬性(Property)

1)優先級(priority)

每個類都有自己的優先級,一般property用1-10的整數表示,默認優先級是5,優先級最高是10;優先級高的線程並不一定比優先級低的線程執行的機會高,只是執行的機率高;默認一個線程的優先級和創建他的線程優先級相同;

 

2)Thread.sleep()/sleep(long millis)

當前線程睡眠/millis的時間(millis指定睡眠時間是其最小的不執行時間,因為sleep(millis)休眠到達後,無法保證會被JVM立即調度);sleep()是一個靜態方法(static method) ,所以他不會停止其他的線程也處於休眠狀態;線程sleep()時不會失去擁有的對象鎖。作用:保持對象鎖,讓出CPU,調用目的是不讓當前線程獨自霸占該進程所獲取的CPU資源,以留一定的時間給其他線程執行的機會;

 

3)Thread.yield()

讓出CPU的使用權,給其他線程執行機會、讓同等優先權的線程運行(但並不保證當前線程會被JVM再次調度、使該線程重新進入Running狀態),如果沒有同等優先權的線程,那麼yield()方法將不會起作用。

 

4)thread.join()

使用該方法的線程會在此之間執行完畢後再往下繼續執行。

 

5)object.wait()

當一個線程執行到wait()方法時,他就進入到一個和該對象相關的等待池(Waiting Pool)中,同時失去了對象的機鎖—暫時的,wait後還要返還對象鎖。當前線程必須擁有當前對象的鎖,如果當前線程不是此鎖的擁有者,會拋出IllegalMonitorStateException異常,所以wait()必須在synchronized block中調用。

 

6)object.notify()/notifyAll()

喚醒在當前對象等待池中等待的第一個線程/所有線程。notify()/notifyAll()也必須擁有相同對象鎖,否則也會拋出IllegalMonitorStateException異常。

 

7)Synchronizing Block

Synchronized Block/方法控制對類成員變量的訪問;Java中的每一個對象都有唯一的一個內置的鎖,每個Synchronized Block/方法只有持有調用該方法被鎖定對象的鎖才可以訪問,否則所屬線程阻塞;機鎖具有獨占性、一旦被一個Thread持有,其他的Thread就不能再擁有(不能訪問其他同步方法),方法一旦執行,就獨占該鎖,直到從該方法返回時才將鎖釋放,此後被阻塞的線程方能獲得該鎖,重新進入可執行狀態。

對於官方已經棄用不建議使用的方法沒有列舉,從這些方法中可以看出,目前的java線程生命周期有開始運行、睡眠、等待、中斷、暫停,但是沒有了重新開始。Java的線程是不能重啟的,也就是說,當線程的run()方法執行到最後一行,退出之後,這個線程就結束了,不能再通過start()方法重啟啟動這個線程,只能重新構造一個線程對象,再調用其start()方法來啟動,但這個對象和原來那個對象已經不同了。

線程在建立後並不馬上執行run方法中的代碼,而是處於等待狀態。線程處於等待狀態時,可以通過Thread類的方法來設置線程不各種屬性,如線程的優先級(setPriority)、線程名(setName)和線程的類型(setDaemon)等。當調用start方法後,線程開始執行run方法中的代碼。線程進入運行狀態。可以通過Thread類的isAlive方法來判斷線程是否處於運行狀態。當線程處於運行狀態時,isAlive返回true,當isAlive返回false時,可能線程處於等待狀態,也可能處於停止狀態。

public class LifeCycle extends Thread    
{    
    public void run()    
    {    
        int n = 0;    
        while ((++n) < 1000);            
    }    
         
    public static void main(String[] args) throws Exception    
    {    
        LifeCycle thread1 = new LifeCycle();    
        System.out.println("isAlive: " + thread1.isAlive());    
        thread1.start();    
        System.out.println("isAlive: " + thread1.isAlive());    
        thread1.join();  // 等線程thread1結束後再繼續執行     
        System.out.println("thread1已經結束!");    
        System.out.println("isAlive: " + thread1.isAlive());    
    }    
} 

要注意一下,在上面的代碼中使用了join方法,這個方法的主要功能是保證線程的run方法完成後程序才繼續運行,上面代碼的運行結果:

isAlive: false
isAlive: true
thread1已經結束!
isAlive: false

一但線程開始執行run方法,就會一直到這個run方法執行完成這個線程才退出。但在線程執行的過程中,可以通過兩個方法使線程暫時停止執行。這兩個方法是yield和sleep。thread.yield()在多線程程序中,為了防止某線程獨占CPU資源(這樣其它的線程就得不到"響應"了).可以讓當前執行的線程"休息"一下.但是這種thread.yield() 調用,並不保證下一個運行的線程就一定不是該線程.而使用sleep使線程休眠後,只能在設定的時間後使線程處於就緒狀態(在線程休眠結束後,線程不一定會馬上執行,只是進入了就緒狀態,等待著系統進行調度)。在使用sleep時要注意,不能在一個線程中來休眠另一個線程。如main方法中使用thread.sleep(2000)方法是無法使thread線程休眠2秒的,而只能使主線程休眠2秒。在使用sleep方法時有四點需要注意:

1. sleep方法有兩個重載形式,其中一個重載形式不僅可以設毫秒,而且還可以設納秒(1,000,000納秒等於1毫秒)。但大多數操作系統平台上的Java虛擬機都無法精確到納秒,因此,如果對sleep設置了納秒,Java虛擬機將取最接近這個值的毫秒。

2. 在使用sleep方法時必須使用throws或try{...}catch{...}。因為run方法無法使用throws,所以只能使用try{...}catch{...}。當在線程休眠的過程中,使用interrupt方法(這個方法將在2.3.3中討論)中斷線程時sleep會拋出一個InterruptedException異常。

3. sleep()使當前線程進入停滯狀態,所以執行sleep()的線程在指定的時間內肯定不會執行;yield()只是使當前線程重新回到可執行狀態,所以執行yield()的線程有可能在進入到可執行狀態後馬上又被執行。

4. sleep()可使優先級低的線程得到執行的機會,當然也可以讓同優先級和高優先級的線程有執行的機會;yield()只能使同優先級的線程有執行的機會。

class TestThreadMethod extends Thread {
    public static int shareVar = 0;

    public TestThreadMethod(String name) {
        super(name);
    }

    public void run() {
        for (int i = 0; i < 4; i++) {
            System.out.print(Thread.currentThread().getName());
            System.out.println(" : " + i);
            //Thread.yield(); (1)
            /* (2) */
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                System.out.println("Interrupted");
            }
        }
    }
}

public class TestThread {
    public static void main(String[] args) {
        TestThreadMethod t1 = new TestThreadMethod("t1");
        TestThreadMethod t2 = new TestThreadMethod("t2");
        t1.setPriority(Thread.MAX_PRIORITY);
        t2.setPriority(Thread.MIN_PRIORITY);
        t1.start();
        t2.start();
    }
}

運行結果為:

1.t1:0

2.t1:1

3.t2:0

4.t1:2

5.t2:1

6.t1:3

7.t2:2

8.t2:3

由結果可見,通過sleep()可使優先級較低的線程有執行的機會。注釋掉代碼(2),並去掉代碼(1)的注釋,結果為:

1.t1:0

2.t1:1

3.t1:2

4.t1:3

5.t2:0

6.t2:1

7.t2:2

8.t2:3

可見,調用yield(),不同優先級的線程永遠不會得到執行機會。yield()的作用:讓出CPU的使用權,給其他線程執行機會、讓同等優先權的線程運行(但並不保證當前線程會被JVM再次調度、使該線程重新進入Running狀態),如果沒有同等優先權的線程,那麼yield()方法將不會起作用。

介紹一種線程退出的方法:使用退出標志,使線程正常退出,也就是當run方法完成後線程終止。

1. 使用退出標志終止線程

當run方法執行完後,線程就會退出。但有時run方法是永遠不會結束的。如在服務端程序中使用線程進行監聽客戶端請求,或是其他的需要循環處理的任務。在這種情況下,一般是將這些任務放在一個循環中,如while循環。如果想讓循環永遠運行下去,可以使用while(true){...}來處理。但要想使while循環在某一特定條件下退出,最直接的方法就是設一個boolean類型的標志,並通過設置這個標志為true或false來控制while循環是否退出。下面給出了一個利用退出標志終止線程的例子。

public class ThreadFlag extends Thread    
{    
    public volatile boolean exit = false;    
   
    public void run()    
    {    
        while (!exit);    
    }    
    public static void main(String[] args) throws Exception    
    {    
        ThreadFlag thread = new ThreadFlag();    
        thread.start();    
        sleep(5000); // 主線程延遲5秒    
        thread.exit = true;  // 終止線程thread    
        thread.join();    
        System.out.println("線程退出!");    
    }    
}  

在上面代碼中定義了一個退出標志exit,當exit為true時,while循環退出,exit的默認值為false。在定義exit時,使用了一個Java關鍵字volatile,這個關鍵字的目的是使exit同步,也就是說在同一時刻只能由一個線程來修改exit的值,

 

8.數字簽名

1.什麼是數字簽名?

數字簽名就是為你的程序打上一種標記,來作為你自己的標識,當別人看到簽名的時候會知道它是與你相關的.

2.為什麼要數字簽名?

最簡單直接的回答:系統要求的。

Android系統要求每一個Android應用程序必須要經過數字簽名才能夠安裝到系統中,也就是說如果一個Android應用程序沒有經過數字簽名,是沒有辦法安裝到系統中的!

Android通過數字簽名來標識應用程序的作者和在應用程序之間建立信任關系,不是用來決定最終用戶可以安裝哪些應用程序。

這個數字簽名由應用程序的作者完成,並不需要權威的數字證書簽名機構認證,它只是用來讓應用程序包自我認證的。

1).保障應用程序開發者的合法權益

在對應用程序簽名後,即表示此應用程序是簽名人所開發的,對此程序具有所有權。

2).預防應用程序替換

應用程序簽名可以防止部分人通過使用相同的Package Name來混淆替換已經安裝的程序,從而出現一些惡意篡改。

3).保證應用程序版本的一致性

一般應用程序都會有更新,即版本的升級。如果應用程序的簽名不一致,是無法進行更新替代的。所以,應用程序簽名是保證當前應用程序順利進行更新安裝的前提。

3.數字證書的機制?

Android使用Java的數字證書相關的機制來給apk加蓋數字證書,要理解android的數字證書,需要先了解以下數字證書的概念和java的數字證書機制。

4.程序使用相同的數字證書的好處

(1)有利於程序升級

當新版程序和舊版程序的數字證書相同時,Android系統才會認為這兩個程序是同一個程序的不同版本。如果新版程序和舊版程序的數字證書不相同,則Android系統認為他們是不同的程序,並產生沖突,會要求新程序更改包名。

(2)有利於程序的模塊化設計和開發。

Android系統允許擁有同一個數字簽名的程序運行在一個進程中,Android程序會將他們視為同一個程序。所以開發者可以將自己的程序分模塊開發,而用戶只需要在需要的時候下載適當的模塊。

(3)可以通過權限(permission)的方式在多個程序間共享數據和代碼。

Android提供了基於數字證書的權限賦予機制,應用程序可以和其他的程序共享概功能或者數據給那些與自己擁有相同數字證書的程序。如果某個權限(permission)的protectionLevel是signature,則這個權限就只能授予那些跟該權限所在的包擁有同一個數字證書的程序。

5.在簽名時,需要考慮數字證書的有效期:

(1)數字證書的有效期要包含程序的預計生命周期,一旦數字證書失效,持有改數字證書的程序將不能正常升級。

(2)如果多個程序使用同一個數字證書,則該數字證書的有效期要包含所有程序的預計生命周期。

(3)Android Market強制要求所有應用程序數字證書的有效期要持續到2033年10月22日以後。

6.數字證書的要點:

Android數字證書包含以下幾個要點:

(1)所有的應用程序都必須有數字證書,Android系統不會安裝一個沒有數字證書的應用程序

(2)Android程序包使用的數字證書可以是自簽名的,不需要一個權威的數字證書機構簽名認證

(3)如果要正式發布一個Android ,必須使用一個合適的私鑰生成的數字證書來給程序簽名,而不能使用adt插件或者ant工具生成的調試證書來發布。

(4)數字證書都是有有效期的,Android只是在應用程序安裝的時候才會檢查證書的有效期。如果程序已經安裝在系統中,即使證書過期也不會影響程序的正常功能。

(5)Android使用標准的java工具Keytool and Jarsigner來生成數字證書,並給應用程序包簽名。

(6)使用zipalign優化程序。

數字簽名的兩種模式

我們都知道Android系統不會安裝運行任何一款未經數字簽名的apk程序,無論是在模擬器上還是在實際的物理設備上。所以我們會有一個疑問,為何在日常開發過程中我沒有進行任何簽名的操作,程序都會在模擬器和真機上運行?下面我們來講講

APK程序的兩種模式: 調試模式(debug mode)和發布模式(release mode)

1.調試模式(debug mode):在調試模式下,ADT會自動的使用debug密鑰為應用程序簽名,因此我們可以直接運行程序。

debug密鑰:一個名為debug.keystore的文件

存放位置 :C:\Users\Xiaopeng\.android\debug.keystoreXiaopeng對應替換為自己操作系統的用戶名

兩個風險:

debug簽名的應用程序有這樣兩個風險:
1)debug簽名的應用程序不能在Android Market上架銷售,它會強制你使用自己的簽名;
2)debug.keystore在不同的機器上所生成的可能都不一樣,就意味著如果你換了機器進行apk版本升級,那麼將會出現上面那種程序不能覆蓋安裝的問題。

不要小視這個問題,如果你開發的程序只有你自己使用,當然無所謂,卸載再安裝就可以了。但要是你的軟件有很多使用客戶,這就是大問題了,就相當於軟件不具備升級功能!

所以一定要有自己的數字證書來簽名;

2.發布模式(release mode):當要發布程序時,開發者就需要使用自己的數字證書給apk包簽名

使用自己的數字證書給APK簽名的兩種方法:

(1)通過DOS命令來對APK簽名。

(2)使用ADT Export Wizard進行簽名

應用程序簽名打包方法

步驟一 進入簽名打包界面

打開Android Studio,依次選擇菜單欄上“Build”->“Generate Signed APK...”,這樣就進入了Android程序簽名打包界面。

\

步驟二 新建Key文件

\

由於我們這裡還沒有已經存在的Key文件,所以需要先創建一個Key,這裡點擊“Create new...”。

\

根據中文提示,填寫對應內容創建相應的Key文件,JACK的機器人這裡創了一個“MyKey.jks”Key文件。

\

步驟三導入相應的Key文件簽名打包應用

創建完Key文件後,會直接返回之前的Key文件導入界面,默認導入當前創建的Key文件。

\

“Next”後,確認APK文件的導出路徑及“Build Type”。

\

在彈出提示語“Signed APKs generated successfully.”表示Android應用程序簽名打包成功。

\

找到剛剛創建的APK文件,這個就是可以直接安裝在Android系統中的應用程序安裝包了。

\    
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved