-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
621 lines (316 loc) · 22.6 KB
/
index.html
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Less is more">
<meta name="generator" content="Hugo 0.56.0" />
<title>Simple...</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/pure/0.6.0/pure-min.css">
<!--[if lte IE 8]>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/pure/0.6.0/grids-responsive-old-ie-min.css">
<![endif]-->
<!--[if gt IE 8]><!-->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/pure/0.6.0/grids-responsive-min.css">
<!--<![endif]-->
<!--[if lte IE 8]>
<link rel="stylesheet" href="/css/side-menu-old-ie.css">
<![endif]-->
<!--[if gt IE 8]><!-->
<link rel="stylesheet" href="/css/side-menu.css">
<!--<![endif]-->
<link rel="stylesheet" href="/css/blackburn.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
<link href="https://fonts.googleapis.com/css?family=Raleway" rel="stylesheet" type="text/css">
<link rel="alternate" type="application/rss+xml" title="Simple..." href="http://coofee.github.ioindex.xml" />
<link rel="shortcut icon" href="http://coofee.github.ioimg/favicon.ico" type="image/x-icon" />
</head>
<body>
<div id="layout">
<a href="#menu" id="menuLink" class="menu-link">
<span></span>
</a>
<div id="menu">
<div class="pure-menu">
<ul class="pure-menu-list">
</ul>
</div>
<div class="pure-menu social">
<ul class="pure-menu-list">
<li class="pure-menu-item">
<a class="pure-menu-link" href="http://coofee.github.ioindex.xml"><i class="fa fa-rss fa-fw"></i>RSS</a>
</li>
</ul>
</div>
<div class="pure-g">
<div class="small-print pure-u-1 pure-u-md-1-1">
<small></small>
</div>
<div class="small-print pure-u-1 pure-u-md-1-1">
<small>Built with <a href="https://gohugo.io/" target="_blank">Hugo</a></small>
<small>Theme <a href="https://github.com/yoshiharuyamashita/blackburn" target="_blank">Blackburn</a></small>
</div>
</div>
</div>
<div id="main">
<div class="header">
<h1>Simple...</h1>
<h2></h2>
</div>
<div class="content">
<article>
<header>
<h2><a href="http://coofee.github.io/post/view-visibility/">view visibility</a></h2>
<div class="post-meta">
<div>
<i class="fa fa-calendar fa-fw"></i>
<time>12 Sep 2019, 15:40</time>
</div>
<div>
<i class="fa fa-tags fa-fw"></i>
<a class="post-taxonomy-tag" href="http://coofee.github.iotags/android">android</a> /
<a class="post-taxonomy-tag" href="http://coofee.github.iotags/view">view</a> /
<a class="post-taxonomy-tag" href="http://coofee.github.iotags/view-lifecycle">view lifecycle</a>
</div>
</div>
</header>
<p>
View的hide埋点缺失 通常针对一个View进行埋点时,一般会有show/hide两个埋点,分别对应于View的展现和消失。
而在View的生命周期中,其onAttachedToWindow()回调方法表示View即将展现;与之相对的onDetachedFromWindow()回调方法则表示View即将消失。所以,一般针对show/hide两个埋点,直接在onAttachedToWindow()和onDetachedFromWindow()中埋点即可。
然而当我们打开一个新的Activity页面时,我们会发现此时View已经看不到了,但是由于其onDetachedFromWindow()方法没有被系统回调,所以我们只有show埋点,而没有hide埋点,那么问题就来了,如果让show/hide这两个埋点就对应上呢?
View的生命周期 对于一个View来说,其本身涉及的回调函数有很多,在此我们只关注与View的展现/消失相关的回调函数,为了方便描述,我们将该类函数统称为View的生命周期函数。其主要包括如下函数:
// View被添加到Window时被调用,View开始绘制。 // View是可见的。 protected void onAttachedToWindow() {} // View所属于的Window展现/消失时被调用。 // View的展现/消失由visibility决定。 protected void onWindowVisibilityChanged(int visibility) {} // View或其祖先View的visibility发生改变时被调用。 // View的展现/消失由visibility决定。 // 注意: 滑动RecyclerView,当一个item view消失时该方法不会被调用。 protected void onVisibilityChanged(@NonNull View changedView, int visibility) {} // View从Window移除时被调用,View不再绘制。 // View不可见。 protected void onDetachedFromWindow() {} 通过以上方法,我们就可以知道一个View的可见状态是显示还是隐藏了。
获取View的可见状态 获取View的可见状态整体流程如下:
LifecycleView -> ViewLifecycle -> ViewVisibilityObserver -> OnViewVisibilityChangedListener 首先通过重写View的上述生命周期函数来监听View的状态并将其分发出去。
public class LifecycleView extends View implements ViewLifecycleOwner { @Override protected void onWindowVisibilityChanged(int visibility) { super.
</p>
<footer>
<a href="/post/view-visibility/">Read more<i class="fa fa-angle-double-right fa-fw"></i></a>
</footer>
</article>
<article>
<header>
<h2><a href="http://coofee.github.io/post/how_to_write_sqlites_extension/">How to write sqlites extension</a></h2>
<div class="post-meta">
<div>
<i class="fa fa-calendar fa-fw"></i>
<time>12 Aug 2019, 19:18</time>
</div>
<div>
<i class="fa fa-tags fa-fw"></i>
<a class="post-taxonomy-tag" href="http://coofee.github.iotags/android">android</a> /
<a class="post-taxonomy-tag" href="http://coofee.github.iotags/sqlite3">sqlite3</a> /
<a class="post-taxonomy-tag" href="http://coofee.github.iotags/sqlite3-extension">sqlite3 extension</a> /
<a class="post-taxonomy-tag" href="http://coofee.github.iotags/latitude-and-longitude-distance">latitude and longitude distance</a>
</div>
</div>
</header>
<p>
0x00 SQLite sqlite是一个使用c语音编写的库,其实现了一个的小巧、快速、自含、高可靠性、全功能的SQL数据库引擎。它仅依赖少数的几个系统调用。它是一个非常流行的数据库,几乎打包到了所有的移动设备中,同时有无数的应用程序内嵌了它。
0x01 SQLite扩展 sqlite extension是可以在运行时被sqlite加载的库,其主要有以下作用:
扩展sqlite的功能,如提供sqlite本身不支持的函数。 运行时加载扩展,可以动态更新,也可以保证只在需要时加载扩展,减少内存消耗。 扩展可以独立于sqlite本身单独开发,测试。 0x02 编写扩展 编写扩展时,我们可以从sqlite的官网复制一份模板代码,整个模板代码如下所示:
/* Add your header comment here */ #include <sqlite3ext.h> /* Do not use <sqlite3.h>! */ SQLITE_EXTENSION_INIT1 /* Insert your extension code here */ #ifdef _WIN32 __declspec(dllexport) #endif /* TODO: Change the entry point name so that "extension" is replaced by ** text derived from the shared library filename as follows: Copy every ** ASCII alphabetic character from the filename after the last "/" through ** the next following ".
</p>
<footer>
<a href="/post/how_to_write_sqlites_extension/">Read more<i class="fa fa-angle-double-right fa-fw"></i></a>
</footer>
</article>
<article>
<header>
<h2><a href="http://coofee.github.io/post/auto_create_wx_acitivty_by_annotation/">auto_create_wx_acitivty_by_annotation</a></h2>
<div class="post-meta">
<div>
<i class="fa fa-calendar fa-fw"></i>
<time>10 Sep 2018, 15:05</time>
</div>
</div>
</header>
<p>
如何使用注解生成WXEntryActivity? 在Android中使用注解时,需要创建java模块,否则无法导入javax.annotation.processing.AbstractProcessor;相关依赖。
1. android注解配置 1. 使用annotationProcessor设置参数 a) /gradle/wrapper/gradle-wrapper.properties
distributionUrl = https\://services.gradle.org/distributions/gradle-4.4-all.zip b) 配置annotationProcessor
buildscript { repositories { // Gradle 4.1 and higher include support for Google's Maven repo using // the google() method. And you need to include this repo to download // Android plugin 3.0.0 or higher. google() ... } dependencies { classpath 'com.android.tools.build:gradle:3.1.0' } } android { defaultConfig { javaCompileOptions { annotationProcessorOptions { arguments = [ key1 : 'key1Value', key2 : 'key2Value' ] } } } } dependencies { annotationProcessor 'xxx:xx:xxx' } 2.
</p>
<footer>
<a href="/post/auto_create_wx_acitivty_by_annotation/">Read more<i class="fa fa-angle-double-right fa-fw"></i></a>
</footer>
</article>
<article>
<header>
<h2><a href="http://coofee.github.io/post/golang-dev/">golang dev</a></h2>
<div class="post-meta">
<div>
<i class="fa fa-calendar fa-fw"></i>
<time>06 Sep 2018, 19:36</time>
</div>
</div>
</header>
<p>
配置Golang开发环境(仅介绍Mac平台) install Homebrew $ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" install golang $ brew install go $ go version go version go1.11 darwin/amd64 # 配置GOROOT $ printf "\n\nexport GOROOT=/usr/local/Cellar/go/1.11/libexec \n" >> ~/.bash_profile # 配置GOPATH $ mkdir -p ~/go/gopath $ printf "export GOPATH=~/go/gopath \n" >> ~/.bash_profile # 追加到PATH $ printf "export GOBIN=$GOROOT/bin \n" >> ~/.bash_profile $ printf "export PATH=$PATH:$GOBIN:$GOPATH/bin \n\n" >> ~/.bash_profile $ source ~/.bash_profile install privoxy privoxy可以将http请求代理到socks5,下面将 privoxy + shadowsocks 搭配使用
</p>
<footer>
<a href="/post/golang-dev/">Read more<i class="fa fa-angle-double-right fa-fw"></i></a>
</footer>
</article>
<article>
<header>
<h2><a href="http://coofee.github.io/post/flutter/">flutter</a></h2>
<div class="post-meta">
<div>
<i class="fa fa-calendar fa-fw"></i>
<time>06 Sep 2018, 19:33</time>
</div>
</div>
</header>
<p>
[TOC]
0x00 Flutter flutter是google开发的移动端UI框架,支持android和ios。该框架使用dart语言进行开发,在skia的基础上开发了一套公共组件达到android与ios共用代码的目的。
1. Flutter系统架构 2. Platform Channels flutter使用methodChannel/flutterMethodChannel来访问系统原生api。 0x01 使用Flutter开发应用程序 1. 下载配置Flutter SDK 由于众所周知的原因,我们首先需要进行如下配置,让flutter通过国内镜像下载sdk等依赖。
export PUB_HOSTED_URL=https://pub.flutter-io.cn export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn 安装sdk
$ git clone -b beta https://github.com/flutter/flutter.git $ export PATH=`pwd`/flutter/bin:$PATH 使用flutter doctor检测本机环境,然后根据提示安装依赖软件。
$ flutter doctor Doctor summary (to see all details, run flutter doctor -v): [✓] Flutter (Channel beta, v0.1.5, on Mac OS X 10.11.6 15G19009, locale zh-Hans) [✓] Android toolchain - develop for Android devices (Android SDK 27.
</p>
<footer>
<a href="/post/flutter/">Read more<i class="fa fa-angle-double-right fa-fw"></i></a>
</footer>
</article>
<article>
<header>
<h2><a href="http://coofee.github.io/post/rxjava-distinguish-user-cancel-from-others/">rxjava distinguish user cancel from others</a></h2>
<div class="post-meta">
<div>
<i class="fa fa-calendar fa-fw"></i>
<time>06 Nov 2017, 20:35</time>
</div>
<div>
<i class="fa fa-tags fa-fw"></i>
<a class="post-taxonomy-tag" href="http://coofee.github.iotags/android">android</a> /
<a class="post-taxonomy-tag" href="http://coofee.github.iotags/rxjava">rxjava</a>
</div>
</div>
</header>
<p>
RxJava区分用户主动取消 0x00 取消订阅 首先我们知道使用rxjava执行操作的时候,基本流程大致如下,取消操作时只需要调用subscription.unsubscribe()即可:
Subscription subscription = Observable.<String>create(new Observable.OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { try { Thread.sleep(5 * 1000); } catch (InterruptedException e) { } println("call..."); subscriber.onNext("aaaaaaa"); subscriber.onCompleted(); } }).subscribeOn(Schedulers.io()) .observeOn(Schedulers.newThread()) .unsubscribeOn(Schedulers.newThread()) .subscribe(new PrintSubscriber<>()); 那么我们在执行操作的过程中,如何知道一个操作被取消了呢?熟悉rxjava的童鞋可能一下子就会想到,直接使用doOnUnsubscribe()不就可以了吗?这有什么好纠结的。
Subscription subscription = Observable.<String>create(new Observable.OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { try { Thread.sleep(5 * 1000); } catch (InterruptedException e) { } println("call..."); subscriber.onNext("aaaaaaa"); subscriber.onCompleted(); } }).
</p>
<footer>
<a href="/post/rxjava-distinguish-user-cancel-from-others/">Read more<i class="fa fa-angle-double-right fa-fw"></i></a>
</footer>
</article>
<article>
<header>
<h2><a href="http://coofee.github.io/post/rxjava2/">rxjava 2.0 head first</a></h2>
<div class="post-meta">
<div>
<i class="fa fa-calendar fa-fw"></i>
<time>10 Oct 2017, 20:35</time>
</div>
<div>
<i class="fa fa-tags fa-fw"></i>
<a class="post-taxonomy-tag" href="http://coofee.github.iotags/android">android</a> /
<a class="post-taxonomy-tag" href="http://coofee.github.iotags/rxjava">rxjava</a>
</div>
</div>
</header>
<p>
RxJava 2.0 简单介绍 一年一年有一年,RxJava也新增了2.0版本,那么为什么是新增版本而不说升级版本呢?
因为2.0版本和1.0版本两者并不兼容,2.0版本是基于Reactive-Streams规范重新设计而来;同时1.x版本和2.x版本两者会并行开发维护,但是1.x版本只维护到2018-03-31。
下面我们简单介绍一下两者的不同。
0x00 依赖&包名不同 使用rxjava 1.x、2.x版本的依赖如下:
// rxjava 1.x compile 'io.reactivex:rxjava:1.1.6' // rxjava 2.x compile "io.reactivex.rxjava2:rxjava:2.x.y" 包名修改如下:
// 1.x -> 2.x rx.** -> io.reactivex.** 0x01 Observable与Flowable Observable在2.0版本不支持backpressure,它会缓存全部的数据,一一发送给消费者,如果消费不及时,会产生OOM。于此对应,在2.x版本新增了Flowable,支持设置/自定义backpressure,同时在创建时必须制定backpressure。
Flowable.create(new FlowableOnSubscribe<Object>() { @Override public void subscribe(FlowableEmitter<Object> e) throws Exception { for (int i = 0; i < 256; i++) { e.onNext(i); } e.onComplete(); } }, BackpressureStrategy.BUFFER).subscribe(System.out::println, Throwable::printStackTrace); 0x02 Single 当使用Single时,生产者调用onSuccess()通知订阅者,同时终止整个事件流,生产者只能发送一个success事件,订阅者也只能收到一个success事件,适用于网络请求等确定只有单个事件的事件流。对于1.x版本而言,则需要主动调用onComplete()来终止事件流。
注意: Single没有onComplete()方法;只能产生success、error两种事件。
Single.create(s -> s.
</p>
<footer>
<a href="/post/rxjava2/">Read more<i class="fa fa-angle-double-right fa-fw"></i></a>
</footer>
</article>
<article>
<header>
<h2><a href="http://coofee.github.io/post/upgrade-android-studio-gradle/">Gradle plugin 3.0 & Android Studio 3.0</a></h2>
<div class="post-meta">
<div>
<i class="fa fa-calendar fa-fw"></i>
<time>15 Sep 2017, 18:59</time>
</div>
</div>
</header>
<p>
Gradle plugin 3.0 & Android Studio 3.0 我们主要讲一下升级gradle plugin 3.0过程中遇到的问题与解决方案。
Gradle Plugin 3.0 1. 升级gradle plugin插件版本为3.x buildscript { repositories { mavenLocal() jcenter() // You need to add the following repository to download the // for new plugin. google() } dependencies { classpath 'com.android.tools.build:gradle:3.0.0-beta2' } } 2. 升级gradle版本为4.1 修改gradle/wrapper/gradle-wrapper.properties中的distributionUrl为gradle-4.1-all。
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip 3. 升级build-tools为25.0.3 The specified Android SDK Build Tools version (22.0.1) is ignored, as it is below the minimum supported version (25.
</p>
<footer>
<a href="/post/upgrade-android-studio-gradle/">Read more<i class="fa fa-angle-double-right fa-fw"></i></a>
</footer>
</article>
<article>
<header>
<h2><a href="http://coofee.github.io/post/android-check-app-running-foreground/">android check app running foreground</a></h2>
<div class="post-meta">
<div>
<i class="fa fa-calendar fa-fw"></i>
<time>25 Jul 2017, 19:43</time>
</div>
<div>
<i class="fa fa-tags fa-fw"></i>
<a class="post-taxonomy-tag" href="http://coofee.github.iotags/android">android</a> /
<a class="post-taxonomy-tag" href="http://coofee.github.iotags/app-running-background">app running background</a>
</div>
</div>
</header>
<p>
0x00 使用Application.ActivityLifecycleCallbacks检测App运行在前台/后台 import android.app.Activity; import android.app.ActivityManager; import android.app.Application; import android.content.Context; import android.os.Bundle; import android.os.Handler; import android.util.Log; import java.util.List; public class ApplicationLifecycle implements Application.ActivityLifecycleCallbacks { private Handler mHandler = new Handler(); private Runnable mCheck = new Runnable() { @Override public void run() { Log.e("ApplicationLifecycle", "check task exec; mCounter=" + mCounter); if (mCounter == 0) { Log.e("ApplicationLifecycle", "check task exec; get runningAppProcessInfo."); final ActivityManager am = (ActivityManager) mAppContext.getSystemService(Context.ACTIVITY_SERVICE); // NOTE: getRunningAppProcess() ONLY GIVE YOU THE PROCESS OF YOUR OWN PACKAGE IN ANDROID M // BUT THAT'S ENOUGH HERE List<ActivityManager.
</p>
<footer>
<a href="/post/android-check-app-running-foreground/">Read more<i class="fa fa-angle-double-right fa-fw"></i></a>
</footer>
</article>
<article>
<header>
<h2><a href="http://coofee.github.io/post/upgrade-app-signature-algorithm/">sha1-collision & android signature algorithm</a></h2>
<div class="post-meta">
<div>
<i class="fa fa-calendar fa-fw"></i>
<time>21 Jul 2017, 18:35</time>
</div>
<div>
<i class="fa fa-tags fa-fw"></i>
<a class="post-taxonomy-tag" href="http://coofee.github.iotags/android-sign-algorithm">android sign algorithm</a> /
<a class="post-taxonomy-tag" href="http://coofee.github.iotags/sha-1-collision">sha-1 collision</a> /
<a class="post-taxonomy-tag" href="http://coofee.github.iotags/shaa-256">shaa-256</a>
</div>
</div>
</header>
<p>
SHA1-Collision & Android Sign 参看SHA1-collision我们可以知道,SHA-1签名已经不安全了,签名算法可以考虑升级到SHA-2或者其他算法。
0x01 SHA1-Collision 1. SHA-1是什么? SHA-1(英语:Secure Hash Algorithm 1,中文名:安全散列算法1)是一种密码散列函数,美国国家安全局设计,并由美国国家标准技术研究所(NIST)发布为联邦数据处理标准(FIPS)[2]。SHA-1可以生成一个被称为消息摘要的160位(20字节)散列值,散列值通常的呈现形式为40个十六进制数,参考:SHA-1
2. SHA1-Collision是什么? 两个内容不同的数据,SHA-1算法会生成相同的摘要信息,参考:SHA1 collision Two PDF。
3. SHA1-Collision对Android的影响 Android SDK默认对apk使用SHA-1签名,在最坏的情况下,攻击者可以伪造SHA-1值相同的文件替换已签名apk中的文件来达到攻击的目的。
0x02 Android的证书验证机制 我们知道Android的Apk文件是一个压缩文件,文件结构大致如下:
. ├── AndroidManifest.xml ├── META-INF │ ├── CERT.RSA │ ├── CERT.SF │ └── MANIFEST.MF ├── assets ├── classes.dex ├── classes2.dex ├── classes3.dex ├── lib ├── res └── resources.arsc apk相关的签名相关的文件在META-INF目录中,其中:
MANIFEST.MF
遍历APK包中除了META-INF\文件夹以外的所有文件,利用SHA-1算法生成这些文件的消息摘要,然后转化为对应的base64编码。MANIFEST.MF存储的是文件的摘要值,保证完整性,防止文件被篡改。
.SF
xx.SF文件(xx为使用者证书的自定义别名,默认为CERT,即CERT.SF),保存的是MANIFEST.MF的摘要值, 以及MANIFEST.MF中每一个摘要项的摘要值,然后转化成对应的base64编码。虽然该文件的后缀名.sf(SignatureFile)看起来是签名文件,但是并没有私钥参与运算,也不保存任何签名内容。
.RSA/.DSA
.RSA/.DSA文件(后缀不同采用的签名算法不同,.RSA使用的是RSA算法,.DSA使用的是数字签名算法DSA,目前APK主要使用的是这两种算法),保存的是第二项.SF文件的数字签名,同时还会包括签名采用的数字证书(公钥)。特别说明,当使用多重证书签名时,每一个.sf文件必须有一个.RSA/.DSA文件与之对应,也就是说使用证书CERT1签名时有CERT1.SF和CERT1.RSA,同时采用证书CERT2签名时又会生成CERT2.SF和CERT2.RSA。
Android 系统不允许安装没有任何数字签名的应用APK程序,所有应用程序必须使用某个证书进行签名(一般为应用开发者自签名证书),
</p>
<footer>
<a href="/post/upgrade-app-signature-algorithm/">Read more<i class="fa fa-angle-double-right fa-fw"></i></a>
</footer>
</article>
<nav class="pagination" role="pagination">
<span>1 / 3</span>
<a href="/page/2/"><i class="fa fa-angle-double-right"></i></a>
</nav>
</div>
</div>
</div>
<script src="http://coofee.github.iojs/ui.js"></script>
</body>
</html>