Allen 专栏-移动互联网

跨越 10 个版本 Solo 升级到最新版本2.9.3 有更新!

前言

我的博客Allen 专栏-移动互联网,环境是腾讯云的 Centos,版本是 7.2,时隔一年过去,最新博客版本已经是 2.9.3,遂决定升级。Github查询升级策略,得知不可以跳版本升级, 抓狂(需要跨越 10个版本升级),今天下午,硬着头皮上了。

过程

数据备份
  • 下载DataGrip对原始博客数据进行备份
  • 将备份的数据拷贝到本机,将在本机完成升级后再部署到云上。
升级前准备

准备sourceTree
准备IDEA
准备DataGrip

版本升级日志日志SourceTree截图

版本升级日志日

升级及验证
  1. 从 2.2.0 到 2.9.3,逐个拉起tag 本地idea 重新编译部署
  2. 每次tag切换完成后, 修改 latke.properties 及 local.properties。
  3. 启动 IDEA,编译运行 ,升级成功后 自动打开浏览器 localhost 请求首页,此时系统会自动完成升级。
  4. 等待 30S,检查 preference 或 option 表的 version 字段,看是否升级成功(版本号是否更新)。
  5. 视情况进行下一步或排错。
升级后扫尾
  • 直到升级到最新版本,在本机将升级成功后的数据库导出,和程序包一起上传至腾讯云,同时检查程序的配置文件 latke.properties 及 local.properties。

总结

升级过程还是很顺利的,升级完之后,顺便把之前的https的个人免费证书再次配上了。偷懒了一年,是该拾取原来的东西了,该用的时候还得用上。
但是升级的步骤真的很无聊,十几个版本,依次这种操作,其实solo团队应该增加一个升级更新脚本,可以跨版本升级,满足这种大版本跳跃升级的需求
升级过程中,顺便翻阅solo的更新日志,看得出作者和维护团队都很尽心尽力将这个开源项目做好,在这里,表示感谢!!

Calendar的add方法中的DAY_OF_MONTH参数和DAY_OF_YEAR参数有什么区别? 有更新!

简单来说,没区别。

Calendar 类的 add 方法是个抽象方法,在 JDK 中有三个类实现了这个方法,分别是:

  • java.util.JapaneseImperialCalendar

  • java.util.GregorianCalendar

  • sun.util.BuddhistCalendar

忽略第三个,只看前两个实现类,有这么一段代码:

case DAY_OF_MONTH: // synonym of DATE
case DAY_OF_YEAR:
case DAY_OF_WEEK:
    break;

粗看一下,break以后的执行分支并没有针对这三种做区别处理。
而且 amount 似乎没有受第一个参数的范围限制,比如调用:

calendar.add(Calendar.DAY_OF_MONTH, 100);

可以看到最终结果的 day_of_year 还是增长了100 天。

这个方法的 API 中描述的两个规则可以解释这种超过范围情况:

Add rule 1. The value of field after the call minus the value of field
before the call is amount, modulo any overflow that has occurred in
field. Overflow occurs when a field value exceeds its range and, as a
result, the next larger field is incremented or decremented and the
field value is adjusted back into its range.

Add rule 2. If a smaller field is expected to be invariant, but it is
impossible for it to be equal to its prior value because of changes in
its minimum or maximum after field is changed, then its value is
adjusted to be as close as possible to its expected value. A smaller
field represents a smaller unit of time. HOUR is a smaller field than
DAY_OF_MONTH. No adjustment is made to smaller fields that are not
expected to be invariant. The calendar system determines what fields
are expected to be invariant.

所以我觉得这两个方法调用没有区别,即便 amount 超出了 day_of_month 的范围,这个方法也会正确处理。
不过从可读性考虑,还是用适当的参数比较好。

文章转载自 https://segmentfault.com/q/1010000004275325

Jupyter Notebook 分析运动模型

import os as os
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# 数据格式
orientationX,orientationY,orientationZ,world_accelerometerX,world_accelerometerY,world_accelerometerZ
1.202669,-0.351937,0.035280,0.152070,0.369052,9.003349
0 1.200916,-0.352036,0.036314,0.029368,0.487795,...
1 1.191972,-0.351980,0.037856,-0.098848,0.156166...
2 1.186100,-0.348452,0.036277,0.066162,-0.294649...
3 1.181217,-0.347043,0.034305,0.053812,-0.307321...
4 1.191511,-0.345502,0.031640,-0.080843,0.073440...
5 1.197771,-0.344494,0.030718,-0.268438,0.376443...
6 1.205506,-0.342699,0.031295,-0.342979,0.038622...
7 1.201536,-0.341691,0.029713,-0.308891,-0.40908...
8 1.206752,-0.338629,0.027096,-0.180185,-0.78439...
9 1.189720,-0.337710,0.025001,-0.016011,-0.90016...
10 1.188346,-0.335357,0.020660,-0.010016,-0.66437...
11 1.182130,-0.335195,0.020691,-0.168150,-0.08738...
12 1.191688,-0.334611,0.020730,-0.318920,0.537937...
13 1.189974,-0.335423,0.022399,-0.329259,0.755035...
14 1.203741,-0.335940,0.026293,-0.070470,0.440032...
15 1.204384,-0.337948,0.026441,0.174845,-0.220265...
16 1.202886,-0.342656,0.026160,0.182681,-0.621191...
17 1.189893,-0.344865,0.023103,0.150804,-0.733242...
18 1.186932,-0.346718,0.023389,-0.082537,-0.36582...
19 1.184310,-0.347660,0.022779,-0.180841,0.055544...
20 1.179736,-0.348779,0.023385,-0.218992,0.540119...
21 1.178087,-0.349583,0.025911,-0.006427,0.492867...
22 1.178802,-0.350321,0.025646,0.133606,0.202018,...
23 1.164416,-0.351872,0.025682,0.198423,-0.351209...
24 1.168749,-0.352112,0.025120,0.063690,-0.899801...
25 1.167735,-0.351873,0.021966,-0.135112,-1.00265...
26 1.170264,-0.350667,0.021338,-0.322740,-0.73996...
27 1.174926,-0.347044,0.018143,-0.351066,-0.29029...
28 1.190670,-0.345708,0.017527,-0.313132,-0.09275...
29 1.188927,-0.344971,0.017858,-0.141977,0.155593...
... ...
121646 1.203871,0.340158,-0.905497,-0.995467,-0.29141...
121647 1.138590,0.343419,-0.908940,-1.009314,-0.34160...
121648 1.138590,0.343419,-0.908940,-0.980498,-0.25634...
121649 1.119260,0.344839,-0.910607,-0.886564,-0.23111...
121650 1.119260,0.344839,-0.910607,-0.854298,-0.14274...
121651 1.213301,0.346194,-0.911407,-0.920431,-0.04586...
121652 1.213419,0.347656,-0.912726,-0.827374,-0.06716...
121653 1.213419,0.347656,-0.912726,-1.043766,-0.11626...
121654 1.177102,0.348217,-0.913946,-1.011394,-0.18760...
121655 1.177102,0.348217,-0.913946,-1.048592,-0.16886...
121656 1.142298,0.348099,-0.914461,-1.149854,-0.22330...
121657 1.142298,0.348099,-0.914461,-1.179157,-0.19167...
121658 1.173866,0.348120,-0.913902,-1.140562,-0.13793...
121659 1.173866,0.348120,-0.913902,-1.148874,0.106232...
121660 1.103764,0.348767,-0.912465,-1.265401,0.025554...
121661 1.103764,0.348767,-0.912465,-1.275287,-0.02291...
121662 1.091189,0.349590,-0.910857,-1.171825,0.008048...
121663 1.091189,0.349590,-0.910857,-1.163578,-0.11556...
121664 1.113554,0.350159,-0.909639,-1.077687,-0.15680...
121665 1.147780,0.350319,-0.909358,-1.094061,-0.14901...
121666 1.147780,0.350319,-0.909358,-1.190770,-0.14847...
121667 1.150275,0.351600,-0.908222,-1.042431,-0.26741...
121668 1.150275,0.351600,-0.908222,-1.025228,-0.28615...
121669 1.140762,0.352663,-0.907117,-0.936975,-0.20711...
121670 1.191499,0.353653,-0.905951,-0.961837,-0.22595...
121671 1.191499,0.353653,-0.905951,-0.915990,0.072008...
121672 1.216137,0.354658,-0.904944,-0.926901,0.087669...
121673 1.216137,0.354658,-0.904944,-1.070568,-0.07154...
121674 1.281445,0.355040,-0.904827,-1.056531,-0.02863...
121675 1.281445,0.355040,-0.904827,-1.129279,-0.10096...

121676 rows × 1 columns

data =pd.read_table('SensorData/bus_data_set_101')
data = pd.DataFrame(data)
data
orientationX orientationY orientationZ world_accelerometerX world_accelerometerY world_accelerometerZ
0 NaN NaN NaN NaN NaN NaN
1 NaN NaN NaN NaN NaN NaN
2 NaN NaN NaN NaN NaN NaN
3 NaN NaN NaN NaN NaN NaN
4 NaN NaN NaN NaN NaN NaN
5 NaN NaN NaN NaN NaN NaN
6 NaN NaN NaN NaN NaN NaN
7 NaN NaN NaN NaN NaN NaN
8 NaN NaN NaN NaN NaN NaN
9 NaN NaN NaN NaN NaN NaN
10 NaN NaN NaN NaN NaN NaN
11 NaN NaN NaN NaN NaN NaN
12 NaN NaN NaN NaN NaN NaN
13 NaN NaN NaN NaN NaN NaN
14 NaN NaN NaN NaN NaN NaN
15 NaN NaN NaN NaN NaN NaN
16 NaN NaN NaN NaN NaN NaN
17 NaN NaN NaN NaN NaN NaN
18 NaN NaN NaN NaN NaN NaN
19 NaN NaN NaN NaN NaN NaN
20 NaN NaN NaN NaN NaN NaN
21 NaN NaN NaN NaN NaN NaN
22 NaN NaN NaN NaN NaN NaN
23 NaN NaN NaN NaN NaN NaN
24 NaN NaN NaN NaN NaN NaN
25 NaN NaN NaN NaN NaN NaN
26 NaN NaN NaN NaN NaN NaN
27 NaN NaN NaN NaN NaN NaN
28 NaN NaN NaN NaN NaN NaN
29 NaN NaN NaN NaN NaN NaN
... ... ... ... ... ... ...
121646 NaN NaN NaN NaN NaN NaN
121647 NaN NaN NaN NaN NaN NaN
121648 NaN NaN NaN NaN NaN NaN
121649 NaN NaN NaN NaN NaN NaN
121650 NaN NaN NaN NaN NaN NaN
121651 NaN NaN NaN NaN NaN NaN
121652 NaN NaN NaN NaN NaN NaN
121653 NaN NaN NaN NaN NaN NaN
121654 NaN NaN NaN NaN NaN NaN
121655 NaN NaN NaN NaN NaN NaN
121656 NaN NaN NaN NaN NaN NaN
121657 NaN NaN NaN NaN NaN NaN
121658 NaN NaN NaN NaN NaN NaN
121659 NaN NaN NaN NaN NaN NaN
121660 NaN NaN NaN NaN NaN NaN
121661 NaN NaN NaN NaN NaN NaN
121662 NaN NaN NaN NaN NaN NaN
121663 NaN NaN NaN NaN NaN NaN
121664 NaN NaN NaN NaN NaN NaN
121665 NaN NaN NaN NaN NaN NaN
121666 NaN NaN NaN NaN NaN NaN
121667 NaN NaN NaN NaN NaN NaN
121668 NaN NaN NaN NaN NaN NaN
121669 NaN NaN NaN NaN NaN NaN
121670 NaN NaN NaN NaN NaN NaN
121671 NaN NaN NaN NaN NaN NaN
121672 NaN NaN NaN NaN NaN NaN
121673 NaN NaN NaN NaN NaN NaN
121674 NaN NaN NaN NaN NaN NaN
121675 NaN NaN NaN NaN NaN NaN

121676 rows × 6 columns

Battery Historian

Battery Historian是一款工具,用于检查运行Android 5.0 Lollipop(API级别21)及更高版本的Android设备上与电池相关的信息和事件,而该设备未插入。它允许应用程序开发人员在时间线上可视化系统和应用程序级事件通过平移和缩放功能,可轻松查看自设备上次充满电以来的各种汇总统计信息,并选择一个应用程序并检查影响所选应用程序特定电池的指标。它还允许两个错误报告的A / B比较,突出显示关键电池相关指标的差异。

入门

使用Docker

安装Docker

运行Battery Historian图像。选择一个端口号,并用``下面的命令替换该号码:

docker -- run -p <port>:9999 gcr.io/android-battery-historian/stable:3.0 --port 9999

对于Linux和Mac OS X:

  • 就是这样,你完成了!历史学家将在 http://localhost:

对于Windows:

  • 您可能必须在BIOS中启用虚拟化

  • 一旦你启动Docker,它应该告诉你它正在使用的机器的IP地址。例如,如果IP地址是123.456.78.90,Historian将在http://123.456.78.90:

有关端口转发的更多信息,请参阅Docker文档

从源代码构建

确保你至少有Golang版本1.8.1:

  • 按照http://golang.org/doc/install上的说明下载和安装Go编译器,工具和库。
  • 根据http://golang.org/doc/code.html#Organization中的说明创建一个工作空间目录 。
  • 确保GOPATHGOBIN环境变量的设置适当并且添加到您的$PATH 环境变量。$GOBIN should be set to $GOPATH/bin
    • 对于Windows,您可以通过“系统”控制面板的“高级”选项卡上的“环境变量”按钮来设置环境变量。某些版本的Windows通过“系统”控制面板中的“高级系统设置”选项提供此控制面板。

    • 对于Linux和Mac OS X,可以将以下行添加到〜/ .bashrc或〜/ .profile文件(假设您的工作区是$ HOME / work):

      export GOPATH=$HOME/work
      export GOBIN=$GOPATH/bin
      export PATH=$PATH:$GOBIN
      
      

接下来,如果尚未安装,请从https://git-scm.com/downloads安装Git 。

接下来,确保安装了Python 2.7(不是Python 3!)。 如果不是,请查看https://python.org/downloads,并确保python被添加到你的$PATH环境变量中。

接下来,从http://www.oracle.com/technetwork/java/javase/downloads/index.html安装Java 。

接下来,下载Battery Historian代码及其依赖项:

$ go get -d -u github.com/google/battery-historian/...

最后,运行Battery Historian!

$ cd $GOPATH/src/github.com/google/battery-historian

# Compile Javascript files using the Closure compiler
$ go run setup.go

# Run Historian on your machine (make sure $PATH contains $GOBIN)
$ go run cmd/battery-historian/battery-historian.go [--port <default:9999>]

请记住,您必须始终从$GOPATH/src/github.com/google/battery-historian目录中运行电池历史记录:

cd $GOPATH/src/github.com/google/battery-historian
go run cmd/battery-historian/battery-historian.go [--port <default:9999>]

如何采取错误报告

要从Android设备上获取错误报告,您需要启用USB下的调试Settings > System > Developer Options。在Android 4.2及更高版本中,开发者选项屏幕默认为隐藏。您可以按照此处的说明启用此功能。

要从运行Android 7.0和更高版本的开发设备获取错误报告:

$ adb bugreport bugreport.zip

对于6.0及更低版本的设备:

$ adb bugreport > bugreport.txt

开始分析!

你现在都准备好了 运行historian并访问http:// localhost:9999并上传bugreport.txt文件以开始分析。

截图

时间线:

系统统计:

应用统计信息:

高级

重置聚合电池统计信息和历史记录:

adb shell dumpsys batterystats --reset

Wakelock分析

默认情况下,即使在运行的基础上维护汇总统计信息,Android也不会为特定于应用程序的用户空间wakelock转换记录时间戳。如果您希望Historian在时间线上显示每个单独的唤醒锁的详细信息,则应在开始实验之前使用以下命令启用完整的唤醒锁报告:

adb shell dumpsys batterystats --enable full-wake-history

请注意,通过启用完全唤醒锁定报告,电池历史记录将在几个小时内溢出。短期试运行(3-4小时)使用此选项。

内核跟踪分析

生成一个记录内核唤醒源和内核唤醒锁活动的跟踪文件:

首先,将设备连接到台式机/笔记本电脑并启用内核跟踪日志记录:

$ adb root
$ adb shell

# Set the events to trace.
$ echo "power:wakeup_source_activate" >> /d/tracing/set_event
$ echo "power:wakeup_source_deactivate" >> /d/tracing/set_event

# The default trace size for most devices is 1MB, which is relatively low and might cause the logs to overflow.
# 8MB to 10MB should be a decent size for 5-6 hours of logging.

$ echo 8192 > /d/tracing/buffer_size_kb

$ echo 1 > /d/tracing/tracing_on

然后,将该设备用于预期的测试用例。

最后,提取日志:

$ echo 0 > /d/tracing/tracing_on
$ adb pull /d/tracing/trace <some path>

# Take a bug report at this time.
$ adb bugreport > bugreport.txt

注意:

历史学家绘制并实时关联事件(PST或UTC),而内核跟踪文件以jiffies(自引导时间以来的秒)记录事件。为了把这些事件联系起来,有一个脚本可以用来近似jiffies。当系统挂起并恢复时,脚本读取dmesg中记录的UTC时间。脚本的范围仅限于dmesg中存在的时间戳的数量。由于脚本在系统挂起时使用dmesg日志,因此每个设备都有不同的脚本,唯一的区别是它试图找到的设备特定的dmesg日志。这些脚本已经集成到Battery Historian工具本身中。

电力监测分析

电源监视器文件中的行应具有以下格式之一,并且格式在整个文件中应该是一致的:

<timestamp in epoch seconds, with a fractional component> <amps> <optional_volts>

要么

<timestamp in epoch milliseconds> <milliamps> <optional_millivolts>

来自电源监视器文件的条目将被覆盖在时间线图的顶部。

为确保电源监视器和错误报告时间表有所对应,请在运行任何电源监视器记录之前重置电池状态:

adb shell dumpsys batterystats --reset

停止电源监视器记录后,马上收到错误报告。

如果使用季风:

https://android.googlesource.com/platform/cts/+/master/tools/utils/monsoon.py下载AOSP季风Python脚本

# Run the script.
$ monsoon.py --serialno 2294 --hz 1 --samples 100000 -timestamp | tee monsoon.out

# ...let device run a while...

$ stop monsoon.py

修改原始文件

如果你想修改原始文件(pb / * / *。proto),首先下载需要的附加工具:

https://github.com/google/protobuf/blob/master/src/README.md安装协议缓冲区的标准C ++实现

下载Go proto编译器:

$ go get -u github.com/golang/protobuf/protoc-gen-go

编译器插件protoc-gen-go将安装在$ GOBIN中,它必须位于你的$ PATH协议编译器protoc中才能找到它。

对原始文件进行更改。

最后,使用重新生成已编译的Go原型输出文件regen_proto.sh

其他命令行工具
# System stats
$ go run cmd/checkin-parse/local_checkin_parse.go --input=bugreport.txt

# Timeline analysis
$ go run cmd/history-parse/local_history_parse.go --summary=totalTime --input=bugreport.txt

# Diff two bug reports
$ go run cmd/checkin-delta/local_checkin_delta.go --input=bugreport_1.txt,bugreport_2.txt

支持

如果您在此项目中发现错误,请提交问题:https//github.com/google/battery-historian/issues

执照

版权所有2016 Google,Inc.

根据Apache许可证2.0版(“许可证”)获得许可; 除遵守许可证外,不得使用此文件。您可以在获得许可证副本

http://www.apache.org/licenses/LICENSE-2.0

除非适用法律要求或书面同意,否则根据许可证分发的软件按“原样”分发,不附有任何明示或暗示的保证或条件。请参阅许可证以获取有关许可证下的权限和限制的特定语言。

Android 开发中的日常积累 有更新!

Android 开发中的日常积累

Android 性能优化

Android 加固与反编译

Android Studio专题

Android 开发中值得看的优秀内容和工具

Android 开源软件

Android 开发辅助工具

Android 推送(含IM)

Android后端等服务

Android 应用内测平台

Android社会化分享,短信验证,意见反馈,支付等相关

安卓网络层(包含图片)

安卓orm框架,用得比较多的就GreenDao,Ormlite

安卓Json解析

Android插件化开发与动态加载

Android 热更新

### Material Design专题
- MaterialShadows 图标阴影虚化

RecyclerView优秀库

安卓开发值得关注的库

iOS 值得关注的库

-iOS图像识别

Gradle插件相关

Kotlin专题

安卓资源相关

git

Android NoSql

设计网站,可以寻找一些酷炫的设计稿

国外个人博客

国外的一些优秀网站

Ibeacon与蓝牙4.0相关

WEB相关

Android 进程保活

前端相关

其他

ReactNative 专题

更新日志

  • 2017/6/30 android 获取帧率fps
  • 2017/6/26 添加iOS图像识别库 ,android 防截屏思路
  • 2017/6/23 添加Collect.js 库
  • 2017/6/19 添加node.js版的htp-server 一行代码实现文件服务器
  • 2017/6/12 添加Android引导页(AppIntro),View提示View (ViewTooltip)
  • 2017/6/6 添加Android WebView框架,遮罩式的导航页
  • 2017/6/5 添加Android Hook框架(Legend)

License

Copyright 2016 AllenCoder

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Mac下Android studio 之NDK配置教程(二)

#Mac下Android studio 之NDK配置教程(二)
##(一)简述

从上一篇NDK配置教程(一) 中,我 简单的阐述了MAC下NDK的基本解压和环境配置步骤。


本节我讲详细描述android studio 在MAC下的的配置运行步骤。

##(二)开始

首先,我们前往上次解压好的NDK文件路径,使用Android studio 导入Hello-jni这里写图片描述
导入完成后,AS会自动帮我们构建为grade版本。
等待完成,版本构建完成。

打开文件目录如图所示
这里写图片描述

我们在local.properties文件下添加一句话为:

ndk.dir=/Applications/Android-NDK/android-ndk-r10e

这个根据你自己的设置,改为你的ndk路径。

点击编译,如果没有出现运行错误,说明配置完成。

点击运行,手机上正常Hello-jni字样。说明配置成功。


提示注意:
1. 运行NDK的测试程序,不建议使用genymotion ,因为内核版本 问题,ndk程序会出现无法运行。
2. 尽量使用真机调试ndk程序。
3.可使用运行模拟器开启intel加速效果也可以。

Mac下Android studio 之NDK配置教程(一)

#Mac下Android studio 之NDK配置教程(一)

##1.概述

     最近项目全线转移到Mac下使用使用Android studio开发。遇到关键代码封装到 ***native***层,此时在win下的NDK配置步骤全部失效。
    为此,花费了大量时间用来查阅资料,在此,记录下来,分享给大家供以后配置中作为参考。

##2.环境

本人使用的开发配置 是:MAC OS 10.10 +androioid studio 1.2+android-ndk-r10e-darwin-x86_64+git 。其他配置类似操作即可。

##3.操作流程
1.MAC 下打开终端 获取NDK目录的权限

chmod a+x android-ndk-r10c-darwin-x86_64.bin
后面为文件存放路径 。


2.cd 路径。
cd 路径。
如果不知道文件的具体路径,可以直接拖拽到命令终端窗口下即可。


3.继续执行解压命令
./android-ndk-r10c-darwin-x86_64.bin


此时在文件存放路径会得到一个解压完成后的NDK存放目录。
效果如下图:

这里写图片描述

得到下图说明:解压文件成功。

此时:打开:命令终端:
这里写图片描述
请按如下步骤操作:

1.输入命令 pico .bash_profile
2. export NDK_ROOT=/Applications/Android-NDK/android-ndk-r10e
3. export PATH=$PATH:$NDK_ROOT
最后保存( control+X) 选 Y
这里写图片描述
4.更新刚配置的环境变量输入source .bash_profile


##验证成功

1.终端下进入
NDK 下的sample 文件夹下

这里写图片描述

按如下步骤测试是否配置成功:
1.cd hello-jni/
2. 执行 ndk-build
这里写图片描述
出现如下界面表示基本变量配置成功。。

我将在教程二继续介绍怎么在Android studio中配置使用的步骤。

android canvas 绘图笔记

android canvas 绘图笔记

1.PathEffect类
画虚线

 Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
        p.setStyle(Paint.Style.STROKE);
        p.setColor(Color.WHITE);
        p.setStrokeWidth(1);
        PathEffect effect = new DashPathEffect(new float[]{getDip2px(4), getDip2px(4), getDip2px(4), getDip2px(4)}, 1);
        p.setPathEffect(effect);
        p.setAlpha(125);//透明度50%
        p.setColor(getResources().getColor(R.color.line_chart_dash_line));
        canvas.drawLine(0, ScreenHeight / 2, ScreenWidth, ScreenHeight / 2, p);
        canvas.drawLine(ScreenWidth / 2, 0, ScreenWidth / 2, getBottom() - getDip2px(25), p);

2.android onMeasure

3.android BlurMaskFilter

***Android MaskFilter的基本使用:***

MaskFilter类可以为Paint分配边缘效果。
        对MaskFilter的扩展可以对一个Paint边缘的alpha通道应用转换。Android包含了下面几种MaskFilter:

        BlurMaskFilter   指定了一个模糊的样式和半径来处理Paint的边缘。
        EmbossMaskFilter  指定了光源的方向和环境光强度来添加浮雕效果。

        要应用一个MaskFilter,可以使用setMaskFilter方法,并传递给它一个MaskFilter对象。下面的例子是对一个已经存在的Paint应用一个EmbossMaskFilter:

Android MaskFilter的基本使用:

MaskFilter类可以为Paint分配边缘效果。
    对MaskFilter的扩展可以对一个Paint边缘的alpha通道应用转换。Android包含了下面几种MaskFilter:

    BlurMaskFilter   指定了一个模糊的样式和半径来处理Paint的边缘。
    EmbossMaskFilter  指定了光源的方向和环境光强度来添加浮雕效果。

    要应用一个MaskFilter,可以使用setMaskFilter方法,并传递给它一个MaskFilter对象。下面的例子是对一个已经存在的Paint应用一个EmbossMaskFilter:

关于设置硬件加速不能用的方法

LAYER_TYPE_NONE

LAYER_TYPE_SOFTWARE

LAYER_TYPE_HARDWARE

View级别

您可以在运行时用以下的代码关闭单个view的硬件加速:

myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
注:您不能在view级别开启硬件加速
为什么需要这么多级别的控制?
很明显,硬件加速能够带来性能提升,android为什么要弄出这么多级别的控制,
而不是默认就是全部硬件加速呢?原因是并非所有的2D绘图操作支持硬件加速,
如果您的程序中使用了自定义视图或者绘图调用,程序可能会工作不正常。
如果您的程序中只是用了标准的视图和Drawable,放心大胆的开启硬件加速吧!
具体是哪些绘图操作不支持硬件加速呢?以下是已知不支持硬件加速的绘图操作:

Canvas
clipPath()
clipRegion()
drawPicture()
drawPosText()
drawTextOnPath()
drawVertices()
Paint
setLinearText()
setMaskFilter()
setRasterizer()

另外还有一些绘图操作,开启和不开启硬件加速,效果不一样:

Canvas
clipRect(): XOR, Difference和ReverseDifference裁剪模式被忽略,3D变换将不会应用在裁剪的矩形上。

drawBitmapMesh():colors数组被忽略

drawLines():反锯齿不支持

setDrawFilter():可以设置,但无效果

Paint

setDither(): 忽略
setFilterBitmap():过滤永远开启
setShadowLayer():只能用在文本上
ComposeShader
ComposeShader
只能包含不同类型的shader (比如一个BitmapShader和一个LinearGradient,但不能是两个BitmapShader实例)

ComposeShader不能包含ComposeShader

如果应用程序受到这些影响,您可以在受影响的部分调用setLayerType(View.LAYER_TYPE_SOFTWARE, null),这样在其它地方仍然可以享受硬件加速带来的好处

2.Paint(画笔)类

   要绘制图形,首先得调整画笔,按照自己的开发需要设置画笔的相关属性。Pain类的常用属性设置方法如下:

  setAntiAlias();            //设置画笔的锯齿效果

  setColor();                 //设置画笔的颜色

  setARGB();                 //设置画笔的A、R、G、B值

  setAlpha();                 //设置画笔的Alpha值

  setTextSize();             //设置字体的尺寸

  setStyle();                  //设置画笔的风格(空心或实心)

  setStrokeWidth();        //设置空心边框的宽度

  getColor();                  //获取画笔的颜色
  

 3.Canvas(画布)类

  画笔属性设置好之后,还需要将图像绘制到画布上。Canvas类可以用来实现各种图形的绘制工作,如绘制直线、矩形、圆等等。Canvas绘制常用图形的方法如下:

  绘制直线:canvas.drawLine(float startX, float startY, float stopX, float stopY, Paint paint);

  绘制矩形:canvas.drawRect(float left, float top, float right, float bottom, Paint paint);

  绘制圆形:canvas.drawCircle(float cx, float cy, float radius, Paint paint);

  绘制字符:canvas.drawText(String text, float x, float y, Paint paint);

  绘制图形:canvas.drawBirmap(Bitmap bitmap, float left, float top, Paint paint);

Shader 渐变色设置

 //设置渐变器后绘制
        //为Paint设置渐变器
        Shader mShasder = new LinearGradient(0, 0, 40, 60, new int[]{Color.RED,Color.GREEN,Color.BLUE,Color.YELLOW}, null, Shader.TileMode.REPEAT);
        mPaint.setShader(mShasder);
        //设置阴影
        mPaint.setShadowLayer(45, 10, 10, Color.GRAY);

Paint.Style区别

Paint.Style.FILL    :填充内部
Paint.Style.FILL_AND_STROKE  :填充内部和描边
Paint.Style.STROKE  :仅描边

Region 判断是否在路径范围内

“onTouchEvent 在自定义View 中”

@Override  
public boolean onTouchEvent(MotionEvent event) {  
    switch (event.getAction()) {  
    case MotionEvent.ACTION_DOWN:  
        // 按下  
        cx = (int) event.getX();  
        cy = (int) event.getY();  
        // 通知重绘  
        postInvalidate();   //该方法会调用onDraw方法,重新绘图  
        break;  
    case MotionEvent.ACTION_MOVE:  
        // 移动  
        cx = (int) event.getX();  
        cy = (int) event.getY();  
        // 通知重绘  
        postInvalidate();  
        break;  
    case MotionEvent.ACTION_UP:  
        // 抬起  
        cx = (int) event.getX();  
        cy = (int) event.getY();  
        // 通知重绘  
        postInvalidate();  
        break;  
    }  
      
    /* 
     * 备注1:此处一定要将return super.onTouchEvent(event)修改为return true,原因是: 
     * 1)父类的onTouchEvent(event)方法可能没有做任何处理,但是返回了false。 
     * 2)一旦返回false,在该方法中再也不会收到MotionEvent.ACTION_MOVE及MotionEvent.ACTION_UP事件。 
     */  
    //return super.onTouchEvent(event);  
    return true;    
}  

RectF

  • Android Rect和RectF的区别*
    1、精度不一样,Rect是使用int类型作为数值,RectF是使用float类型作为数值
    2、两个类型提供的方法也不是完全一致
    
    Rect:
    equals(Object obj)   (for some reason it as it's own implementation of equals)
    exactCenterX()
    exactCenterY()
    flattenToString()
    toShortString()
    unflattenFromString(String str)
    
    RectF:
    round(Rect dst)
    roundOut(Rect dst)
    set(Rect src)
    

Shader

//设置渐变器后绘制
        //为Paint设置渐变器
        Shader mShasder = new LinearGradient(0, 0, 40, 60, new int[]{Color.RED,Color.GREEN,Color.BLUE,Color.YELLOW}, null, Shader.TileMode.REPEAT);
        mPaint.setShader(mShasder);
        //设置阴影
        mPaint.setShadowLayer(45, 10, 10, Color.GRAY);
Paint p=new Paint();
LinearGradient lg=new LinearGradien(0,0,100,100,Color.RED,Color.BLUE,Shader.TileMode.MIRROR);  
参数一为渐变起初点坐标x位置,
参数二为y轴位置,
参数三和四分辨对应渐变终点,
最后参数为平铺方式,这里设置为镜像
Gradient是基于Shader类,所以我们通过Paint的setShader方法来设置这个渐变,代码如下: mPaint.setShader(lg);

canvas.drawCicle(0,0,200,mPaint); //参数3为画圆的半径,类型为float型。
 
 
它除了定义开始颜色和结束颜色以外还可以定义,多种颜色组成的分段渐变效果

LinearGradient shader = new LinearGradient(0, 0, endX, endY, new int[]{startColor, midleColor, endColor},new float[]{0 , 0.5f, 1.0f}, TileMode.MIRROR);

其中参数new int[]{startColor, midleColor, endColor}是参与渐变效果的颜色集合,

其中参数new float[]{0 , 0.5f, 1.0f}是定义每个颜色处于的渐变相对位置,

这个参数可以为null,如果为null表示所有的颜色按顺序均匀的分布

LinearGradient有两个构造函数;

public LinearGradient(float x0, float y0, float x1, float y1, int[] colors, float[] positions,Shader.TileMode tile)

参数:
float x0: 渐变起始点x坐标

float y0:渐变起始点y坐标

float x1:渐变结束点x坐标

float y1:渐变结束点y坐标

int[] colors:颜色 的int 数组

float[] positions: 相对位置的颜色数组,可为null,  若为null,可为null,颜色沿渐变线均匀分布

Shader.TileMode tile: 渲染器平铺模式

public LinearGradient(float x0, float y0, float x1, float y1, int color0, int color1,Shader.TileMode tile)
float x0: 渐变起始点x坐标

float y0:渐变起始点y坐标

float x1:渐变结束点x坐标

float y1:渐变结束点y坐标

int color0: 起始渐变色

int color1: 结束渐变色

Shader.TileMode tile: 渲染器平铺模式


Android 透明度渐变

android 代码截屏

 /**
     * Returns the bitmap that represents the chart.
     *
     * @return
     */
    public Bitmap getChartBitmap() {
        // Define a bitmap with the same size as the view
        Bitmap returnedBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.RGB_565);
        // Bind a canvas to it
        Canvas canvas = new Canvas(returnedBitmap);
        // Get the view's background
        Drawable bgDrawable = getBackground();
        if (bgDrawable != null)
            // has background drawable, then draw it on the canvas
            bgDrawable.draw(canvas);
        else
            // does not have background drawable, then draw white background on
            // the canvas
            canvas.drawColor(Color.WHITE);
        // draw the view on the canvas
        draw(canvas);
        // return the bitmap
        return returnedBitmap;
    }
 /**
     * Returns the bitmap that represents the chart.
     *
     * @return
     */
    public Bitmap getChartBitmap() {
        // Define a bitmap with the same size as the view
        Bitmap returnedBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.RGB_565);
        // Bind a canvas to it
        Canvas canvas = new Canvas(returnedBitmap);
        // Get the view's background
        Drawable bgDrawable = getBackground();
        if (bgDrawable != null)
            // has background drawable, then draw it on the canvas
            bgDrawable.draw(canvas);
        else
            // does not have background drawable, then draw white background on
            // the canvas
            canvas.drawColor(Color.WHITE);
        // draw the view on the canvas
        draw(canvas);
        // return the bitmap
        return returnedBitmap;
    }

对canvas的translate()方法的理解

canvas.save();//锁画布(为了保存之前的画布状态)
        canvas.translate(10, 10);//把当前画布的原点移到(10,10),后面的操作都以(10,10)作为参照点,默认原点为(0,0)
        drawScene(canvas);
        canvas.restore();//把当前画布返回(调整)到上一个save()状态之前

        canvas.save();//锁画布(为了保存之前的画布状态)
        canvas.translate(160, 10);//把当前画布的原点移到(160,10),后面的操作都以(160,10)作为参照点,
        canvas.clipRect(10, 10, 90, 90);//这里的真实坐标为左上(170,170)、右下(250,250)
        canvas.clipRect(30, 30, 70, 70, Region.Op.DIFFERENCE);
        drawScene(canvas);
        canvas.restore();

图片镜像

public Bitmap convertBmp(Bitmap bmp) {  
        int w = bmp.getWidth();  
        int h = bmp.getHeight();  
  
        Matrix matrix = new Matrix();  
        matrix.postScale(-1, 1); // 镜像水平翻转  
        Bitmap convertBmp = Bitmap.createBitmap(bmp, 0, 0, w, h, matrix, true);  
          
        return convertBmp;  
    }  

Android 防内存泄露handler

Android 防内存泄露handler

1.使用弱引用 WeakRefHander

	/**
	 * 作者: allen on 15/11/24.感谢开源作者https://coding.net/u/coding/p/Coding-Android/git
	 */
	
	/**
	 * 弱引用 handler 防止内存泄露
	 */
	public class WeakRefHander extends Handler {
	
	    private final WeakReference<Handler.Callback> mRef;
	    private final int mLoopTime;
	    private int NO_LOOP = -1;
	    private int what =0;
	
	    /**
	     * 循环
	     *
	     * @param loopAction
	     * @param loopTime
	     */
	    public WeakRefHander(Handler.Callback loopAction, int loopTime) {
	        super();
	        this.mRef = new WeakReference<>(loopAction);
	        this.mLoopTime = loopTime;
	
	    }
	
	    /**
	     * 不循环
	     *
	     * @param loopAction
	     */
	    public WeakRefHander(Handler.Callback loopAction) {
	        super();
	        mRef = new WeakReference<>(loopAction);
	        mLoopTime = NO_LOOP;
	    }
	
	    @Override
	    public void handleMessage(Message msg) {
	        Handler.Callback action = mRef.get();
	        if (action != null) {
	            action.handleMessage(msg);
	            if (mLoopTime != NO_LOOP) {
	                sendEmptyMessageDelayed(what, mLoopTime);
	            }
	        }
	    }
	
	    public void start() {
	        removeMessages(0);
	        sendEmptyMessageDelayed(0, 0);
	    }
	
	    public void start(int what, long delay) {
	        this.what = what;
	        removeMessages(what);
	        sendEmptyMessageDelayed(what, delay);
	    }
	
	    public void stop() {
	        removeMessages(what);
	    }
	
	    public void clear() {
	        removeMessages(what);
	        mRef.clear();
		    }
		}

2. 实现 Activity implements WeakRefHander.Callback

3. 在handleMessage处理业务逻辑

示例代码:

    public class MainActivity extends AppCompatActivity implements WeakRefHander.Callback {
        private WeakRefHander weakRefHander;
        private static final int HANDLER_MESSAGE_START = 1001;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            weakRefHander = new WeakRefHander(this, 1);
            weakRefHander.start(HANDLER_MESSAGE_START, 1000 * 30);
    }

    @Override
    public boolean handleMessage(Message msg) {
        switch (msg.what) {
            case HANDLER_MESSAGE_START:
                //Todo 处理业务逻辑
                break;
            default:
                break;
        }
        return true;
    }


    @Override
    public void onResume() {
        super.onResume();
        weakRefHander.start();
    }

    @Override
    public void onPause() {
        weakRefHander.stop();
        super.onPause();
    }

    @Override
    protected void onDestroy() {
        weakRefHander.clear();
        super.onDestroy();
    }
    }

-Github示例参考代码

参考作者:-Coding-Android作者

AndroidCustomView(投票 ,排名对比图)

Android Arsenal

##Github 地址前往

简介(投票 ,排名对比图)


  1. 一个简单的自定义 View 可高度定制
  2. 支持设置替换 支持 ,和反对的图标
  3. 支持自定义线宽和支持反对线的字体颜色

设置比分值

效果图

Dependency

Add dependency in your app module

dependencies {
	compile 'com.allen.comparsechart:comparsechart:1.0.0'
}

Maven

<dependency>
  <groupId>com.allen.comparsechart</groupId>
  <artifactId>comparsechart</artifactId>
  <version>1.0.0</version>
  <type>pom</type>
</dependency>

Usage

Java

    <com.allen.comparsechart.CompareIndicator
            android:id="@+id/CompareIndicator3"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="50dp"
            app:approve_line_color="@android:color/holo_green_light"
            app:approve_res="@mipmap/approve"
            app:oppose_line_color="@android:color/holo_red_dark"
            app:opposite_res="@mipmap/opposite"
            />
CompareIndicator1.updateView(10,90);

股票走势图

Apk 下载地址

License

Copyright 2016 AllenCoder

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.