赞
踩
初级工程师拿到需求会直接开始做,然后做着做着发现有问题了,要么技术实现不了,要么逻辑有问题。
而高级工程师拿到需求会考虑很多,技术的可行性?对现有业务有没有帮助?对现有技术架构的影响?扩展性如何?等等…之后才会再进行设计编码阶段。
而现在随着跨平台开发,混合式开发,前端开发之类的热门,Android开发者需要学习和掌握的技术也在不断的增加。
通过和一些行业里的朋友交流讨论,以及参考现在大厂面试的要求。我们花了差不多一个月时间整理出了这份Android高级工程师需要掌握的所有知识体系。你可以看下掌握了多少。
混合式开发,微信小程序。都是得学会并且熟练的
这些是Android相关技术的内核,还有Java进阶
高级进阶必备的一些技术。像移动开发架构项目实战等
Android前沿技术;包括了组件化,热升级和热修复,以及各种架构跟框架的详细技术体系
以上即是我们整理的Android高级工程师需要掌握的技术体系了。可能很多朋友觉得很多技术自己都会了,只是一些新的技术不清楚而已。应该没什么太大的问题。
而这恰恰是问题所在!为什么别人高级工程师能年限突破30万,而你只有十几万呢?
就因为你只需补充你自己认为需要的,但并不知道企业需要的。这个就特别容易造成差距。因为你的技术体系并不系统,是零碎的,散乱的。那么你凭什么突破30万年薪呢?
我这些话比较直接,可能会戳到一些人的玻璃心,但是我知道肯定会对一些人起到点醒的效果的。而但凡只要有人因为我的这份高级系统大纲以及这些话找到了方向,并且付出行动去提升自我,为了成功变得更加努力。那么我做的这些就都有了意义。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
在获取地址的过程中会调用RIMEMD-160算法处理公钥hash:
//Utils.java
public static byte[] sha256hash160(byte[] input) {
byte[] sha256 = Sha256Hash.hash(input);
RIPEMD160Digest digest = new RIPEMD160Digest();
digest.update(sha256, 0, sha256.length);
byte[] out = new byte[20];
digest.doFinal(out, 0);
return out;
}
处理公钥hash后会进行Base58算法:
//VersionedChecksummedBytes.java
public final String toBase58() {
// A stringified buffer is:
// 1 byte version + data bytes + 4 bytes check code (a truncated hash)
byte[] addressBytes = new byte[1 + bytes.length + 4];
addressBytes[0] = (byte) version;
System.arraycopy(bytes, 0, addressBytes, 1, bytes.length);
byte[] checksum = Sha256Hash.hashTwice(addressBytes, 0, bytes.length + 1);
System.arraycopy(checksum, 0, addressBytes, bytes.length + 1, 4);
return Base58.encode(addressBytes);
}
//读取钱包文件
File walletFile = activity.getFileStreamPath(“wallet-protobuf”);
if (walletFile.exists()) {
InputStream inputStream = new FileInputStream(walletFile);
//反序列化
wallet = new WalletProtobufSerializer().readWallet(inputStream);
//设置自动保存
wallet.autosaveToFile(walletFile, 3 * 1000, TimeUnit.MILLISECONDS, null);
//清理钱包
wallet.cleanup();
}
String s = BitcoinURI.convertToBitcoinURI(address, null, null, null);
Bitmap bitmap = Qr.bitmap(s);
BitmapDrawable bitmapDrawable = new BitmapDrawable(getResources(), bitmap);
bitmapDrawable.setFilterBitmap(false);
mQrImageView.setImageDrawable(bitmapDrawable);
public static Bitmap bitmap(final String content) {
try {
final Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
hints.put(EncodeHintType.MARGIN, 0);
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
final BitMatrix result = QR_CODE_WRITER.encode(content, BarcodeFormat.QR_CODE, 0, 0, hints);
final int width = result.getWidth();
final int height = result.getHeight();
final byte[] pixels = new byte[width * height];
for (int y = 0; y < height; y++) {
final int offset = y * width;
for (int x = 0; x < width; x++) {
pixels[offset + x] = (byte) (result.get(x, y) ? -1 : 0);
}
}
final Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ALPHA_8);
bitmap.copyPixelsFromBuffer(ByteBuffer.wrap(pixels));
return bitmap;
} catch (final WriterException x) {
log.info(“problem creating qr code”, x);
return null;
}
}
比特币钱包余额需要统计所有钱包地址对应的UTXO
Simplified Payment Verification (SPV):节点无需下载所有的区块数据,而只需要加载所有区块头数据(block header的大小为80B),即可验证这笔交易是否曾经被比特币网络认证过。
布隆过滤器(Bloom Filter):过滤掉那些不包含有目标地址的交易信息,这一步能避免掉大量不相关的数据下载。
//创建区块链文件
File blockChainFile = new File(getDir(“blockstore”, Context.MODE_PRIVATE), “blockchain”);
//创建SPVBlockStore,管理区块数据
blockStore = new SPVBlockStore(Constants.NETWORK_PARAMETERS, blockChainFile);
//加载检查点
final InputStream checkpointsInputStream = getAssets().open(“checkpoints-testnet.txt”);
CheckpointManager.checkpoint(Constants.NETWORK_PARAMETERS, checkpointsInputStream,
blockStore, earliestKeyCreationTime);
//创建区块链对象
blockChain = new BlockChain(Constants.NETWORK_PARAMETERS, wallet, blockStore);
//添加网络权限:
private void startup() {
Log.d(TAG, "startup: ");
peerGroup = new PeerGroup(Constants.NETWORK_PARAMETERS, blockChain);
peerGroup.setDownloadTxDependencies(0); // recursive implementation causes StackOverflowError
peerGroup.addWallet(wallet);//设置钱包,重要
try {
PackageInfo packageInfo = getPackageManager().getPackageInfo(getPackageName(), PackageManager.GET_ACTIVITIES);
peerGroup.setUserAgent(USER_AGENT, packageInfo.versionName);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
peerGroup.setMaxConnections(8);
int connectTimeout = (int) (15 * DateUtils.SECOND_IN_MILLIS);
peerGroup.setConnectTimeoutMillis(connectTimeout);
int discoveryTimeout = (int) (10 * DateUtils.SECOND_IN_MILLIS);
peerGroup.addConnectedEventListener(mPeerConnectedEventListener);
peerGroup.addDisconnectedEventListener(mPeerDisconnectedEventListener);
peerGroup.addDiscoveredEventListener(mPeerDiscoveredEventListener);
peerGroup.setPeerDiscoveryTimeoutMillis(discoveryTimeout);
//添加节点探索器,重要
peerGroup.addPeerDiscovery(new PeerDiscovery() {
private final PeerDiscovery normalPeerDiscovery = MultiplexingDiscovery
.forServices(Constants.NETWORK_PARAMETERS, 0);
@Override
public InetSocketAddress[] getPeers(final long services, final long timeoutValue,
final TimeUnit timeoutUnit) throws PeerDiscoveryException {
return normalPeerDiscovery.getPeers(services, timeoutValue, timeoutUnit);
}
@Override
public void shutdown() {
normalPeerDiscovery.shutdown();
}
});
peerGroup.startAsync();
peerGroup.startBlockChainDownload(null);
}
获取测试用比特币:testnet.manu.backend.hamburg/faucet 刚收到的币可能需要几分钟后才能使用
//监听比特币接受事件
wallet.addCoinsReceivedEventListener(mWalletListener);
//刷新余额
Coin balance = wallet.getBalance(Wallet.BalanceType.ESTIMATED);
比特币测试链转账查询 创建一个Tx,对Tx进行签名,对Tx进行P2P网络广播
Address address = Address.fromBase58(Constants.NETWORK_PARAMETERS, to);
//转账金额,以mBTC为单位
Coin coin = MonetaryFormat.MBTC.parse(amount);
//创建请求
SendRequest sendRequest = SendRequest.to(address, coin);
try {
//创建Transaction
Transaction transaction = wallet.sendCoinsOffline(sendRequest);
//通过P2P广播
BlockChainService.broadcastTransaction(BitcoinWalletActivity.this, transaction);
} catch (InsufficientMoneyException e) {
Toast.makeText(this, e.getLocalizedMessage(), Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
public static void broadcastTransaction(Context context, Transaction transaction) {
Intent intent = new Intent(ACTION_BROADCAST_TRANSACTION, null, context, BlockChainService.class);
intent.putExtra(ACTION_BROADCAST_TRANSACTION_HASH, transaction.getHash().getBytes());
context.startService(intent);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand: ");
if (intent != null) {
byte[] txHash = intent.getByteArrayExtra(“tx”);
if (txHash != null) {
Sha256Hash sha256Hash = Sha256Hash.wrap(txHash);
Transaction transaction = BitcoinWalletManager.getInstance().getWallet().getTransaction(sha256Hash);
peerGroup.broadcastTransaction(transaction);
Log.d(TAG, "onStartCommand: " + sha256Hash.toString());
}
}
return super.onStartCommand(intent, flags, startId);
}
以太坊钱包功能与比特币钱包功能类似,获取用户余额,管理地址和密钥,转账、智能合约调用。以太坊钱包一般不用在本地维护区块链数据,只需要使用JSON-RPC访问
KeyStore = 私钥 + 密码
如果使用ImToken创建钱包,创建了助记词,密码用来加密钱包地址对应的子私钥,加密的结果就是Keystore.
{
“address”: “001d3f1ef827552ae1114027bd3ecf1f086ba0f9”,
“crypto”: {
“cipher”: “aes-128-ctr”,
“ciphertext”: “233a9f4d236ed0c13394b504b6da5df02587c8bf1ad8946f6f2b58f055507ece”,
“cipherparams”: {
“iv”: “d10c6ec5bae81b6cb9144de81037fa15”
},
“kdf”: “scrypt”,
“kdfparams”: {
“dklen”: 32,
“n”: 262144,
“p”: 1,
“r”: 8,
“salt”: “99d37a47c7c9429c66976f643f386a61b78b97f3246adca89abe4245d2788407”
},
“mac”: “594c8df1c8ee0ded8255a50caf07e8c12061fd859f4b7c76ab704b17c957e842”
},
“id”: “4fcb2ba4-ccdb-424f-89d5-26cce304bf9c”,
“version”: 3
}
1、使用Secp256k1创建公私钥
2、通过Keccak算法得到公钥Hash值,进而得到长度为40的地址字符串
3、一般的,会在地址字符串签名加前缀"0x"
添加Web3j依赖
implementation ‘org.web3j:core:3.3.1-android’
这里不涉及BIP协议,为非确定性钱包
Wallet.createStandard() 出现OOM, Out of Memory juejin.im/post/684490…
File walletDir = contextWrapper.getDir(“eth”, Context.MODE_PRIVATE);
//生成密钥对
ECKeyPair ecKeyPair = Keys.createEcKeyPair();
//WalletFile = KeyStore
WalletFile wallet = Wallet.createLight(PASSWORD, ecKeyPair);
String walletFileName = getWalletFileName(wallet);
File destination = new File(walletDir, walletFileName);
objectMapper.writeValue(destination, wallet);
File[] files = walletDir.listFiles();
wallet = objectMapper.readValue(files[0], WalletFile.class);
涉及BIP协议,但没有遵循bitcoin地址只使用一次的原则,钱包一般只使用派生出来第一个地址
可通过工具检查派生的地址是否正确
//创建助记词
public List createMnemonics() throws MnemonicException.MnemonicLengthException {
SecureRandom secureRandom = new SecureRandom();
byte[] entropy = new byte[DeterministicSeed.DEFAULT_SEED_ENTROPY_BITS / 8];
secureRandom.nextBytes(entropy);
return MnemonicCode.INSTANCE.toMnemonic(entropy);
}
//m / 44’ / 60’ / 0’ / 0
//Hardened意思就是派生加固,防止获取到一个子私钥之后可以派生出后面的子私钥
//必须还有上一级的父私钥才能派生
public static final ImmutableList BIP44_ETH_ACCOUNT_ZERO_PATH =
ImmutableList.of(new ChildNumber(44, true), new ChildNumber(60, true),
ChildNumber.ZERO_HARDENED, ChildNumber.ZERO);
//通过助记词生成HD钱包
public void onCreateWallet(View view) {
byte[] seed = MnemonicCode.toSeed(words, “”);
DeterministicKey masterPrivateKey = HDKeyDerivation.createMasterPrivateKey(seed);
DeterministicHierarchy deterministicHierarchy = new DeterministicHierarchy(masterPrivateKey);
// m / 44’ / 60’ / 0’ / 0 / 0
DeterministicKey deterministicKey = deterministicHierarchy
.deriveChild(BIP44_ETH_ACCOUNT_ZERO_PATH, false, true, new ChildNumber(0));
byte[] bytes = deterministicKey.getPrivKeyBytes();
ECKeyPair keyPair = ECKeyPair.create(bytes);
try {
WalletFile walletFile = Wallet.createLight(PASSWORD, keyPair);
String address = walletFile.getAddress();
mAddress.setText(“0x” + address);
} catch (CipherException e) {
e.printStackTrace();
}
}
public String exportKeyStore(WalletFile wallet) {
try {
return objectMapper.writeValueAsString(wallet);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
}
public String exportPrivateKey(WalletFile wallet) {
try {
ECKeyPair ecKeyPair = Wallet.decrypt(PASSWORD, wallet);
BigInteger privateKey = ecKeyPair.getPrivateKey();
return Numeric.toHexStringNoPrefixZeroPadded(privateKey, Keys.PRIVATE_KEY_LENGTH_IN_HEX);
} catch (CipherException e) {
e.printStackTrace();
}
return null;
}
一般可以将助记词加密存储,导出时解密。注意无法从KeyStore或者私钥导出助记词。
例如:使用IMToken导入私钥或者KeyStore创建的钱包,没有导出助记词的功能 如果是通过助记词创建的,就会有导出助记词的功能
private Web3j mWeb3j = Web3jFactory.build(new HttpService(“https://ropsten.infura.io/1UoO4I/”));
BigInteger balance = mWeb3j.ethGetBalance(mAddress, DefaultBlockParameterName.LATEST).send().getBalance();
BigDecimal balance = Convert.fromWei(balance.toString(), Convert.Unit.ETHER);
BigInteger transactionCount = mWeb3j.ethGetTransactionCount(mAddress, DefaultBlockParameterName.LATEST).send().getTransactionCount();
BigInteger gasPrice = mWeb3j.ethGasPrice().send().getGasPrice();
BigInteger gasLimit = new BigInteger(“200000”);
BigDecimal value = Convert.toWei(mAmountEdit.getText().toString().trim(), Convert.Unit.ETHER);
String to = mToAddressEdit.getText().toString().trim();
RawTransaction etherTransaction = RawTransaction.createEtherTransaction(transactionCount, gasPrice, gasLimit, to, value.toBigInteger());
ECKeyPair ecKeyPair = Wallet.decrypt(“a12345678”, mWalletFile);
Credentials credentials = Credentials.create(ecKeyPair);
byte[] bytes = TransactionEncoder.signMessage(etherTransaction, credentials);
String hexValue = Numeric.toHexString(bytes);
String transactionHash = mWeb3j.ethSendRawTransaction(hexValue).send().getTransactionHash();
调用ERC20代币智能合约,获取当前地址的余额
//创建Function
private Function balanceOf(String owner) {
return new Function(“balanceOf”,
Collections.singletonList(new Address(owner)),
Collections.singletonList(new TypeReference(){}));
}
Function function = balanceOf(mAddress);
//调用智能合约
String s = callSmartContractFunction(function, CONTRACT_ADDRESS);
List decode = FunctionReturnDecoder.decode(s, function.getOutputParameters());
if (decode != null && decode.size() > 0) {
Uint256 type = (Uint256) decode.get(0);
BigInteger tokenBalance = type.getValue();
}
private String callSmartContractFunction(
Function function, String contractAddress) throws Exception {
String encodedFunction = FunctionEncoder.encode(function);
org.web3j.protocol.core.methods.response.EthCall response = mWeb3j.ethCall(
Transaction.createEthCallTransaction(
mAddress, contractAddress, encodedFunction),
DefaultBlockParameterName.LATEST)
.sendAsync().get();
return response.getValue();
}
//创建Function
private Function transfer(String to, BigInteger value) {
return new Function(
“transfer”,
Arrays.asList(new Address(to), new Uint256(value)),
Collections.singletonList(new TypeReference() {}));
}
Function transfer = transfer(to, new BigInteger(amount));
//获取私钥,进行签名
ECKeyPair ecKeyPair = Wallet.decrypt(“a12345678”, mWalletFile);
Credentials credentials = Credentials.create(ecKeyPair);
String transactionHash = execute(credentials, transfer, CONTRACT_ADDRESS);
//执行合约调用
private String execute(
第一章、 热修复设计
第一节、 AOT/JIT & dexopt 与 dex2oat
第二节、 热修复设计之 CLASS_ISPREVERIFIED 问题
第三节、热修复设计之热修复原理
第四节、Tinker 的集成与使用(自动补丁包生成)
第二章、 插件化框架设计
第一节、 Class 文件与 Dex 文件的结构解读
第二节、 Android 资源加载机制详解
第三节、 四大组件调用原理
第四节、 so 文件加载机制
第五节、 Android 系统服务实现原理
第三章、 组件化框架设计
第一节、阿里巴巴开源路由框——ARouter 原理分析
第二节、APT 编译时期自动生成代码&动态类加载
第三节、 Java SPI 机制
第四节、 AOP&IOC
第五节、 手写组件化架构
第四章、图片加载框架
第一节、图片加载框架选型
第二节、Glide 原理分析
第三节、手写图片加载框架实战
第五章、网络访问框架设计
第一节、网络通信必备基础
第二节、OkHttp 源码解读
第三节、Retrofit 源码解析
第六章、 RXJava 响应式编程框架设计
第一节、链式调用
第二节、 扩展的观察者模式
第三节、事件变换设计
第四节、Scheduler 线程控制
第七章、 IOC 架构设计
第一节、 依赖注入与控制反转
第二节、ButterKnife 原理上篇、中篇、下篇
第三节、Dagger 架构设计核心解密
第八章、 Android 架构组件 Jetpack
第一节、 LiveData 原理
第二节、 Navigation 如何解决 tabLayout 问题
第三节、 ViewModel 如何感知 View 生命周期及内核原理
第四节、 Room 架构方式方法
第五节、 dataBinding 为什么能够支持 MVVM
第六节、 WorkManager 内核揭秘
第七节、 Lifecycles 生命周期
本文包含不同方向的自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中…
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
第一节、 LiveData 原理*
第二节、 Navigation 如何解决 tabLayout 问题
第三节、 ViewModel 如何感知 View 生命周期及内核原理
第四节、 Room 架构方式方法
第五节、 dataBinding 为什么能够支持 MVVM
第六节、 WorkManager 内核揭秘
第七节、 Lifecycles 生命周期
[外链图片转存中…(img-zzDPeqbc-1714973698824)]
本文包含不同方向的自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中…
[外链图片转存中…(img-c0o1RVDo-1714973698825)]
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。