详解Android端与JavaWeb传输加密(DES+RSA)

一、加密介绍

本文采用对称式加密算法DES和非对称式加密算法RSA结合做数据传输加密的方式。

先说一下对称式加密 DES:对称式加密即使用单钥密码加密的方法,信息的加密和解密使用同一个秘钥,这种方式也称为单秘钥加密。所谓对称就是指加密和解密使用的是同一个秘钥!

常用的对称加密有:DES、IDEA、RC2、RC4、SKIPJACK、RC5、AES算法等。

与对称加密算法不同,非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥 (privatekey)。公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。

RSA 公钥加密算法是1977年由Ron Rivest、Adi Shamirh和LenAdleman在(美国麻省理工学院)开发的。RSA取名来自开发他们三者的名字。RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的所有密码攻击,已被ISO推荐为公钥数据加密标准。 RSA算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但那时想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。

二、RSA密钥生成

RSA密钥采用OpenSSL协议进行生成,本文仅简单生成公钥和私钥,如有其它需要可以通过CA证书进行密钥的生成

1、OpenSSL安装

http://slproweb.com/products/Win32OpenSSL.html

请自行选择32位64位进行下载安装

2、打开工作空间

打开OpenSSL安装目录下的bin,运行OpenSSL.exe进入OpenSSL工作空间

3、密钥生成

①、私钥生成(生成位置位于bin目录下)

genrsa -out rsa_private_key.pem 1024

openssl随机生成了一份私钥,加密长度是1024位。加密长度是指理论上最大允许”被加密的信息“长度的限制,也就是明文的长度限制。随着这个参数的增大(比方说2048),允许的明文长度也会增加,但同时也会造成计算复杂度的极速增长。一般推荐的长度就是1024位(128字节)

JAVA需要使用的私钥需要经过PKCS#8编码,PHP程序不需要

当前私钥格式需要转换为pkcs#8的格式,命令为:

pkcs8 -topk8 -inform PEM -in pkcs8_rsa_private_key.pem -outform PEM -nocrypt

②、公钥生成

rsa -in rsa_private_key.pem -out rsa_public_key.pem -pubout

至此,RSA+DES相关前期准备工作完成

三、Android端配置

本文主要针对数据传输过程进行加密,采取加密Json字符串完成整个加密过程,由此,需要统一传输参数为"data=********&sign="*******************"的格式,如有其它需求请自行更改。

由于本项目网络框架采用Retrofit+OkHttp的实现方式,所以对参数进行加密的过程由OkHttp拦截器来实现

public class EncryptionInterceptor implements Interceptor {

private Context mContext;

public EncryptionInterceptor(Context context) {
 this.mContext = context;
}

@Override
public Response intercept(@NonNull Chain chain) throws IOException {
 Request request = chain.request();
 RequestBody oldBody = request.body();
 Buffer buffer = new Buffer();
 if (oldBody != null) {
  oldBody.writeTo(buffer);
 }
 String strOldBody = buffer.readUtf8();
 Map<String, String> map = new HashMap<>();
 String dataByte = URLDecoder.decode(strOldBody.substring(5), "utf-8");
 try {
  //获取DES的key
  byte[] desKey = DESCoder.initKey();
  //DES加密数据
  byte[] encrypt = DESCoder.encrypt(dataByte.getBytes(), desKey);
  map.put("data", parseByte2HexStr(encrypt));
  //RSA加密
  RSAEncrypt rsaEncrypt = new RSAEncrypt();
  InputStream inputStream =  mContext.getResources().getAssets().open("rsa_public_key.pem");
  //rsa设置公钥
  rsaEncrypt.loadPublicKey(inputStream);
  //rsa加密DES的key
  byte[] rsaData = rsaEncrypt.encrypt(rsaEncrypt.getPublicKey(), desKey);
  map.put("sign", parseByte2HexStr(rsaData));
 } catch (Exception e) {
  e.printStackTrace();
 }

 FormBody body = new FormBody.Builder().add("data", map.get("data")).add("sign", map.get("sign")).build();
 request = request.newBuilder().header("Content-Type", body.contentType().type()).header("Content-Length", String.valueOf(body.contentLength())).method(request.method(), body).build();
 return chain.proceed(request);
}

/**
 * 将二进制转换成16进制
 *
 * @since v1.0
 */
private static String parseByte2HexStr(byte buf[]) {
 StringBuilder sb = new StringBuilder();
 for (byte aBuf : buf) {
  String hex = Integer.toHexString(aBuf & 0xFF);
  if (hex.length() == 1) {
   hex = '0' + hex;
  }
  sb.append(hex.toUpperCase());
 }
 return sb.toString();
}

/**
 * 按照key排序得到参数列表字符串
 *
 * @param paramValues 参数map对象
 * @return 参数列表字符串
 */
public static String getParamsOrderByKey(Map<String, String> paramValues) {
 String params = "";
 List<String> paramNames = new ArrayList<>(paramValues.size());
 paramNames.addAll(paramValues.keySet());
 Collections.sort(paramNames);
 for (String paramName : paramNames) {

  if (params.equals("")) {
   params += paramName + "=" + paramValues.get(paramName);
  } else {
   params += "&" + paramName + "=" + paramValues.get(paramName);
  }
 }

 return params;
}

/**
 * 将16进制转换为二进制
 *
 * @since v1.0
 */
public byte[] parseHexStr2Byte(String hexStr) {
 if (hexStr.length() < 1)
  return null;
 byte[] result = new byte[hexStr.length() / 2];
 for (int i = 0; i < hexStr.length() / 2; i++) {
  int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
  int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
  result[i] = (byte) (high * 16 + low);
 }
 return result;
}

}

添加OkHttp拦截器

new OkHttpClient.Builder()
    .addInterceptor(new EncryptionInterceptor(this))
    .build();

RSA工具类实现

public class RSAEncrypt {
public static final String DEFAULT_PUBLIC_KEY =
  "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC1Qcf1zVOuhseFxvo6+FnVvEPs" + "\r" + "Uvczg6oX+HjMNksiiDWcNkbPHfznaPDtgoBY2xF0R8HGHbrT53LNvkj7UMcI48tq" + "\r" + "K+B4YdJHe9SgJVDCCiceLLGtf/ev206qJ/XgKgrLFD+vMmjIB8gQCkZvy/dxhEf1" + "\r" + "aAmoz5tdJhOVdxT7QwIDAQAB" + "\r";

public static final String DEFAULT_PRIVATE_KEY =
  "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALVBx/XNU66Gx4XG" + "\r" +
    "+jr4WdW8Q+xS9zODqhf4eMw2SyKINZw2Rs8d/Odo8O2CgFjbEXRHwcYdutPncs2+" + "\r" +
    "SPtQxwjjy2or4Hhh0kd71KAlUMIKJx4ssa1/96/bTqon9eAqCssUP68yaMgHyBAK" + "\r" +
    "Rm/L93GER/VoCajPm10mE5V3FPtDAgMBAAECgYAf1hEAHHNhSS0MUzmqV+q3ftzT" + "\r" +
    "SnM+6hZbJXpaLAMgapo3+NSRFmxQXP9MSEqw0LGNIfloCdrB03o3pv98nOCIZCh7" + "\r" +
    "PHsU2GhxJ04Qro+wKhK358326KNXCjjqVIBG0xMbJxVhjM2/jjfocxFpe5iD7h53" + "\r" +
    "c+GvDgUVduAYO4I1GQJBAO21n2aIzQV3mScS1O8BRV+9CmHaDbVHqBetRoB3kJ2U" + "\r" +
    "piflKTNofwWmTA5A8sKt8WcOz7LsB2SWcp9jNvatxA8CQQDDNCmfo6eix9e5f11K" + "\r" +
    "Rf8sRiN7XGDzlKkZlmQAN0UtXdTP4AN9cuZrwnntWKysXr/zLntYLGYn9rdrohbD" + "\r" +
    "9RGNAkBOEsog7iuQcSCfQcMoIN29PSSs0OaRtNBTvniadyrLZuhP0CeBGAAoRd9T" + "\r" +
    "CyfwoxrXg3jaRkWDVxqcmQSTbq0nAkB8flcRhilSqsuNdYpE5VFxpiXY9jirAKO8" + "\r" +
    "Our6LEXFQjOIhCEVr+L+1OA4HDa8FA2thXaK7H4WfMXMMmr8fN69AkEAuR0YU9My" + "\r" +
    "snzWLDWYR5sNp90PhyDSL/HTZHBnebD+JlAYwoYRFYt+tXw0/PEmV2B3thYGPeiZ" + "\r" +
    "kHKd/TeLIVbxGg==" + "\r";

/**
 * 私钥
 */
private RSAPrivateKey privateKey;

/**
 * 公钥
 */
private RSAPublicKey publicKey;

/**
 * 字节数据转字符串专用集合
 */
private static final char[] HEX_CHAR = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};

/**
 * 获取私钥
 *
 * @return 当前的私钥对象
 */
public RSAPrivateKey getPrivateKey() {
 return privateKey;
}

/**
 * 获取公钥
 *
 * @return 当前的公钥对象
 */
public RSAPublicKey getPublicKey() {
 return publicKey;
}

/**
 * 随机生成密钥对
 */
public void genKeyPair() {
 KeyPairGenerator keyPairGen = null;
 try {
  keyPairGen = KeyPairGenerator.getInstance("RSA");
 } catch (NoSuchAlgorithmException e) {
  e.printStackTrace();
 }
 keyPairGen.initialize(1024, new SecureRandom());
 KeyPair keyPair = keyPairGen.generateKeyPair();
 this.privateKey = (RSAPrivateKey) keyPair.getPrivate();
 this.publicKey = (RSAPublicKey) keyPair.getPublic();
}

/**
 * 从文件中输入流中加载公钥
 *
 * @param in 公钥输入流
 * @throws Exception 加载公钥时产生的异常
 */
public void loadPublicKey(InputStream in) throws Exception {
 try {
  BufferedReader br = new BufferedReader(new InputStreamReader(in));
  String readLine = null;
  StringBuilder sb = new StringBuilder();
  while ((readLine = br.readLine()) != null) {
   if (readLine.charAt(0) == '-') {
    continue;
   } else {
    sb.append(readLine);
    sb.append('\r');
   }
  }
  loadPublicKey(sb.toString());
 } catch (IOException e) {
  throw new Exception("公钥数据流读取错误");
 } catch (NullPointerException e) {
  throw new Exception("公钥输入流为空");
 }
}

/**
 * 从字符串中加载公钥
 *
 * @param publicKeyStr 公钥数据字符串
 * @throws Exception 加载公钥时产生的异常
 */
public void loadPublicKey(String publicKeyStr) throws Exception {
 try {
 // byte[] buffer = Base64.decode(publicKeyStr.getBytes(), Base64.DEFAULT);
  BASE64Decoder base64Decoder= new BASE64Decoder();
  byte[] buffer= base64Decoder.decodeBuffer(publicKeyStr);
  KeyFactory keyFactory = KeyFactory.getInstance("RSA");
  X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
  this.publicKey = (RSAPublicKey) keyFactory.generatePublic(keySpec);
 } catch (NoSuchAlgorithmException e) {
  throw new Exception("无此算法");
 } catch (InvalidKeySpecException e) {
  throw new Exception("公钥非法");
 } catch (NullPointerException e) {
  throw new Exception("公钥数据为空");
 }
}

/**
 * 从文件中加载私钥
 *
 * @return 是否成功
 * @throws Exception
 */
public void loadPrivateKey(InputStream in) throws Exception {
 try {
  BufferedReader br = new BufferedReader(new InputStreamReader(in));
  String readLine = null;
  StringBuilder sb = new StringBuilder();
  while ((readLine = br.readLine()) != null) {
   if (readLine.charAt(0) == '-') {
    continue;
   } else {
    sb.append(readLine);
    sb.append('\r');
   }
  }
  loadPrivateKey(sb.toString());
 } catch (IOException e) {
  throw new Exception("私钥数据读取错误");
 } catch (NullPointerException e) {
  throw new Exception("私钥输入流为空");
 }
}

public void loadPrivateKey(String privateKeyStr) throws Exception {
 try {
  //byte[] buffer = Base64.encode(privateKeyStr.getBytes(), Base64.DEFAULT);
  BASE64Decoder base64Decoder= new BASE64Decoder();
  byte[] buffer= base64Decoder.decodeBuffer(privateKeyStr);
  PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
  KeyFactory keyFactory = KeyFactory.getInstance("RSA");
  this.privateKey = (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
 } catch (NoSuchAlgorithmException e) {
  throw new Exception("无此算法");
 } catch (InvalidKeySpecException e) {
  throw new Exception("私钥非法");
 } catch (NullPointerException e) {
  throw new Exception("私钥数据为空");
 }
}

/**
 * 加密过程
 *
 * @param publicKey  公钥
 * @param plainTextData 明文数据
 * @return
 * @throws Exception 加密过程中的异常信息
 */
public byte[] encrypt(RSAPublicKey publicKey, byte[] plainTextData) throws Exception {
 if (publicKey == null) {
  throw new Exception("加密公钥为空, 请设置");
 }
 Cipher cipher = null;
 try {

  cipher = Cipher.getInstance("RSA");
  //Android端无需添加此加密提供者,已默认实现
  //cipher = Cipher.getInstance("RSA", new BouncyCastleProvider());
  cipher.init(Cipher.ENCRYPT_MODE, publicKey);
  return cipher.doFinal(plainTextData);
 } catch (NoSuchAlgorithmException e) {
  throw new Exception("无此加密算法");
 } catch (NoSuchPaddingException e) {
  e.printStackTrace();
  return null;
 } catch (InvalidKeyException e) {
  throw new Exception("加密公钥非法,请检查");
 } catch (IllegalBlockSizeException e) {
  throw new Exception("明文长度非法");
 } catch (BadPaddingException e) {
  throw new Exception("明文数据已损坏");
 }
}

/**
 * 解密过程
 *
 * @param privateKey 私钥
 * @param cipherData 密文数据
 * @return 明文
 * @throws Exception 解密过程中的异常信息
 */
public byte[] decrypt(RSAPrivateKey privateKey, byte[] cipherData) throws Exception {
 if (privateKey == null) {
  throw new Exception("解密私钥为空, 请设置");
 }
 Cipher cipher = null;
 try {
  cipher = Cipher.getInstance("RSA");
  //Android端无需添加此加密提供者,已默认实现
  //cipher = Cipher.getInstance("RSA", new BouncyCastleProvider());
  cipher.init(Cipher.DECRYPT_MODE, privateKey);
  byte[] output = cipher.doFinal(cipherData);
  return output;
 } catch (NoSuchAlgorithmException e) {
  throw new Exception("无此解密算法");
 } catch (NoSuchPaddingException e) {
  e.printStackTrace();
  return null;
 } catch (InvalidKeyException e) {
  throw new Exception("解密私钥非法,请检查");
 } catch (IllegalBlockSizeException e) {
  throw new Exception("密文长度非法");
 } catch (BadPaddingException e) {
  throw new Exception("密文数据已损坏");
 }
}

/**
 * 字节数据转十六进制字符串
 *
 * @param data 输入数据
 * @return 十六进制内容
 */
public static String byteArrayToString(byte[] data) {
 StringBuilder stringBuilder = new StringBuilder();
 for (int i = 0; i < data.length; i++) {
  //取出字节的高四位 作为索引得到相应的十六进制标识符 注意无符号右移
  stringBuilder.append(HEX_CHAR[(data[i] & 0xf0) >>> 4]);
  //取出字节的低四位 作为索引得到相应的十六进制标识符
  stringBuilder.append(HEX_CHAR[(data[i] & 0x0f)]);
  if (i < data.length - 1) {
   stringBuilder.append(' ');
  }
 }
 return stringBuilder.toString();
}

public static void main(String[] args) {
 RSAEncrypt rsaEncrypt = new RSAEncrypt();

 //加载公钥
 try {
  rsaEncrypt.loadPublicKey(RSAEncrypt.DEFAULT_PUBLIC_KEY);
  System.out.println("加载公钥成功");
 } catch (Exception e) {
  System.err.println(e.getMessage());
  System.err.println("加载公钥失败");
 }
 /*try {
  rsaEncrypt.loadPublicKey(RSAEncrypt.DEFAULT_PUBLIC_KEY);
  System.out.println("加载公钥成功");
 } catch (Exception e) {
  System.err.println(e.getMessage());
  System.err.println("加载公钥失败");
 }
 //加载私钥
 try {
  rsaEncrypt.loadPrivateKey(RSAEncrypt.DEFAULT_PRIVATE_KEY);
  System.out.println("加载私钥成功");
 } catch (Exception e) {
  System.err.println(e.getMessage());
  System.err.println("加载私钥失败");
 }
 try {
  SecureRandom sr = new SecureRandom();
  KeyGenerator kg = KeyGenerator.getInstance("DES");
  kg.init(56, sr);
  SecretKey generateKey = kg.generateKey();
  String encodeHexString = Hex.toHexString(generateKey.getEncoded());
  System.out.println(encodeHexString);
 } catch (NoSuchAlgorithmException e) {
  e.printStackTrace();
 }
 //测试字符串
 String encryptStr= "Test String chaijunkun";

 try {
  //加密
  long encryptStart = System.currentTimeMillis();
  byte[] cipher = rsaEncrypt.encrypt(rsaEncrypt.getPublicKey(), encryptStr.getBytes());
  long encryptEnd = System.currentTimeMillis();
  System.out.println("密文长度:"+ cipher.length);
  System.out.println(RSAEncrypt.byteArrayToString(cipher));
  System.out.println("加密时间"+ (encryptEnd-encryptStart));

  //解密
  long decryptStart = System.currentTimeMillis();
  byte[] plainText = rsaEncrypt.decrypt(rsaEncrypt.getPrivateKey(), cipher);
  long decryptEnd = System.currentTimeMillis();
  System.out.println("明文长度:"+ plainText.length);
  System.out.println(RSAEncrypt.byteArrayToString(plainText));
  System.out.println("解密时间"+ (decryptEnd-decryptStart));

  System.out.println(new String(plainText));
 } catch (Exception e) {
  System.err.println(e.getMessage());
 }*/
  }
}

DES工具类实现

public class DESCoder {
/**
 * 密钥算法
 * java 7只支持56位密钥
 * Bouncy Castle 支持64位密钥
 */
public static final String KEY_ALGORITHM = "DES";
/**
 * 加密/解密算法 /工作模式/填充方式
 */
public static final String CIPHER_ALGORITHM = "DES/ECB/PKCS5Padding";
/**
 * 转换密钥
 * @param key 二进制密钥
 * @return key 密钥
 * @throws Exception
 */
private static Key toKey(byte[] key) throws Exception{
 //实例化DES密钥材料
 DESKeySpec dks = new DESKeySpec(key);
 //实例化密钥工厂
 SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(KEY_ALGORITHM);
 //生产密钥
 SecretKey secretKey = keyFactory.generateSecret(dks);
 return secretKey;
}
/**
 * 解密
 * @param data 待解密数据
 * @param key 密钥
 * @return byte[] 解密数据
 * @throws Exception
 */
public static byte[] decrypt(byte[] data,byte[] key) throws Exception{
 //还原密钥
 Key k = toKey(key);
 //实例化
 Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
 //初始化,设置为解密模式
 cipher.init(Cipher.DECRYPT_MODE, k);
 //执行操作
 return cipher.doFinal(data);
}
/**
 * 加密
 * @param data 待加密数据
 * @param key 密钥
 * @return byte[] 加密数据
 * @throws Exception
 */
public static byte[] encrypt(byte[] data,byte[] key) throws Exception{
 //还原密钥
 Key k = toKey(key);
 //实例化
 Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM,new BouncyCastleProvider());
 //初始化,设置为加密模式
 cipher.init(Cipher.ENCRYPT_MODE,k);
 //执行操作
 return cipher.doFinal(data);
}
/**
 * 生产密钥
 * java 7只支持56位 密钥
 * Bouncy Castle 支持64位密钥
 * @return byte[] 二进制密钥
 * @throws Exception
 */
public static byte[] initKey() throws Exception{
 /*
  * 实例化密钥生成器
  * 若要使用64位密钥注意替换
  * 讲下述代码中的
  * KeyGenerator.getInstance(KEY_ALGORITHM);
  * 替换为
  * KeyGenerator.getInstance(KEY_ALGORITHM,"BC");
  */
 KeyGenerator kg = KeyGenerator.getInstance(KEY_ALGORITHM,new BouncyCastleProvider());

 kg.init(64);
 //生成密钥
 SecretKey secretKey = kg.generateKey();
 //获得密钥的二进制编码形式
 return secretKey.getEncoded();
}
}

四、JavaWeb端配置

Web后端只需要在Controller中添加以下代码,接受服务端传递的data和sign,并完成接收的Json字符串转换为实体类即可

/**
 * 解密所需数据
 *
 * @param data 接受客户端上传的Json格式的数据
 * @param sign 接受客户端上传的解密数据的key值
 */
public <T> T convertJson(String data, String sign,Class<T> clazz) {
 System.out.println(data);
 System.out.println(sign);
 T tClass = null;
 try {
  //rsa加密
  RSAEncrypt rsaEncrypt = new RSAEncrypt();
  //加载rsa私钥
  InputStream in = new FileInputStream(new File("C:\\OpenSSL-Win64\\bin\\pkcs8_rsa_private_key.pem"));
  rsaEncrypt.loadPrivateKey(in);
  //获取RSA加密的key的数据,并把该16进制的sign转成byte[],(客户端采用将byte[]转成16进制进行数据上传)
  byte[] keyBytes = parseHexStr2Byte(sign);
  //通过RSA解密DES的key值
  byte[] rsaKey = rsaEncrypt.decrypt(rsaEncrypt.getPrivateKey(), keyBytes);

  //通过DES的key值解密需要的json数据
  byte[] desData = DESCoder.decrypt(parseHexStr2Byte(data), rsaKey);
  System.out.println(Arrays.toString(desData));
  System.out.println(new String(desData));
  tClass = JSON.parseObject(new String(desData), clazz);
 } catch (Exception e) {
  e.printStackTrace();
 }
 return tClass;
}

五、备注

后续会上传相关Demo到Github

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 详解Android使用Socket对大文件进行加密传输

    前言 数据加密,是一门历史悠久的技术,指通过加密算法和加密密钥将明文转变为密文,而解密则是通过解密算法和解密密钥将密文恢复为明文.它的核心是密码学. 数据加密目前仍是计算机系统对信息进行保护的一种最可靠的办法.它利用密码技术对信息进行加密,实现信息隐蔽从而起到保护信息的安全的作用. 项目中使用Socket进行文件传输过程时,需要先进行加密.实现的过程中踏了一些坑,下面对实现过程进行一下总结. DES加密 由于加密过程中使用的是DES加密算法,下面贴一下DES加密代码: //秘钥算法 privat

  • 详解Android端与JavaWeb传输加密(DES+RSA)

    一.加密介绍 本文采用对称式加密算法DES和非对称式加密算法RSA结合做数据传输加密的方式. 先说一下对称式加密 DES:对称式加密即使用单钥密码加密的方法,信息的加密和解密使用同一个秘钥,这种方式也称为单秘钥加密.所谓对称就是指加密和解密使用的是同一个秘钥! 常用的对称加密有:DES.IDEA.RC2.RC4.SKIPJACK.RC5.AES算法等. 与对称加密算法不同,非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥 (privatekey).公开密钥与私有密钥是一对,如

  • 详解Android 基于TCP和UDP协议的Socket通信

    本来想讲一下基础的网络通信方面的知识点,发现太枯燥乏味了,不过笔试中也经常会问到这方面的问题,所以关于通信方面的知识点,小编会放到面试中去,因为实战中也就面试会用到这方面知识点 Android与服务器的通信方式主要有两种,一是Http通信,一是Socket通信.两者的最大差异在于,http连接使用的是"请求-响应方式",即在请求时建立连接通道,当客户端向服务器发送请求后,服务器端才能向客户端返回数据. 而Socket通信中基于TCP/IP协议的通信则是在双方建立起连接后就可以直接进行数

  • 详解Android 蓝牙通信方式总结

    1.摘要 Android手机间通过蓝牙方式进行通信,有两种常见的方式,一种是socket方式,另一种是通过Gatt Server(Android 5.0以后)通信,socket方式最为简单,但是很多低功耗的蓝牙设备,如单片机上的蓝牙模块可能不支持:而Gatt方式相对比较复杂.其实无论是socket方式还是Gatt,Android设备间蓝牙通信都是一种C/S(client-server)模式. 本文基于两种通信方式,进行详细展开,并推荐了开源项目,建议配合学习. 关键词 (1)Bluetooth

  • 详解Android通过修改配置文件设置wifi密码

    详解Android通过修改配置文件设置wifi密码 前言: 在一些非常规Android设备上,如眼镜/手表,输入wifi密码如同一场灾难.此时可以通过修改配置文件的方法设置wifi的ssid和密码. wifi密码配置文件 首先要保证设备已经root,wifi的配置文件在/data/misc/wifi/wpa_supplicant.conf,可以先将其pull出来,然后在下面加上network开头的那部分就ok了.然后再导入进去.下面是我的配置文件: ##### wpa_supplicant co

  • 详解Android中图片的三级缓存及实例

    详解Android中图片的三级缓存及实例 为什么要使用三级缓存 如今的 Android App 经常会需要网络交互,通过网络获取图片是再正常不过的事了 假如每次启动的时候都从网络拉取图片的话,势必会消耗很多流量.在当前的状况下,对于非wifi用户来说,流量还是很贵的,一个很耗流量的应用,其用户数量级肯定要受到影响 特别是,当我们想要重复浏览一些图片时,如果每一次浏览都需要通过网络获取,流量的浪费可想而知 所以提出三级缓存策略,通过网络.本地.内存三级缓存图片,来减少不必要的网络交互,避免浪费流量

  • 详解Android.activity销毁流程的工作原理

    继续我们的源码解析,上一篇文章我们介绍了Activity的启动流程,一个典型的场景就是Activity a 启动了一个Activity b,他们的生命周期回调方法是: onPause(a) –> onCreate(b) –> onStart(b) –> onResume(b) –> onStop(a) 而我们根据源码也验证了这样的生命周期调用序列,那么Activity的销毁流程呢?它的生命周期的调用顺序又是这样的呢? 这里我们我做一个简单的demo,让一个Activity a启动A

  • 详解Android aidl的使用方法

    AIDL是Android中IPC(Inter-Process Communication)方式中的一种,AIDL是Android Interface definition language的缩写(对于小白来说,AIDL的作用是让你可以在自己的APP里绑定一个其他APP的service,这样你的APP可以和其他APP交互.) AIDL只是Android中众多进程间通讯方式中的一种方式, AIDL和Messenger的区别: Messenger不适用大量并发的请求:Messenger以串行的方式来处

  • 详解Android项目多服务端接口适配(超简单)

    现状 Android项目如果是多服务端接口时,一般怎么弄呢? 方法1:服务器地址放在Header中 把服务器地址放在接口Header中,然后通过拦截器来动态修改请求地址而实现的.除了默认服务器的接口,其它都要加一个Header,有点麻烦.看起来也不爽,不简洁. interface ApiHeaderCase { /************************** server A ****************************/ @Headers("host:$SERVER_HOS

  • 详解Android Activity的启动流程

    前言 activity启动的流程分为两部分:一是在activity中通过startActivity(Intent intent)方法启动一个Activity:二是我们在桌面通过点击应用图标启动一个App然后显示Activity:第二种方式相较于第一种方式更加全面,所以本文会以第二种流程来分析. 简要 我们手机的桌面是一个叫做Launcher的Activity,它罗列了手机中的应用图标,图标中包含安装apk时解析的应用默认启动页等信息.在点击应用图标时,即将要启动的App和Launcher.AMS

  • 详解Android Automotive车载应用对驾驶模式Safe Drive Mode的适配

    前言 最近在Android Automotive 上遇到的一些问题,有好几个都跟Android 车载操作系统上应用的驾驶模式有关,国内这方面的资料很少,自己在这里总结一下相关的知识,主要包含下面几个方面: Android Automotive 和 Android Auto的区别 Android Automotive 的驾驶模式介绍 Android Automotive 实现驾驶模式的几种实现方式和代码示例,以及实现效果 主要是还是想总结一下Android 车载应用对Automotive 驾驶模式

随机推荐