咸鱼

咸鱼是以盐腌渍后,晒干的鱼

0%

在开发IoT App往往需要WiFi配网功能,所以需要用到获取当前SSID的API接口,在Android9.0上获取的权限更加严格。

android9-wifi.png

权限

  • ACCESS_FINE_LOCATION ACCESS_COARSE_LOCATION (需要动态申请)

  • ACCESS_WIFI_STATE 和 ACCESS_NETWORK_STATE

1
2
3
4
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
阅读全文 »

工程 compileSdkVersion 28preview 一片空白,无法预览布局,降低 sdk 版本也不行。

点击旁边的 红色圆点叹号,出现

1
Failed to load AppCompat ActionBar with unknown error.

应该是 ActionBar 出了问题,按照以下修改可预览:

1
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
阅读全文 »

借助网上的一段描述:

若以银行账户为类比,这 5 个词分别对应内容如下:

地址=银行卡号
密码=银行卡密码
私钥=银行卡号+银行卡密码
助记词=银行卡号+银行卡密码
Keystore+密码=银行卡号+银行卡密码
Keystore ≠ 银行卡号

1
2
implementation 'org.web3j:core:3.3.1-android'
implementation 'io.github.novacrypto:BIP39:0.1.9'//用于生成助记词

org.web3j:core 这个库是Java的,org.web3j:core:x-android 是兼容Android平台,所有接口和工具类都是为Java应用设计的,所以在Android上使用的时候要注意变通一下。

创建数字身份

阅读全文 »

测试“生成合约的Java代码”环境

下载web3j-3.4.0
解压目录

1
2
3
4
5
.
├── bin
│   ├── web3j
│   └── web3j.bat
└── lib

进入bin目录,编写一个测试合约代码 SimpleStorage.sol

1
2
3
4
5
6
7
8
9
10
11
pragma solidity ^0.4.17;

contract SimpleStorage {
uint storedData;
function set(uint x) public {
storedData = x;
}
function get() public view returns (uint) {
return storedData;
}
}
阅读全文 »

为了防止交易重复进行,以太坊要求每笔交易必须有一个nonce数值。nonce值从0开始递增,每发送一笔交易,nonce便加1。

交易处理从nonce值较小的开始,所以nonce的值太大的话,交易会被延迟处理。

如何合理的获取nonce的值:向以太坊节点获取。

示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/**
* 以太坊交易
* @throws ExecutionException
* @throws InterruptedException
*/
public void testTransferEther() throws ExecutionException, InterruptedException {

EthCoinbase coinbase = web3j.ethCoinbase().sendAsync().get();

//拨款地址,这里用coinbase账号的地址
final String formAddress = coinbase.getAddress();
//拨款账号的Key,Key是账号的身份验证,很重要
final String formKey = "58e7f34b59a828d1dc37a97a921b55de0cb8cedea91b1e09b490f39264b151ce";
//收款地址
final String toAddress = "0x9958eC47C8286DC89F5CbCbD842458bD43540a7D";

EthGetTransactionCount ethGetTransactionCount = web3j.ethGetTransactionCount(
formAddress, DefaultBlockParameterName.LATEST).sendAsync().get();
BigInteger nonce = ethGetTransactionCount.getTransactionCount();

//转0.5个以太坊币
BigInteger value = Convert.toWei("0.5", Convert.Unit.ETHER).toBigInteger();
Log.e(TAG, "transaction nonce: " + nonce );

RawTransaction rawTransaction = RawTransaction.createEtherTransaction(
nonce, GAS_PRICE, GAS_LIMIT, toAddress, value);
//签名
Credentials credentials = Credentials.create(formKey);
byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
String hexValue = Numeric.toHexString(signedMessage);
//交易
EthSendTransaction ethSendTransaction = web3j.ethSendRawTransaction(hexValue).sendAsync().get();
Log.e(TAG, "transactionHash: " + ethSendTransaction.getTransactionHash());
}
阅读全文 »

我们使用 Js / Java / Go 等语言调用以太坊 ethereum 的服务时,以太坊是通过 JSON-RPC 提供服务的,那么什么是 JSON-RPC ?

JSON-RPC

JSON-RPC是一种无状态轻量级远程过程调用(RPC)协议。本规范定义了数据结构及 相应的处理规则。规范本身是传输无关的,可以用于进程内通信、Socket套接字、HTTP 或各种消息通信环境。规范使用JSON(RFC 4627)数据格式。

相较于一般的 RESTAPI 通过网址(如 GET /user)调用远程服务器,JSON-RPC 直接在内容中定义了欲调用的函数名称,如 {“method”: “getUser”},JSON-RPC 更加简单和轻量级。

眼下主流语言都已有 JSON-RPC 的实现框架,Java语言中较好的JSON-RPC实现框架有 jsonrpc4j、jpoxy、json-rpc。三者之中 jsonrpc4j 既可独立使用。又可与 spring 无缝集合,比較适合于基于 spring的项目开发。

阅读全文 »

平时写Android App和Web服务器的通讯是通过JSON的数据格式,然而自己对响应数据的定义的一般是使用Java Bean的继承来实现,下面是web3j的设计,也差不多这样,但是他的泛型用的挺的,以后可以参考。

比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
package org.web3j.protocol.core.methods.response;

import org.web3j.protocol.core.Response;

/**
* eth_coinbase.
*/
public class EthCoinbase extends Response<String> {
public String getAddress() {
return getResult();
}
}

Response类的 result 字段使用了泛型 T :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package org.web3j.protocol.core;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

/**
* Our common JSON-RPC response type.
*
* @param <T> the object type contained within the response
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class Response<T> {
private long id;
private String jsonrpc;
private T result;
private Error error;
private String rawResponse;

public Response() {
}

public long getId() {
return id;
}

public void setId(long id) {
this.id = id;
}

public String getJsonrpc() {
return jsonrpc;
}

public void setJsonrpc(String jsonrpc) {
this.jsonrpc = jsonrpc;
}

public T getResult() {
return result;
}

public void setResult(T result) {
this.result = result;
}

public Error getError() {
return error;
}

public void setError(Error error) {
this.error = error;
}

public boolean hasError() {
return error != null;
}

public String getRawResponse() {
return rawResponse;
}

public void setRawResponse(String rawResponse) {
this.rawResponse = rawResponse;
}

public static class Error {
private int code;
private String message;
private String data;

public Error() {
}

public Error(int code, String message) {
this.code = code;
this.message = message;
}

public int getCode() {
return code;
}

public void setCode(int code) {
this.code = code;
}

public String getMessage() {
return message;
}

public void setMessage(String message) {
this.message = message;
}

public String getData() {
return data;
}

public void setData(String data) {
this.data = data;
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof Error)) {
return false;
}

Error error = (Error) o;

if (getCode() != error.getCode()) {
return false;
}
if (getMessage() != null
? !getMessage().equals(error.getMessage()) : error.getMessage() != null) {
return false;
}
return getData() != null ? getData().equals(error.getData()) : error.getData() == null;
}

@Override
public int hashCode() {
int result = getCode();
result = 31 * result + (getMessage() != null ? getMessage().hashCode() : 0);
result = 31 * result + (getData() != null ? getData().hashCode() : 0);
return result;
}
}
}

阅读全文 »

描述

multipart/form-data 用以向服务器发送二进制数据,一般用于多个文件和参数一起发送。

服务端接收数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@RequestMapping("/test/multipart")
@ResponseBody
public String handleFileUpload(@RequestPart("file")MultipartFile file,
@RequestPart("describe")String describe){

System.out.println("describe="+describe);
if(!file.isEmpty()){

try {
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(new File(file.getOriginalFilename())));
out.write(file.getBytes());
out.flush();
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
return e.getMessage();

} catch (IOException e) {
e.printStackTrace();
return e.getMessage();
}
return"OK";
}else{
return"file is null";
}
}

客户端

阅读全文 »

需求

分块传输编码(Chunked transfer encoding)是超文本传输协议(HTTP)中的一种数据传输机制,允许HTTP由网页服务器发送给客户端应用( 通常是网页浏览器)的数据可以分成多个部分。分块传输编码只在HTTP协议1.1版本(HTTP/1.1)中提供。

客户端给服务器发送数据也一样可以使用 Chunk 传输,比如,客户端要上传数据,但是数据没有完全生成,通过chunk分块传输,就可以一边生成数据一边上传,典型的比如:上传录音。

服务端接收数据

1
2
3
4
5
@PostMapping(value = "/upload")
public String upload(@RequestBody byte[] body){

return "PONG:"+body.length;
}
阅读全文 »

微信硬件平台方案

假如我们要有一个WiFi硬件产品,已经有与自己的服务器通讯的私有协议,现在要接入到微信公众号平台,那将如何选择对接方案呢?

《微信硬件平台》 有两大类接入方案:微信硬件云标准接入方案平台基础接入方案

选择接入方案.png

调试工具

阅读全文 »

Jenkins是一个开源软件项目,是基于Java开发的一种持续集成工具。Jenkins非常灵活,不过需要自己部署服务器,功能非常强大。可以通过配置插件,实现各种项目的 编译 - 打包 - 部署 等一条龙服务工作。

……篇幅较长,还是看别人的吧 《搭建jenkins实现自动化部署》

travis-ci 是在线托管的CI服务,用Travis来进行持续集成,不需要自己搭服务器,使用方便,对Github开源项目是免费的,支持多数主流语言。

使用

  1. 登录Travis官网 ,用Github账号登录。
  2. 首次登录,授权给Travis访问你的GitHub代码库
  3. 把需要CI的项目(UIAutomatorTest)勾选上
  4. 点击 “hebbely/UiAutomatorTest”,进入该项目”More Options”-“Setting” ,打开选项”Build ..yml” 和 “Build pushed branches”
  5. 添加.travis.yml
1
2
3
4
5
6
7
8
9
10
language: java
jdk:
- oraclejdk8
script: "mvn clean package -Dmaven.test.skip=true"
branches:
only:
- master
notifications:
email:
- xxx@qq.com

在github看到很多项目根目录都有 .editorconfig 文件,所以去了解一下。

这个文件是 EditorConfig 用来统一不同编辑器的代码风格的配置。

各种IDE的风格自然不一样,通过这样一个配置文件定义的标准统一风格,比如缩进用x个空格。再有就是多人一起协同开发一个项目,editorconfig 能起到很好的效果。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# EditorConfig: http://editorconfig.org/

root = true

[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false

阅读全文 »

自己搜索的内容含有 csdn.net 的,但这个网站要登录才能看,所以这些搜索结果是无用的,所以要过滤掉这些无用的结果。
如某搜索,这样搜索:关键字 -site:csdn.net 就是过滤掉 csdn.net 的搜索结果。

实用的插件,idea默认没有带的,自己可以安装。

.ignore

可以帮助你创建相关项目的.gitignore文件

GsonFormat

快速生成JSON类

阅读全文 »

启动默认不打开项目

Appearance & Behavior –System Setting – Reopen last project on startup

terminal

shell path 设置为 git 安装路径的/bin/bash.exe

keymap

阅读全文 »

目前Android4.x也算是老设备了,今天做的一个项目访问客户的 HTTPS 服务器,在Android4.x一直抛异常

1
javax.net.ssl.SSLException: Connection closed by peer

这是由于 Android4.x 默认关闭 TLS 的支持和 OkHTTP3.x 的问题,这个问题的讨论在于 issues/2372

解决这个问题有两个大方向:

  1. 服务器配置兼容支持TLS1.0、TLS1.1、TLS1.2,这样客户端就不需要做任何处理,完美兼容
  2. Android端开启TLS1.2支持
阅读全文 »