tar 本质上只是一个打包命令,可以将多个文件或者文件夹打包到一个 tar 文件中,结合其他的压缩程序再将打包后的档案文件压缩。所以看到 .tar.gz
, .tar.bz2
, .tar.xz
等等文件其实是 tar 文件之后进行 Gzip, Bzip2, XZ 压缩之后的文件。
tar [-] A --catenate --concatenate | c --create | d --diff --compare |
--delete | r --append | t --list | --test-label | u --update | x
--extract --get [options] [pathname ...]
tar 命令常用参数
-c 创建 archive
-x 解压文件
-f ARCHIVE 使用该 ARCHIVE
-v 输出 verbose 日志
-t 测试压缩文件内容
-z, --gzip, --gunzip, gzip 格式
-j 支持 bzip2 格式
常见的压缩和解压用法
tar -cvf filename.tar /folder # 仅打包不压缩
tar -xvf filename.tar # 解压包
压缩与解压 gzip:
tar -zcvf filename.tar.gz /folder # gzip 压缩
tar -zxvf filename.tar.gz # 当前目录下解压文件
压缩解压 bzip2 / bz2
tar -jcvf filename.tar.bz2 /folder # bzip2 压缩
tar -jxvf filename.tar.bz2 -C /path # 解压
压缩解压 tar.xz
tar -Jcvf filename.tar.xz /folder # xz 压缩
tar -Jxvf filename.tar.xz # 解压
解释
-c
表示创建-x
表示解压-t
表示查看压缩包内容
注意 c/x/t 三个参数不能同时使用
-v
表示打印出日志-j
表示 bzip2 压缩方法-J
表示 xz 压缩方法-z
表示 gzip 压缩方法-f ARCHIVE
后面接文件,-f
后面需要直接接压缩包名经过上面的解释,可以习惯上可以记忆成 压缩格式 (z/j/J) + 压缩 / 解压 / 查看 (c/x/t) + v + f 文件名
有的时候在打包文件的时候会跟随着很长的路径,如果不想要这个很长的路径可以使用 -C
参数来将目录 change to directory
比如想要备份 Docker volume 目录 /var/lib/docker/volumes/chevereto_chevereto_content/
,如果:
tar -zcvf backup_content.tar.gz /var/lib/docker/volumes/chevereto_chevereto_content/
这样打包,最后的压缩包内容会将整个相对目录也打包进去,可以使用
tar -zcvf backup_content.tar.gz -C /var/lib/docker/volumes/chevereto_chevereto_content/ .
然后打包的结果 tar 中就只有 chevereto_chevereto_content
目录下的内容。
比如说在使用 -C
来解压目录的时候,在压缩包内所有的文件内容都在 path-1.4
这样的带版本的文件夹内,如果要想要解压到 path
这样的目录,可以使用:
tar xzvf path-1.4.tar.gz -C path --strip-components=1
注意 path
目录需要存在,否则会报错。
tar -ztvf filename.tar.gz # 列出 tar.gz 下文件
tar -zxvf filename.tar.gz folder/filename # 仅仅解压某个文件
tar -zcvpf fileetc.tar.gz /etc # 将 /etc/ 内所有文件备份,并保存其权限 -p
tar -zcvpf file.tar.gz /etc
这里多了一个 -p
参数,保留原始属性时使用,比如打包时不想改变文件的权限等等。
比如说在打包 /etc
和 /home
目录到 file.tar.gz 文件中时排除 /path
目录
tar --exclude /path -zcvf file.tar.gz /etc /home
这里注意 --exclude
参数
使用 -N
参数来打包更新的文件
tar -N "2016/01/01" -zcvf download.tar.gz /home/einverne/Download
比如只打包指定目录下文件日期新于 20160101 的文件。
使用 -C
参数来指定解压到的目录
tar -zxvf filename.tar.gz -C /path/to/
使用 -C
参数将压缩包内容解压到目录 /path/to/filename
tar -tf archive.tar.gz
上面提到的命令都需要将压缩文件存储到本地,那么如果有一种情况,本地空间有限,无法容纳压缩包的内容,想要实时通过压缩,然后传输到另一台机器,可以使用:1
tar czvf - /source | ssh username@remote.host "cd /destination; tar xzvf -"
比如要在 A 机器将目录 /www/backup
备份到 B 机器的 /home/einverne/Backup
目录,并压缩:
tar zcvf - /www/backup/ | ssh your_username@ip_of_hostname "cat > /home/einverne/Backup/aapanel.tgz"
Gzip, Bzip2 和 XZ 是 UNIX 系统下常见的压缩工具。 xz 是一个使用 LZMA 压缩算法的无损数据压缩文件格式,xz 文件格式的压缩率更高。
这里 有篇文章对比了三个工具的压缩率,压缩时间等等
如果不使用上面提及的一步压缩和解压方式,可以拆看先解压,再拆包
xz -d file.tar.xz
tar -xvf file.tar
创建同理
tar -cvf file.tar /file
xz -z file.tar
Android Support v4 包中的 NotificationCompat.Builder ,在 Android 3.0 API Level 11 中才有 Notification.Builder。
您可以在 NotificationCompat.Builder 对象中为通知指定 UI 信息和操作。要创建通知,请调用 NotificationCompat.Builder.build(),它将返回包含您的具体规范的 Notification 对象。要发出通知,请通过调用 NotificationManager.notify() 将 Notification 对象传递给系统。
必需的通知内容
Notification 对象必须包含以下内容:
setContentIntent() 设置用户点击通知之后的动作。
NotificationCompat.Builder 在构造时自动设置时间为 System.currentTimeMillis() ,设置 Audio stream 为 STREAM_DEFAULT
。
NotificationCompat.Builder 中可选的其他参数有
NotificationCompat.Builder 不必多说,其他重要的类有 NotificationCompat.Action
通知动作需要包含一个图标,一个标签,一个 PendingIntent 。通知动作在 Android 4.1 之前不会显示。
如果要在通知栏显示复杂View,需要设定 RemoteView,使用 setContent(RemoteViews views)
方法
NotificationCompat.Style
用来展现更丰富的通知内容的样式,直接子类有
BigPictureStyle 可以显示大图,如果通知附带一张大图片,可以使用该样式。通常 Android 截屏之后显示的通知就是。
Notification notif = new Notification.Builder(mContext)
.setContentTitle("New photo from " + sender.toString())
.setContentText(subject)
.setSmallIcon(R.drawable.new_post)
.setLargeIcon(aBitmap)
.setStyle(new Notification.BigPictureStyle()
.bigPicture(aBigBitmap))
.build();
InboxStyle 可以产生多行文本的通知,至多可以显示5个字符串。
Notification noti = new Notification.Builder()
.setContentTitle("5 New mails from " + sender.toString())
.setContentText(subject)
.setSmallIcon(R.drawable.new_mail)
.setLargeIcon(aBitmap)
.setStyle(new Notification.InboxStyle()
.addLine(str1)
.addLine(str2)
.setContentTitle("")
.setSummaryText("+3 more"))
.build();
还有可以显示很多文字的 BigTextStyle,和比较复杂的 MediaStyle。
Android UI monkey 测试
伪随机用户事件,发送到模拟器或者设备,用来对应用程序进行压力测试。
功能:
报错:
基本语法:
adb shell monkey [options] <event-count>
下面的例子是测试在特定包上,发送500随机事件
adb shell monkey -p your.package.name -v 500
一些有用的选项:
Option | 描述 |
---|---|
-v -vv -vvv | 三档等级,越来越详细 |
--throttle |
事件和事件之间延迟 |
--pct-touch |
点击事件,单个点按下抬起,后接百分比 |
--pct-motion |
滑动事件,某一点按下,随机移动距离,抬起 |
--pct-trackball |
模拟轨迹球,包含随机的移动,可能伴随着点击 |
--pct-nav |
外部输入,上下左右操作(没有使用过,但似乎游戏可用) |
--pct-syskeys |
调整系统事件,包括Home,back ,音量键等等 |
-p |
允许的 package name |
-c |
指定允许monkey跑的 category,下面有例子 |
--ignore-crashes | 通常monkey 遇到crash 会停止,此选项忽略crash 直到指定次数跑完 |
--ignore-timeouts | 忽略 ANR |
--ignore-security-exceptions | 忽略Permission error 或者其他 unhandled exception |
Manifest
文件中定义 category:
<activity android:name="MonkeyActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.MONKEY" />
</intent-filter>
</activity>
使用命令:
adb shell monkey -p my.package -c android.intent.category.MONKEY -v 500
在 Android 5.0 Lollipop 及以上系统中可以使用 screen pinning.
此时再运行则不会跳出应用。
使用以下命令停止 monkey Test :
adb shell ps | awk '/com\.android\.commands\.monkey/ { system("adb shell kill " $2) }'
features 功能:
monkeyrunner 使用 Jython
dpkg-reconfigure
命令是 Debian 系 Linux 中用来重新配置软件包的命令,运行该命令可以重新配置软件包第一次安装后的配置问题。
sudo dpkg-reconfigure [package name]
常用的配置,比如配置语言
sudo dpkg-reconfigure locales
配置 display manager
sudo dpkg-reconfigure lightdm
sudo dpkg-reconfigure mdm
配置时区
sudo dpkg-reconfigure tzdata
记录一下纠结了两天的问题。
项目中遇到如下错误:
Error:Execution failed for task ':mobile:packageAllDebugClassesForMultiDex'.
> java.util.zip.ZipException: duplicate entry:android/support/annotation/AnyRes.class
这个问题是因为项目中引入了 support-annotations
包,但是导入的其他 jar 包中包含了这个 package,重复导致了 duplicate entry
错误。
在 app 的 build.gradle
中加入:
android{
...
configurations {
all*.exclude group: 'com.android.support', module: 'support-annotations'
}
}
项目中尽量只导入一个库,在引用其他库时注意查看该库的依赖版本,在导入 support v4 包或者其他 v7 包时尽量考虑只在主项目中导入一次,在任何 library 中减少使用。
这个问题的由来,应该也是项目历史原因,在我接手时,项目 build.gradle
中 buildTypes 是这样的:
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt'
}
debug {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt'
}
}
这里竟然 debug 和 release 使用了同样的 minifyEnabled 配置,默认情况下 minifyEnabled 应该是 false,设置成 true 之后,debug 下无法调试,无法设置断点。查看 git 历史这个问题竟然从项目初始就这样,真无法想象他们是怎么调试的。然后将 minifyEnabled 设置成 false 之后就产生了 multiDex 错误,然后是上面的错误。
buildTypes 下 minifyEnabled
选项, 设置为 true 情况下, debug 无法设置断点及调试 1, 但是这个选线在 release 下非常有用,可以减少包的大小,缩减无用代码(shrink unless codes)。
修改后的配置:
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt'
}
debug {
minifyEnabled false
debuggable true
}
}
multiDex 的错误倒是还好解决 2,设置:
android {
compileSdkVersion 22
buildToolsVersion "23.0.0"
defaultConfig {
minSdkVersion 14 //lower than 14 doesn't support multidex
targetSdkVersion 22
// Enabling multidex support.
multiDexEnabled true
}
}
dependencies {
compile 'com.android.support:multidex:1.0.1'
}
然后在 Application 类中设置:
public class YouApplication extends Application {
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
}
}
正是这个错误促使我看了 Gradle 中依赖的语法,总结如下:
Gradle 项目可能依赖其他组件,包括外部的二进制文件,或者另一个 Gradle 项目。
下面代码可以添加本地 libs
目录下所有 jar 包:
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
}
android {
...
}
如果想要配置本地 jar 包,可以依照下面顺序:
compile files('libs/xxx.jar')
在 build.gradle
文件中,或者 compile fileTree(dir: 'libs', include: '*.jar')
Gradle 支持从远端 Maven 或者 Ivy repositories 自动拉取依赖。首先远端 repository 需要加入列表,其次需要定义具体依赖。
repositories {
jcenter()
}
dependencies {
compile 'com.google.guava:guava:18.0'
}
android {
...
}
Note:
jcenter()
是远端库的 URL 缩写, Gradle 支持本地和远程库。通常用子目录来配置 libraries ,例如
MyProject/
+ app/
+ libraries/
+ lib1/
+ lib2/
三个项目, Gradle 通过如下指定:
:app
:libraries:lib1
:libraries:lib2
每一个项目都有自己的 build.gradle
文件,另外在跟目录下有 settings.gradle
来描述工程:
MyProject/
| settings.gradle
+ app/
| build.gradle
+ libraries/
+ lib1/
| build.gradle
+ lib2/
| build.gradle
settings.gradle
中的描述:
include ':app', ':libraries:lib1', ':libraries:lib2'
然后在 :app
项目中定义,依赖 library :
dependencies {
compile project(':libraries:lib1')
}
可以使用如下的语法排除 v4 包:
compile ('com.android.support:recyclerview-v7:+') {
exclude module: 'support-v4'
}
同样也可以在:
android{
configurations {
'com.android.support', module: 'support-v4'
}
}
下排除。
更加系统的学习 Android Gradle build system 可以参考官方文档,或者中文译本 3。
关于 build.gradle
文件中的字段属性,可以参考 Android Plugin DSL Reference.
http://stackoverflow.com/questions/31926189/android-debugging-with-minifyenabled-true ↩
StackOverflow 和 官网 ↩
adb 相关的命令在 这篇 文章中已经提及。这里主要展开
adb shell dumpsys
这个子命令。
今天在查当前运行的 Activity 时遇见这个命令。
adb shell dumpsys
,默认打印出当前系统所有 service 信息
adb shell dumpsys display |grep DisplayDevice
adb shell dumpsys power
adb shell dumpsys battery
Current Battery Service state:
AC powered: false
USB powered: true
Wireless powered: false
Max charging current: 500000
status: 5
health: 2
present: true
level: 100
scale: 100
voltage: 4276
temperature: 305
technology: Li-ion
adb shell dumpsys cpuinfo
Load: 5.76 / 6.18 / 6.54
CPU usage from 591395ms to 291331ms ago with 99% awake:
6.9% 497/surfaceflinger: 3.2% user + 3.6% kernel
6.5% 2688/com.google.android.googlequicksearchbox:search: 4.1% user + 2.4% kernel
5.8% 4740/com.qiyi.video: 2.9% user + 2.8% kernel / faults: 529 minor
3.9% 11113/com.qiyi.video:downloader: 2% user + 1.9% kernel / faults: 270 minor
2.9% 1441/system_server: 1.9% user + 1% kernel / faults: 25775 minor 1 major
1.5% 1883/com.android.systemui: 1.3% user + 0.2% kernel / faults: 3487 minor
1% 28574/kworker/u8:7: 0% user + 1% kernel
0.9% 2836/kworker/u8:2: 0% user + 0.9% kernel
0.8% 1862/android.process.media: 0.4% user + 0.3% kernel / faults: 12370 minor 1 major
0.5% 3330/com.android.vending: 0.3% user + 0.2% kernel / faults: 1483 minor
0.5% 21190/kworker/u8:3: 0% user + 0.5% kernel
0.4% 58/irq/169-cpr3: 0% user + 0.4% kernel
0.4% 30021/kworker/u8:8: 0% user + 0.4% kernel
0.4% 14747/com.microsoft.office.outlook: 0.3% user + 0.1% kernel / faults: 9563 minor
0.4% 733/adbd: 0% user + 0.3% kernel / faults: 7954 minor
0.4% 3/ksoftirqd/0: 0% user + 0.4% kernel
0.3% 26596/org.thunderdog.challegram: 0.2% user + 0.1% kernel / faults: 160 minor
0.3% 53/smem_native_rpm: 0% user + 0.3% kernel
0.3% 15/ksoftirqd/1: 0% user + 0.3% kernel
0.3% 1849/VosMCThread: 0% user + 0.3% kernel
0.3% 2785/com.google.android.gms.persistent: 0.2% user + 0% kernel / faults: 1635 minor 2 major
0.2% 336/cfinteractive: 0% user + 0.2% kernel
0.1% 4090/com.hjwordgames:pushservice: 0.1% user + 0% kernel / faults: 1551 minor
0.2% 2135/com.fanli.android.apps: 0.1% user + 0% kernel / faults: 5490 minor
0.1% 13655/.DaemonService: 0.1% user + 0% kernel
0.1% 25689/com.douban.frodo: 0.1% user + 0% kernel / faults: 276 minor
0.1% 17113/com.lastpass.lpandroid: 0.1% user + 0% kernel / faults: 13 minor
0.1% 3021/com.smzdm.client.android: 0.1% user + 0% kernel / faults: 619 minor
0.1% 31410/kworker/0:4: 0% user + 0.1% kernel
0.1% 5053/kworker/0:0: 0% user + 0.1% kernel
0.1% 7/rcu_preempt: 0% user + 0.1% kernel
0.1% 31308/kworker/1:1: 0% user + 0.1% kernel
0.1% 3496/com.smzdm.client.android:QALSERVICE: 0% user + 0% kernel / faults: 1021 minor
0.1% 2320/com.android.phone: 0% user + 0% kernel / faults: 90 minor
0.1% 2162/com.catchingnow.icebox:Service: 0.1% user + 0% kernel / faults: 662 minor
0.1% 10/rcuop/0: 0% user + 0.1% kernel
0.1% 493/healthd: 0% user + 0.1% kernel
0.1% 13190/kworker/0:2: 0% user + 0.1% kernel
0% 4075/com.smzdm.client.android:core: 0% user + 0% kernel / faults: 732 minor 1 major
0% 941/ipacm: 0% user + 0% kernel
0% 13475/com.tencent.mm: 0% user + 0% kernel / faults: 58 minor
0% 25826/com.douban.frodo:pushservice: 0% user + 0% kernel
0% 16098/com.hjwordgames: 0% user + 0% kernel / faults: 822 minor 2 major
0% 30029/com.netease.cloudmusic: 0% user + 0% kernel / faults: 604 minor
0% 444/logd: 0% user + 0% kernel / faults: 1 minor
0% 2668/com.smzdm.client.android:channel: 0% user + 0% kernel / faults: 496 minor
0% 739/netd: 0% user + 0% kernel / faults: 578 minor
0% 2039/com.catchingnow.icebox: 0% user + 0% kernel / faults: 51 minor
0% 753/thermal-engine: 0% user + 0% kernel
0% 3616/com.fanli.android.apps:xg_service_v3: 0% user + 0% kernel / faults: 349 minor
0% 495/lmkd: 0% user + 0% kernel
0% 730/jbd2/dm-0-8: 0% user + 0% kernel
0% 742/rild: 0% user + 0% kernel
0% 6131/com.tencent.mm:push: 0% user + 0% kernel / faults: 75 minor
0% 9407/cn.wiz.note: 0% user + 0% kernel / faults: 64 minor
0% 22/ksoftirqd/2: 0% user + 0% kernel
0% 1856/sdcard: 0% user + 0% kernel
0% 25/rcuop/2: 0% user + 0% kernel
0% 496/servicemanager: 0% user + 0% kernel
0% 1381/kworker/1:3: 0% user + 0% kernel
0% 2141/com.oneplus.camera: 0% user + 0% kernel
0% 765/cnss-daemon: 0% user + 0% kernel
0% 32524/kworker/2:2: 0% user + 0% kernel
0% 5673/com.netease.cloudmusic:play: 0% user + 0% kernel / faults: 196 minor
0% 6991/com.jingdong.app.reader: 0% user + 0% kernel / faults: 567 minor
0% 18/rcuop/1: 0% user + 0% kernel
0% 587/sensors.qcom: 0% user + 0% kernel / faults: 62 minor
0% 2291/com.oneplus.camera:picture: 0% user + 0% kernel
0% 2300/com.oneplus.gallery: 0% user + 0% kernel
0% 1096/xposed_service_app: 0% user + 0% kernel
0% 4964/irq/21-408000.q: 0% user + 0% kernel
0% 5109/kworker/3:1: 0% user + 0% kernel
0% 436/kworker/0:1H: 0% user + 0% kernel
0% 1848/wlan_logging_th: 0% user + 0% kernel
0% 10572/cn.wiz.note:channel: 0% user + 0% kernel / faults: 502 minor
0% 32/rcuop/3: 0% user + 0% kernel
0% 187/hwrng: 0% user + 0% kernel
0% 735/file-storage: 0% user + 0% kernel
0% 2333/com.android.launcher3: 0% user + 0% kernel / faults: 8 minor
0% 4982/perfd: 0% user + 0% kernel
0% 8/rcu_sched: 0% user + 0% kernel
0% 29/ksoftirqd/3: 0% user + 0% kernel
0% 143/kswapd0: 0% user + 0% kernel
0% 428/ueventd: 0% user + 0% kernel
0% 5734/com.duokan.reader:pushservice: 0% user + 0% kernel / faults: 3 minor
0% 26019/com.instagram.android:mqtt: 0% user + 0% kernel / faults: 112 minor
0% 11/rcuos/0: 0% user + 0% kernel
0% 760/zygote64: 0% user + 0% kernel / faults: 1215 minor
0% 2272/com.quicinc.cne.CNEService: 0% user + 0% kernel / faults: 6 minor
0% 3381/com.google.android.gms: 0% user + 0% kernel / faults: 393 minor
0% 29600/kworker/3:2: 0% user + 0% kernel
0% 451/vold: 0% user + 0% kernel
0% 745/installd: 0% user + 0% kernel
0% 2103/wpa_supplicant: 0% user + 0% kernel
0% 2277/com.android.nfc: 0% user + 0% kernel
0% 7631/com.instagram.android: 0% user + 0% kernel / faults: 3 minor
0% 26/rcuos/2: 0% user + 0% kernel
0% 44/msm_watchdog: 0% user + 0% kernel
0% 494/dashd: 0% user + 0% kernel
0% 750/cnd: 0% user + 0% kernel
0% 2682/com.fanli.android.apps:channel: 0% user + 0% kernel
0% 25022/kworker/2:0H: 0% user + 0% kernel
0% 29503/kworker/1:0: 0% user + 0% kernel
+0% 5626/kworker/2:1: 0% user + 0% kernel
+0% 5854/kworker/3:0: 0% user + 0% kernel
+0% 5886/kworker/1:4: 0% user + 0% kernel
+0% 5981/kworker/0:1: 0% user + 0% kernel
+0% 6096/com.ideashower.readitlater.pro: 0% user + 0% kernel
11% TOTAL: 5.2% user + 4.3% kernel + 0% iowait + 1.3% irq + 0.3% softirq
adb shell dumpsys meminfo
# 指定应用内存
adb shell dumpsys meminfo package_name
adb shell dumpsys activity
adb shell dumpsys activity -h
adb shell dumpsys package
adb shell dumpsys package -h
adb shell dumpsys package pacakge_name
adb shell dumpsys notification
adb shell dumpsys wifi
adb shell dumpsys telephony.registry
输出
一些常用的 adb 命令,包括 Android 录屏,及从电脑复制文件,从 Android 设备拉取文件等等。
adb 的全称是 Android Debug Bridge, 这个命令可以用来发送一系列指令给 Android 设备,包括但不限于基本的 Linux 指令。只要手机或者任何 Android 设备开启了 Debug 模式并且取得信任,adb 命令几乎可以用来做任何事情。因此网络上也存在使用 adb 来入侵同一局域网下的 Android 盒子的例子。
adb 使用的默认端口是 5037.
Ubuntu 系下安装
sudo apt-get install android-tools-adb
sudo apt-get install android-tools-fastboot
来查看设备是否已经连接
$ adb devices
List of devices attached
2dd11c6e device
获取设备状态
adb get-state
返回的结果可能有三种
在连接异常时,而已杀死服务重启尝试
adb kill-server
adb start-server
adb logcat
将文件复制到 Android 设备上:
adb push filename.txt /sdcard/Download/
将文件从 Android 设备上拉回本地
adb pull /sdcard/Download/filename.txt ~/filename.txt
adb pull
命令不知道为什么用 *.apk
这样的正则无法使用,所以只能先过滤出来特定的文件后缀,然后再使用 adb pull
比如说要把 /sdcard/Download
文件夹中的 *.apk
文件都拉取到本地,那么可以:
adb shell ls /sdcard/Download/\*.apk | tr '\r' ' ' | xargs -n1 adb pull
如果想要了解更多 xargs
命令的使用,可以参考这一篇文章。
adb shell
然后进入之后输入 su
查看手机是否会弹出 root 授权窗口。
重启设备,在刷机时经常使用
使用
adb reboot bootloader
重启进去 bootloader
或者使用 adb reboot recovery
直接进入 recovery 模式
将宿主机上某端口重定向到设备端口
adb forward tcp:8008 tcp:8008
执行命令后所有发往宿主机 8008 端口的数据都会被转发到 Android 设备 8008 上。
直接使用该命令可以进入手机的 Shell。 adb 其他命令是 adb 自带的命令,而 adb shell
则是调用的 Android 设备上的命令。Android 设备的命令放在 /system/bin
目录下。
比如 adb shell which ls
返回的结果会告诉你找到的是 /system/bin/ls
这个命令。
进入 Android Shell 之后就可以使用任何 Linux 命令来直接操作 Android 设备, 比如:
adb shell chmod 666 /data/filename.txt
shell 中可以直接截取设备的屏幕
adb shell screencap -p /sdcard/screen.png
adb pull /sdcard/screen.png
adb shell rm /sdcard/screen.png
使用 screencap
截图保存到 sdcard 上,使用 pull
命令拉到本地并删除 sd 卡中文件。这种方式比较繁杂,需要三个步骤,如果查看 screencap -h
会发现,帮助中有一行,如果不加文件名,命令会将结果输出到标准输出。那么
adb shell screencap -p > screen.png
adb shell screencap -p | sed 's/\r$//' > screen.png
直接将结果输出到本地,之所以使用 sed
是因为需要将多余的 \r
删除。adb shell
在执行时会将 \n
转换为 \r\n
。
在本地添加 alias
alias and-screencap="adb shell screencap -p | sed 's/\r$//'"
and-screencap > screen.png
在 shell 命令中可以使用 screenrecord
命令来录制屏幕。需要 Android 4.4 (API Level 19)及以上,该命令将屏幕保存成 MPEG-4 文件。不录制声音。
adb shell screenrecord /sdcard/Download/filename.mp4
使用 Ctrl + c 来停止录像,否则默认录制 3min 或者使用 --time-limit
参数来指定。
注意:
screenrecord
命令可以按照设备原始分辨率录屏,但是有些设备可能不支持原始分辨率,此时降低分辨率再尝试。可选参数:
--help
--size <width*Height>
比如 1280*720
.--bit-rate <rate>
默认码率 4Mbps,6Mbps 可以设置 6000000.--time-limit <TIME>
默认为 180 (3min) 设置时间,单位秒--rotate
旋转输出--verbose
显示 log 信息,如果不设置,不显示任何信息pm
可以记忆成 package manager ,使用 pm 命令可以获取设备上应用相关的信息。
使用如下命令 1:
adb shell 'pm list packages'
使用如下命令去除前面的 package:
adb shell pm list packages | awk -F ":" '{print $2}'
# 或者,-f 用来输出第二部分, -d 用来标示分割符号
adb shell pm list packages | cut -f 2 -d ":"
在使用 adb shell 进入 手机 Shell 之后可以使用, pm help 来获取更多关于 pm 命令的详情。关于 pm 的命令。
adb shell pm list packages
adb shell pm list packages -f
列出包名及对应的 apk 名及存放的位置adb shell pm list packages -d
Filter to only show disabled packages.adb shell pm list packages -e
Filter to only show enabled packages.adb shell pm list packages -s
Filter to only show system packages.adb shell pm list packages -3
Filter to only show third party packages.adb shell pm list packages -i
应用包名及其安装来源 com.android.vending 表示从官方 Play Store 安装adb shell pm list packages -u
Also include uninstalled packages.adb shell pm list packages --user <KEYWORDS>
The user space to query.在命令后直接添加关键词能够根据关键字过滤结果。
adb shell pm path com.android.chrome
能够给出应用的 apk 路径。
adb shell pm dump com.android.chrome
能够列出指定应用的各种信息
如果 apk 文件在 Android 设备上,可以使用
adb shell pm install /path/to/apk
adb shell pm uninstall package_name
adb shell pm clear # 清除应用数据
启动一个指定的 Activity
adb shell am start -n com.oneplus.camera/.OPCameraActivity
强制停止应用
adb shell am force-stop pacakge_name
命令格式
adb shell input text <string>
adb shell input keyevent <key code number or name>
adb shell input tap <x> <y> # 点击事件
adb shell input swipe <x1> <y1> <x2> <y2> [duration(ms)]
模拟按键的,keycode 为 3 时表示 HOME 键,更多的可以参考后文的附录
adb shell input keyevent 3
模拟点击时,后面接的 x,y 都是真实屏幕分辨率,比如想要点击屏幕 (x,y)=(150,150) 像素的位置
adb shell input tap 150 150
模拟屏幕滑动和 tap 是一样的,只是需要给出滑动的起点和终点两个坐标值
adb shell input swipe 150 150 200 200
列出设备上的输入法
adb shell ime list [-a] [-s]
adb shell ime enable ID
adb shell ime disable ID
adb shell ime set ID
获取设备分辨率
adb shell wm size
可以使用该命令安装应用程序,命令的通用模式:
adb install app.apk
可以使用 -r
命令覆盖安装应用 adb install -r apkfilename.apk
如果 adb 连接了多台设备可以使用 -s
来选择一台设备
adb -s DEVICE install -r app.apk
adb install
的其他参数
adb install -l app.apk
forward lock applicationadb install -r app.apk
替换存在的应用adb install -t app.apk
允许测试包adb install -s app.apk
在 sdcard 上安装adb install -d app.apk
允许比现在安装版本更低的包 allow version code downgradeadb install -p app.apk
增量更新 partial application install同理可以使用 adb uninstall apkfilename.apk
来卸载应用。
使用 adb uninstall -k apkfilename.apk
可以卸载应用,但是保留数据。
通过网络来使用 adb,可以通过该命令来连接网络上开放远程调试的设备(比如 Android 机顶盒之类)。
adb connect <host>[:<port>]
远程连接之后就可以使用上面的所有命令,也可卸载远程设备上的应用,也可以安装本地的 apk 到远程设备上,也可以通过 adb 命令来控制远程设备上的应用。
通过下面的命令向远程设备安装应用
adb -s <ip:port> install -r <app.apk>
向远程设备发送按键事件,比如下面向远程设备发送 Powerbutton 按键按下事件
adb -s <ip:port> shell input keyevent 26
或者启动远程设备上的应用 Start the App
adb -s <ip:port> shell monkey -p <package name> -c android.intent.category.LAUNCHER 1
在电视盒子上安装 Youtube 应用的时候,遇到了几个版本,突然想到这个命令
adb shell dumpsys package com.google.android.youtube | grep version
可以用来查看当前这个 package 的版本号。
使用 adb shell dumpsys
adb shell dumpsys activity activities | grep 'Hist #'
* Hist #0: ActivityRecord{b71f1a7 u0 com.oneplus.camera/.OPCameraActivity t4826}
* Hist #0: ActivityRecord{5de041d u0 slide.cameraZoom/.CameraZoomActivity t4825}
* Hist #0: ActivityRecord{1e2287c u0 mobi.acpm.inspeckage/.ui.MainActivity t4824}
* Hist #0: ActivityRecord{e96e625 u0 com.google.android.calendar/.AllInOneCalendarActivity t4812}
* Hist #0: ActivityRecord{cf38cb2 u0 com.google.android.googlequicksearchbox/com.google.android.apps.gsa.staticplugins.opa.OpaActivity t4711}
* Hist #0: ActivityRecord{ff685a1 u0 com.android.launcher3/.Launcher t4639}
* Hist #0: ActivityRecord{78edd61 u0 com.android.systemui/.recents.RecentsActivity t4652}
有一个常见的场景就是在需要备份已经安装的 app,导出 apk 的时候,如果是手机的的话借助 ES Explorer 能快速搞定,如果是机顶盒那么就要 adb connect 之后用命令来备份了。用到的命令上文都有提及,首先要知道需要备份的应用的包名 package name
adb shell pm list packages
然后获取该应用的完整路径
adb shell pm path com.example.app
输出结果会是类似于
package:/data/app/com.example.app-2.apk
这样的路径,然后使用 pull 命令将文件备份到本地
adb pull /data/app/com.example.app-2.apk /path/to/local/destination/app.apk
然后在目标目录下就能看到备份的内容了。
KEYCODE_UNKNOWN=0;
KEYCODE_SOFT_LEFT=1;
KEYCODE_SOFT_RIGHT=2;
KEYCODE_HOME=3;
KEYCODE_BACK=4;
KEYCODE_CALL=5;
KEYCODE_ENDCALL=6;
KEYCODE_0=7;
KEYCODE_1=8;
KEYCODE_2=9;
KEYCODE_3=10;
KEYCODE_4=11;
KEYCODE_5=12;
KEYCODE_6=13;
KEYCODE_7=14;
KEYCODE_8=15;
KEYCODE_9=16;
KEYCODE_STAR=17;
KEYCODE_POUND=18;
KEYCODE_DPAD_UP=19;
KEYCODE_DPAD_DOWN=20;
KEYCODE_DPAD_LEFT=21;
KEYCODE_DPAD_RIGHT=22;
KEYCODE_DPAD_CENTER=23;
KEYCODE_VOLUME_UP=24;
KEYCODE_VOLUME_DOWN=25;
KEYCODE_POWER=26;
KEYCODE_CAMERA=27;
KEYCODE_CLEAR=28;
KEYCODE_A=29;
KEYCODE_B=30;
KEYCODE_C=31;
KEYCODE_D=32;
KEYCODE_E=33;
KEYCODE_F=34;
KEYCODE_G=35;
KEYCODE_H=36;
KEYCODE_I=37;
KEYCODE_J=38;
KEYCODE_K=39;
KEYCODE_L=40;
KEYCODE_M=41;
KEYCODE_N=42;
KEYCODE_O=43;
KEYCODE_P=44;
KEYCODE_Q=45;
KEYCODE_R=46;
KEYCODE_S=47;
KEYCODE_T=48;
KEYCODE_U=49;
KEYCODE_V=50;
KEYCODE_W=51;
KEYCODE_X=52;
KEYCODE_Y=53;
KEYCODE_Z=54;
KEYCODE_COMMA=55;
KEYCODE_PERIOD=56;
KEYCODE_ALT_LEFT=57;
KEYCODE_ALT_RIGHT=58;
KEYCODE_SHIFT_LEFT=59;
KEYCODE_SHIFT_RIGHT=60;
KEYCODE_TAB=61;
KEYCODE_SPACE=62;
KEYCODE_SYM=63;
KEYCODE_EXPLORER=64;
KEYCODE_ENVELOPE=65;
KEYCODE_ENTER=66;
KEYCODE_DEL=67;
KEYCODE_GRAVE=68;
KEYCODE_MINUS=69;
KEYCODE_EQUALS=70;
KEYCODE_LEFT_BRACKET=71;
KEYCODE_RIGHT_BRACKET=72;
KEYCODE_BACKSLASH=73;
KEYCODE_SEMICOLON=74;
KEYCODE_APOSTROPHE=75;
KEYCODE_SLASH=76;
KEYCODE_AT=77;
KEYCODE_NUM=78;
KEYCODE_HEADSETHOOK=79;
KEYCODE_FOCUS=80;//*Camera*focus
KEYCODE_PLUS=81;
KEYCODE_MENU=82;
KEYCODE_NOTIFICATION=83;
KEYCODE_SEARCH=84;
KEYCODE_MEDIA_PLAY_PAUSE=85;
KEYCODE_MEDIA_STOP=86;
KEYCODE_MEDIA_NEXT=87;
KEYCODE_MEDIA_PREVIOUS=88;
KEYCODE_MEDIA_REWIND=89;
KEYCODE_MEDIA_FAST_FORWARD=90;
KEYCODE_MUTE=91;
https://gist.github.com/davidnunez/1404789 ↩
动画插值器,用来描述动画的变化率,这里讨论的 Interpolator 指的是 android.animation
包下的 TimeInterpolator
。 以下所有的插值器都继承自 Interpolator , 而 Interpolator 接口直接继承自 TimeInterpolator , 自身并没有添加任何方法。
TimeInterpolator 中有
abstract float getInterpolation(float input)
方法,参数 input:input 参数是一个 float 类型,它取值范围是 0 到 1,表示当前动画的进度,取 0 时表示动画刚开始,取 1 时表示动画结束,取 0.5 时表示动画中间的位置。返回值:表示当前实际想要显示的进度。取值可以超过 1 也可以小于 0,超过 1 表示已经超过目标值,小于 0 表示小于开始位置。
input 的值只与时间相关,和我们设定没有任何关系。线性插值器函数实现:
public float getInterpolation(float input) {
return input;
}
加速插值器,开始很慢,不断加速
public AccelerateInterpolator(float factor)
将factor设置为1.0f会产生一条y=x^2的抛物线。增加factor到1.0f之后为加大这种渐入效果(也就是说它开头更加慢,结尾更加快)
当fractor不为1时,轨迹曲线是 y=x^(2*fractor)(0<x<=1)
的曲线
减速插值器,开始比较快然后减速的插值器,动画的快慢度。将factor值设置为1.0f时将产生一条从上向下的y=x^2抛物线。增加factor到1.0f以上将使渐入的效果增强(也就是说,开头更快,结尾更慢)
加速减速插值器,开始慢从中间后开始变快
线性插值器
弹跳插值器
回荡秋千插值器
正弦周期变化插值器
ImageView 的 ScaleType 属性决定了图片在 View 上显示时的样子,是比例缩放,还是显示图片的整体或者局部等等。对于一张图片,有其自身的大小,而 ImageView 也有其自身的大小,这两者如何完美的合作其结果很重要的设置便是 ScaleType 属性。
设置该属性的方式有两种:
android:scaleType="center"
imageView.setScaleType(ImageView.ScaleType.CENTER);
所有的 Scale 方式有 8 种,文档 中可以查看到,下文也会详细介绍。
按图片原大小居中显示,不缩放原图片。当原始图片长/宽超过View的长/宽,则截取图片的居中部分显示,当图片长/宽小于 View 长宽时,可能造成填充不完全, ImageView 周围有空白的情况。
在 xml 中使用定义: android:scaleType="center"
按比例扩大图片的size居中显示,不改变图片宽高比,使得图片长(宽)等于或大于View的长(宽),图片填充满 ImageView,可能产生裁剪,此时能保证 View 被完整填充。也就意味着这种裁剪方式会使 ImageView 被完整填充,对于高大于宽的图片,高部分就会被裁剪。
在 xml 中使用定义: android:scaleType="centerCrop"
将图片的内容完整居中显示,通过按比例缩小或原来的size使得图片长/宽小于或等于View的长/宽,ImageView 可能产生空白部分。对于高度大于宽度图片,则高度填充整个 ImageView 高度,宽度则小于 ImageView 宽度,则宽度两边产生空白。
在 xml 中使用定义: android:scaleType="centerInside"
把图片按比例扩大/缩小到 ImageView 的高度或者宽度,使用 CENTER 方式居中显示,也就是使用该方式,使用图片长的一部分适应。
FIT_START
, FIT_END
在图片缩放效果上与 FIT_CENTER
一样,只是显示位置不同,FIT_START
是置于顶部,FIT_CENTER
居中,FIT_END
置于底部。
在 xml 中使用定义: android:scaleType="fitCenter"
、 android:scaleType="fitEnd"
、 android:scaleType="fitStart"
不按比例缩放图片,把图片塞满整个 View ,如果 View 与 原图片长宽不对应,可能造成图片长宽比改变,以及图片变形。
在 xml 中使用定义: android:scaleType="fitXY"
通过变化矩阵来设置 ImageView 大小。可以通过设置 matrix 然后手动利用 matrix 来调整 ImageView 可以实现 ImageView 的双指缩放和旋转。不过似乎用的很少。
具体细节可以继续再讨论。
如果要看效果图,这里 很不错,一目了然。
在 xml 中使用定义: android:scaleType="matrix"
每一种 View 都可以包含背景图片,而 ImageView 的 src 可以设置 ScaleType ,adjustViewBounds 等属性。
center, center_crop, center_inside, fit_center, fit_start, fit_end 等方式都会改变图片的比例,但是会有一定程度的裁剪。
使用如下 Layout
<ImageView
android:id="@id/img"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="fitCenter" />
使用 fitCenter
来使图片填充整个 ImageView 宽度,并且进行等比例放缩。
答案来自 StackOverflow
Android 的动画实现有不同的方式,在 3.0 以前 Android 的动画很简单只能在 View 层做,在后期版本中不断的加入动画实现,至今已经有这非常完善的动画系统了。Android 系统提供了 Property animation 和 View animation 两大动画系统。除去这两大动画系统之外,还有一类 Drawable Animation, 允许加载 drawable 并且一帧一帧播放:
另外官方文档也有另外一种分类方法 将 Tween Animation 补间动画 和 Frame Animation 逐帧动画归纳为 View Animation。 见文档
旧的动画系统,只能用来对 View 进行动画。View Animation 很简单,不过只能支持简单的缩放、平移、旋转、透明度基本的动画,且有一定的局限性。
Android中提供的 4种 View 动画:
以及 AnimationSet 动画集合,可以混合使用多种动画。 View Animation 都在 view.animation 包名下。
Android 系统在 3.0 之后推出了 Property Animation (属性动画)框架,属性动画可以用于任何对象,相比属性动画,View Animation (视图动画)的一个非常大的缺陷就是不具备交互性,当某个元素发生视图动画后,其响应事件的位置还依然是在动画前的地方,所以视图动画只能做普通的动画效果,避免交互的发生。但它的优点也非常明显,即效率比较高且使用方便。
视图动画使用非常简单,不仅可以通过XML文件来描述一个动画过程,同样可以使用代码来控制整个动画过程。
animation.setDuration(long durationMillis); // 设置动画时长
animation.setRepeatCount(int repeatCount); // 设置动画重复次数
animation.setFillAfter(boolean); // 动画执行完后是否停留在执行完的状态
animation.setFillBefore(boolean); // 动画执行前是否应用状态
animation.setStartOffset(long startOffset); // 动画执行前的等待时间
animation.setInterpolator(Interpolator i); // 设置动画插值
// 设置重复模式, 这个模式只有在 repeat count 大于0 或者 INFINITE 时才生效,有 RESTART 和 REVERSE 两种,RESTART 为重头播放,REVERSE 为逆向播放动画。
animation.setRepeatMode(int repeatMode);
animation.setStartTime(long startTimeMillis); // 设置动画开始时间
animation.start(); // 开始动画
animation.startNow(); // 立即开始动画
启动动画的两种方式:
view.startAnimation(animation);
//或者设置动画之后延后开始动画
view.setAnimation(animation);
animation.start();
当使用 xml 配置动画时,需要放到 res 目录下 res/anim/
。 xml 定义的 root 元素可以是 :
<alpha>
<scale>
<translate>
<rotate>
interpolator
元素<set>
或者 set 中包含其他 set举例:
<set android:shareInterpolator="false">
<scale
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:fromXScale="1.0"
android:toXScale="1.4"
android:fromYScale="1.0"
android:toYScale="0.6"
android:pivotX="50%"
android:pivotY="50%"
android:fillAfter="false"
android:duration="700" />
<set android:interpolator="@android:anim/decelerate_interpolator">
<scale
android:fromXScale="1.4"
android:toXScale="0.0"
android:fromYScale="0.6"
android:toYScale="0.0"
android:pivotX="50%"
android:pivotY="50%"
android:startOffset="700"
android:duration="400"
android:fillBefore="false" />
<rotate
android:fromDegrees="0"
android:toDegrees="-45"
android:toYScale="0.0"
android:pivotX="50%"
android:pivotY="50%"
android:startOffset="700"
android:duration="400" />
</set>
</set>
可以使用如下代码,从 XML 中加载动画:
ImageView spaceshipImage = (ImageView) findViewById(R.id.spaceshipImage);
Animation hyperspaceJumpAnimation = AnimationUtils.loadAnimation(this, R.anim.hyperspace_jump);
spaceshipImage.startAnimation(hyperspaceJumpAnimation);
接下来就分别看一下不同 View Animation 的使用。
AlphaAnimation 动画,可实现淡入淡出。
AlphaAnimation(float fromAlpha, float toAlpha)
参数说明:float 设置透明度渐变动画, 1.0 完全不透明, 0.0 是完全透明
然后利用 View 的 startAnimation 方法就可以使用。
旋转动画,可以在 X-Y 平面设置旋转的动画,可以指定旋转中心, (0,0) 表示 top left 坐点,如果不指定,默认为左上角为旋转中心。
有四个构造函数:
RotateAnimation(Context context, AttributeSet attrs)
// 默认旋转中心为 (0,0)
RotateAnimation(float fromDegrees, float toDegrees)
RotateAnimation(float fromDegrees, float toDegrees, float pivotX, float pivotY)
RotateAnimation(float fromDegrees, float toDegrees, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)
参数说明:
Animation.ABSOLUTE
、RELATIVE_TO_SELF
、RELATIVE_TO_PARENT
。决定了 pivotXValue 的方式。ABSOLUTE
、RELATIVE_TO_SELF
、RELATIVE_TO_PARENT
。放缩动画,可指定缩放中心。
ScaleAnimation(Context context, AttributeSet attrs)
ScaleAnimation(float fromX, float toX, float fromY, float toY)
ScaleAnimation(float fromX, float toX, float fromY, float toY, float pivotX, float pivotY)
ScaleAnimation(float fromX, float toX, float fromY, float toY, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)
参数说明:
Animation.ABSOLUTE
, Animation.RELATIVE_TO_SELF
,Animation.RELATIVE_TO_PARENT.
.位移动画,可以控制位置的动画
TranslateAnimation(Context context, AttributeSet attrs)
TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta)
TranslateAnimation(int fromXType, float fromXValue, int toXType, float toXValue, int fromYType, float fromYValue, int toYType, float toYValue)
参数说明:
Animation.ABSOLUTE
, Animation.RELATIVE_TO_SELF
, or Animation.RELATIVE_TO_PARENT
Android 3.0, API 11 及以上,可以对任意类型进行动画。 属性动画在系统的 android.animation 包名下。总的来说,属性动画就是,动画的执行类来设置动画操作的对象的属性、持续时间,开始和结束的属性值,时间差值等,然后系统会根据设置的参数动态的变化对象的属性。
可定义如下参数:
addListener(Animator.AnimatorListener listener); // 添加监听器,可以手动设置监听,手动设置属性
isRunning(); // 当前动画是否在执行
isStarted(); // 动画是否开始
isPaused(); // 暂停状态
setDuration(long duration); // 设置动画时长,单位为毫秒
setInterpolator(TimeInterpolator value); // 设置动画插值
setStartDelay(long startDelay); // start() 方法被调用之后延时
setTarget(Object target); // 设置动画主体
start(); // 开始动画
cancel(); // 取消动画
static ValueAnimator ofArgb(int... values); // 颜色动画
static ValueAnimator ofFloat(float... values)
static ValueAnimator ofInt(int... values)
static ValueAnimator ofObject(TypeEvaluator evaluator, Object... values)
setRepeatCount(int value); // 可选值 INFINITE 无限循环动画
setRepeatMode(int value); // RESTART,REVERSE
Object getAnimatedValue(); // 运动时,当前运动点的值
// 监听动画变化时的实时值
public static interface AnimatorUpdateListener {
void onAnimationUpdate(ValueAnimator animation);
}
// 添加方法为:public void addUpdateListener(AnimatorUpdateListener listener)
// 监听动画变化时四个状态
public static interface AnimatorListener {
void onAnimationStart(Animator animation); // 动画开始
void onAnimationEnd(Animator animation); // 动画结束
void onAnimationCancel(Animator animation); // 动画 cancel
void onAnimationRepeat(Animator animation); // 动画重复
}
//添加方法为:public void addListener(AnimatorListener listener)
removeAllListeners();
removeListener(Animator.AnimatorListener listener);
removePauseListener(Animator.AnimatorPauseListener listener);
默认的 ValueAnimator 使用非线性的插值器 interpolation,加速进入减速退出,可以通过 setInterpolator(TimeInterpolator) 来改变默认的行为。
可以类似 View Animation 定义 xml 来创建动画, 动画资源文件需要保存在 res/animator/
目录下。Animator 动画支持:
<animator>
<objectAnimator
<set>
<animator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:valueFrom="1"
android:valueTo="0"
android:valueType="floatType"
android:repeatCount="1"
android:repeatMode="reverse"/>
<!-- 同样可以定义动画集合,顺序执行动画 -->
<set android:ordering="sequentially">
<set>
<objectAnimator
android:propertyName="x"
android:duration="500"
android:valueTo="400"
android:valueType="intType"/>
<objectAnimator
android:propertyName="y"
android:duration="500"
android:valueTo="300"
android:valueType="intType"/>
</set>
<objectAnimator
android:propertyName="alpha"
android:duration="500"
android:valueTo="1f"/>
</set>
定义动画资源之后可以使用如下代码使用动画:
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext,
R.animator.property_animator);
set.setTarget(myObject);
set.start();
更多XML定义的语法可以参考官方 文档
ObjectAnimator 动画的执行类,后面详细介绍 ValueAnimator 动画的执行类 AnimatorSet 用于控制一组动画的执行:线性,一起,每个动画的先后执行等。 AnimatorInflater 用户加载属性动画的xml文件 TypeEvaluator 类型估值,主要用于设置动画操作属性的值。 TimeInterpolator 时间插值,有很多子类,可以具体展开再讲,AccelerateDecelerateInterpolator, AccelerateInterpolator, AnticipateInterpolator, AnticipateOvershootInterpolator, BaseInterpolator, BounceInterpolator, CycleInterpolator, DecelerateInterpolator, FastOutLinearInInterpolator, FastOutSlowInInterpolator, Interpolator, LinearInterpolator, LinearOutSlowInInterpolator, OvershootInterpolator, PathInterpolator
ValueAnimator animator = ValueAnimator.ofInt(0,1000);
animator.setDuration(1000);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int curValue = (int)animation.getAnimatedValue();
Log.d(TAG,"curValue: "+curValue);
}
});
animator.start();
同样也可以通过 ofFloat
, ofObject
等等静态方法构造不同类型的 ValueAnimator。然后通过监听器动态地更新属性。
ObjectAnimator anim = ObjectAnimator.ofFloat(foo, "alpha", 0f, 1f);
anim.setDuration(1000);
anim.start();
ObjectAnimator 使用范围更广,但是同样也有很多约束条件。
可以在 res/drawable/
目录下定义 XML 文件:
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="true">
<item android:drawable="@drawable/rocket_thrust1" android:duration="200" />
<item android:drawable="@drawable/rocket_thrust2" android:duration="200" />
<item android:drawable="@drawable/rocket_thrust3" android:duration="200" />
</animation-list>
用如下代码,将 Drawable 附加到 ImageView 中:
AnimationDrawable rocketAnimation;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ImageView rocketImage = (ImageView) findViewById(R.id.rocket_image);
rocketImage.setBackgroundResource(R.drawable.rocket_thrust);
rocketAnimation = (AnimationDrawable) rocketImage.getBackground();
}
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
rocketAnimation.start();
return true;
}
return super.onTouchEvent(event);
}
start()
方法不能在 onCreate()
方法中调用, AnimationDrawable 此时还没有附加到window 上,如果需要动画自动播放,可以在 onWindowFocusChanged()
中调用。
更多的 XML 语法可以参考官方文档