和你一起终身学习,这里是程序员 Android
本篇文章主要介绍 Android
开发中的部分知识点,通过阅读本篇文章,您将收获以下内容:
一、CPU 温度相关
二、开机向导相关方法
三、APP启动时间相关
四、判断 user,userdebug 版本的方法
五、修改截屏默认存储路径
六、解析 kernel dump 方法
七、SPRD 默认打开 Ylog 以及dumpsys enable方法
八、判断是否正在 monkey 测试的方法
九、修改MTK log 模式的方法
十、MTK平台只开Mobile log方法
十一、SPRD平台 只开Android log方法
十二、SPRD平台功耗 Log 注意事项
十三、获取Top Activity 包名
十四、OTG 去掉白色焦点框的方法
十五、修改状态栏 时间显示秒
十六、判断多用户方法
十七、低RAM(1G)下的模糊效果去除
十八、屏幕四周圆角方案
十九、uiautomator 使用ADB抓取方法
二十、开机动画到Launcher界面闪黑屏解决方案
二十一、优化少数特定App冷启动方案
二十二、SPRD平台判断mode log 打开的方法
一、CPU 温度相关
1.使用ADB 查看CPU温度(debug版本)
查看CPU命令如下:
adb shell cat /sys/class/thermal/thermal_zone*/temp
2.查看CPU 返回内容对应分类信息
adb shell cat /sys/class/thermal/thermal_zone*/type
CPU 温度查看命令方法使用举例如下:

由此查看的 CPU 温度包含小数点后三位,小数点省去,此方法适用于MTK 平台。
3.MTK log 中查看CPU 温度
kernel log中 搜索关键字 T_AP 查看CPU 温度。

二、 开机向导相关方法
1.debug 版本跳过开机向导方案
- 1.点击四次快捷操作
连续点击屏幕四角(左上-->右上-->右下-->左下),既可跳过开机向导。

- adb 命令disable 开机向导
adb shell settings put secure user_setup_complete 1
adb shell settings put global device_provisioned 1
adb shell pm disable com.google.android.setupwizard/.SetupWizardActivity
2.debug 重启 开机向导方案
跳过开机向导 后 又想重新走开机向导,可以尝试以下命令。
- 1.将开机向导 完成后设置的值复位
adb命令如下:
adb shell settings put secure user_setup_complete 0
adb shell settings put global device_provisioned 0
- 设置开机向导可用,并启动
过完开机向导后,会设置开机向导apk
不可用。
此时我们应该设置开机向导为enable
状态。
adb shell pm enable com.google.android.setupwizard/.SetupWizardActivity
adb shell am start -n com.google.android.setupwizard/.SetupWizardActivity
3. 开机向导 log 调试方案
打开开机向导调试Log
方式如下:
adb shell setprop log.tag.SetupWizard VERBOSE
4. 代码中跳过开机向导的方法
在代码中跳过开机向导的方法如下:
private void SkipSetupwizard(){
ActivityManager activityAanager = (ActivityManager) mContext
.getSystemService(Context.ACTIVITY_SERVICE);
ComponentName cn = activityAanager.getRunningTasks(1).get(0).topActivity;
String pName = cn.getPackageName();
if("com.google.android.setupwizard".equals(pName))
{
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 1);
Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, 1);
activityAanager.forceStopPackage("com.google.android.setupwizard");
Log.i("wjwj","----------skip com.google.android.setupwizard--------");
}
}
5. 修改Google 开机向导欢迎语
孟加拉语开机向导欢迎语不对,客户要求去掉开机向导界面欢迎语方法。
idh.code/frameworks/base/core/java/android/widget/TextView.java
public class TextView extends View implements ViewTreeObserver.OnPreDrawListener {
... ...
public void setTextLocale(@NonNull Locale locale) {
// add for Bangla language
if (getContext().getClass().getName().equals("com.google.android.setupwizard.user.WelcomeActivity") &&
locale.getLanguage().equals("bn") && locale.getCountry().equals("BD"))
{
Log.i(LOG_TAG, "find text:" + getText());
if (!getText().equals("") && !getText().toString().contains("("))
Log.i(LOG_TAG, "set text:" + getText());
setText("");
}
// add for Bangla language
mLocalesChanged = true;
mTextPaint.setTextLocale(locale);
... ...
}
... ...
}
三、 APP启动时间相关
1.使用adb 抓log 查看方法
adb logcat | findstr Displayed
或者直接抓取 adb Log, 然后搜索关键字 Displayed


2.多次 app 查看方法
- 测试 10次 Chrome 冷启动的方法如下:
adb shell am start -S -R10 -W com.android.chrome/com.google.android.apps.chrome.Main
部分测试结果如下:
C:\Users\Administrator>adb shell am start -S -R10 -W com.android.chrome/com.google.android.apps.chrome.Main
Stopping: com.android.chrome
Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.android.chrome/com.google.android.apps.chrome.Main }
Status: ok
Activity: com.android.chrome/org.chromium.chrome.browser.firstrun.FirstRunActivity
TotalTime: 1514
WaitTime: 1525
Complete
Stopping: com.android.chrome
Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.android.chrome/com.google.android.apps.chrome.Main }
Status: ok
... ...
Activity: com.android.chrome/org.chromium.chrome.browser.firstrun.FirstRunActivity
TotalTime: 534
WaitTime: 549
Complete
- 测试 10次 支付宝冷启动的方法如下:
adb shell am start -S -R10 -W com.eg.android.AlipayGphone/.AlipayLogin
- 测试 10次 淘宝冷启动的方法如下:
adb shell am start -S -R10 -W com.taobao.taobao/com.taobao.tao.welcome.Welcome
- 测试 10次 微信冷启动的方法如下:
adb shell am start -S -R10 -W com.tencent.mm/.ui.LauncherUI
- 测试 10次 QQ冷启动的方法如下:
adb shell am start -S -R10 -W com.tencent.mobileqq/.activity.SplashActivity
- 测试 10次 QQ浏览器冷启动的方法如下:
adb shell am start -S -R10 -W com.tencent.mtt/.SplashActivity
四、判断 user ,userdebug 版本的方法
1.判断 user ,userdebug 版本的方法
private static final boolean USER_BUILD = android.os.Build.IS_USER;
2.源码参考来源
查看 Build.java 发现,这些是对外部apk 隐藏的方法,只有系统平台 签名的应用才可以使用。
/** {@hide} */
public static final boolean IS_ENG = "eng".equals(TYPE);
/** {@hide} */
public static final boolean IS_USERDEBUG = "userdebug".equals(TYPE);
/** {@hide} */
public static final boolean IS_USER = "user".equals(TYPE);
五、修改截屏默认存储路径
音量下
与Power键
组合键可以截取Android 手机当前界面图片,修改类如下/frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
,
修改 SystemUI 音量下
与Power键
组合键截屏保存位置的方法如下:
class SaveImageInBackgroundData {
private static final boolean SAVE_EXTERNAL_STORAGE = false;
... ...
public static void getScreenshotPicInfo(ScreenshotPicInfo info) {
info.mImageTime = System.currentTimeMillis();
info.dateSeconds = info.mImageTime / 1000;
String imageDate = new SimpleDateFormat("yyyyMMdd-HHmmss").format(new Date(info.mImageTime));
info.mImageFileName = String.format(SCREENSHOT_FILE_NAME_TEMPLATE, imageDate);
File mScreenshotDir = null;
if(!SAVE_EXTERNAL_STORAGE){
mScreenshotDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), SCREENSHOTS_DIR_NAME);
}else{
mScreenshotDir = new File(getStorePath(), SCREENSHOTS_DIR_NAME);
}
if (!mScreenshotDir.exists()) mScreenshotDir.mkdir();
/*SPRD :fix bug 708401,modify save path for a screenshot*/
info.longscreenshotFilePath = new File(mScreenshotDir, info.mImageFileName).getAbsolutePath();
}
... ...
}
六、解析 kernel dump 方法
1.将所有 dump 文件追加到一个文件中
首先我们需要抓到dumpsys log,然后将所有的systemcore* 文件 追加到一个文件中。
使用的命令如下:
cat systemcore* > all

2. 使用对应版本的vmlinux 解析dump文件
使用对应版本的vmlinux 解析dump文件, crash_arm 有32位跟 64位的区别,常用使用方法如下:
-
32位系统使用如下:
./crash_arm vmlinux all -m phys_base=0x80000000
-
64位系统使用如下命令:
./crash_arm64 vmlinux all -m phys_offset=0x80000000
3.解析成功后进行调试
成功解析dump后解析log方法
log > log.txt

七、SPRD 默认打开 Ylog 以及dumpsys enable方法
1. 修改方案
修改 device\sprd\xxxx\common\rootdir\root\init.common.rc
在on post-fs-data
中添加如下内容:
on post-fs-data
.....
setprop persist.ylog.enabled 1//增加这一句用于打开ylog
setprop debug.sysdump.enabled true //增加这一句用于打开sysdump
setprop persist.sys.eng.reset 1 //再增加这一句
start ylog
八、 判断是否正在monkey测试
monkey 是我们经常用来测试系统或者app稳定性的测试方法,但是我们有些功能是不需要monkey触发的,比如定时关机等功能。
判断是否正在进行monkey测试的方法如下:
public boolean isMonkeyRunning() {
return ActivityManager.isUserAMonkey();
}
九、 MTK log 模式开关修改的方法
修改以下路径下配置的属性值既可修改MTK默认的log 开关,修改目录如为alps\device\mediatek\common\mtklog
。
将false
改为true
就可以打开对应的log
mtklog_path = internal_sd
com.mediatek.log.mobile.enabled = false
com.mediatek.log.mobile.maxsize = 500
com.mediatek.log.mobile.totalmaxsize = 1000
com.mediatek.log.modem.enabled = false
com.mediatek.log.modem.maxsize = 2000
com.mediatek.log.net.enabled = false
com.mediatek.log.net.maxsize = 600
com.mediatek.log.gps.enabled = false
十、MTK平台 只开Mobile log方法
输入暗码 *#*#3646633#*#*
,进入MTK Logger
界面,右上角打开Logger Setting
,手动关闭除Moblie Log
之外的开关。
关闭方法请看下图:

十一、SPRD平台 只开Android log方法
输入暗码 *#*#83781#*#*
,进入SPRD Logger
界面,右上角打开Settings
, 点击Custom scene
,关闭除Android log
之外的开关,关闭方法请看下图。

十二、SPRD 平台功耗 Log 注意事项
- 只开 Android Log(
参考十一、SPRD平台 只开Android log方法
) - 进入
DEBUG&Log
界面,system info
->Power Log
; - 打开
PowerGuru log
和wakelock log
; - 重启设备。
- 使用下面命令,复位一下
battery history
adb shell dumpsys batterystats --enable full-wake-history
adb shell dumpsys batterystats --reset
- 测试完成后,使用下面命令,抓取
bugreport
adb root
adb bugreport > bugreport.zip
- 最后将
andorid log
和bugreport.zip
都提供出来。
十三、获取Top Activity 包名
获取Activity Top的方法如下:
//import android.app.ActivityManager;
//import android.app.ActivityManager.RunningTaskInfo;
//import android.content.ComponentName;
//import java.util.List;
// 获取top Activity apk
public String getTopActivityPackageName(Context context) {
String topActivityPackage = null;
ActivityManager activityManager = (ActivityManager) (context
.getSystemService(android.content.Context.ACTIVITY_SERVICE));
List<RunningTaskInfo> runningTaskInfos = activityManager
.getRunningTasks(1);
if (runningTaskInfos != null) {
ComponentName f = runningTaskInfos.get(0).topActivity;
topActivityPackage = f.getPackageName();
//Slog.e("wangjie", "------topActivityPackage---------"+topActivityPackage);
}
return topActivityPackage;
}
十四、OTG 去掉白色焦点框的方法
当手机连接OTG功能时候,通过鼠标点击Launcher 桌面上的文件夹里的内容,退出点击后,会导致桌面文件夹有默认的焦点,并且不会随着Launcher的滑动而消失。
出现问题截图如下:

解决方案如下:
1. 修改 Folder文件
Folder文件路径为packages/apps/Launcher3/src/com/android/launcher3/folder/Folder.java
,
修改方法如下:
public class Folder extends AbstractFloatingView implements DragSource,
View.OnLongClickListener, DropTarget, FolderListener, TextView.OnEditorActionListener,
View.OnFocusChangeListener, DragListener, ExtendedEditText.OnBackKeyListener {
... ...
private void closeComplete(boolean wasAnimated) {
// TODO: Clear all active animations.
.. ...
if (mFolderIcon != null) {
mFolderIcon.setVisibility(View.VISIBLE);
mFolderIcon.setBackgroundVisible(true);
mFolderIcon.mFolderName.setTextVisibility(true);
if (wasAnimated) {
mFolderIcon.mBackground.fadeInBackgroundShadow();
mFolderIcon.mBackground.animateBackgroundStroke();
mFolderIcon.onFolderClose(mContent.getCurrentPage());
if (mFolderIcon.hasBadge()) {
mFolderIcon.createBadgeScaleAnimator(0f, 1f).start();
}
// Launcher上的文件夹关闭时候不回去焦点
//mFolderIcon.requestFocus();
}
}
if (mRearrangeOnClose) {
rearrangeChildren();
mRearrangeOnClose = false;
}
... ...
}
... ...
}
2.修改FocusIndicatorHelper文件
修改FocusIndicatorHelper文件,使得Launcher桌面文件夹中的app icon 也不绘制背景。
修改文件路径为packages/apps/Launcher3/src/com/android/launcher3/keyboard/FocusIndicatorHelper.java
修改方法如下:
public abstract class FocusIndicatorHelper implements
OnFocusChangeListener, AnimatorUpdateListener {
... ...
public void draw(Canvas c) {
if (mAlpha > 0) {
Rect newRect = getDrawRect();
if (newRect != null) {
mDirtyRect.set(newRect);
// Launcher桌面文件夹中的app icon 也不绘制背景
//c.drawRect(mDirtyRect, mPaint);
mIsDirty = true;
}
}
}
... ...
}
十五、修改状态栏 时间显示秒
展讯平台修改状态栏 时间显示秒方法如下
adb shell pm enable com.android.systemui/com.android.systemui.tuner.TunerActivity
adb shell am start -n com.android.systemui/com.android.systemui.tuner.TunerActivity
进入设置--系统--界面界面调谐器--状态栏--时间--显示时分秒。
十六、判断多用户方法
判断多用户方法如下:
// import android.os.UserHandle;
if(UserHandle.myUserId() != UserHandle.USER_OWNER){
// 给管理员用户 进行操作
}
十七、低RAM(1G)下的模糊效果去除
Android GO 版本下,为了兼容系统性能,牺牲部分UI体验,比如 最近任务列表模糊,Settings 界面加载由模糊到清晰,Launcher 图标加载由模糊到清晰,但是这个很影响用户体验,个人认为不太好,去掉模糊效果的方案如下:
1.需要修改的文件如下:
frameworks/base/services/core/java/com/android/server/wm/AppWindowContainerController.java
frameworks/base/services/core/java/com/android/server/wm/TaskSnapshotController.java
frameworks/base/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
- 1.AppWindowContainerController 修改方法
在AppWindowContainerController.java 类中,请注释掉scheduleAddStartingWindow方法实现。
public class AppWindowContainerController
extends WindowContainerController<AppWindowToken, AppWindowContainerListener> {
... ...
// 注释掉该方法
void scheduleAddStartingWindow() {
// Note: we really want to do sendMessageAtFrontOfQueue() because we
// want to process the message ASAP, before any other queued
// messages.
/***
if (!mService.mAnimationHandler.hasCallbacks(mAddStartingWindow)) {
mContainer.startingAdding = true;
if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Enqueueing ADD_STARTING");
mService.mAnimationHandler.postAtFrontOfQueue(mAddStartingWindow);
} ***/
}
... ...
}
- 2.TaskSnapshotController 修改方法
将系统手动设置为非低内存设备,比如将isLowRamDevice =false状态。
class TaskSnapshotController {
... ...
// 将系统手动设置为非低内存设备
final boolean isLowRamDevice = false;
//final boolean isLowRamDevice = ActivityManager.isLowRamDeviceStatic();
... ...
- 3.TaskSnapshotPersister 修改方法
在TaskSnapshotPersister 类中,将DISABLE_FULL_SIZED_BITMAPS状态设置为false。
class TaskSnapshotPersister {
... ...
// 将DISABLE_FULL_SIZED_BITMAPS状态设置为false。
static final boolean DISABLE_FULL_SIZED_BITMAPS = false;
//static final boolean DISABLE_FULL_SIZED_BITMAPS = ActivityManager.isLowRamDeviceStatic();
... ...
}
十八、屏幕四周圆角方案
SPRD屏幕四周圆角方案需要修改***.dtsi 文件。
以sc7731e.dtsi 为例,需要修改的文件路径为kernel4.4/arch/arm/boot/dts/sc7731e.dtsi
,其中15
表示圆角的弧度,默认直角90度
修改方法如下:
soc: soc {
ap-ahb {
dispc0: dispc@20800000 {
... ...
sprd,ip = "dpu-lite-r1p0";
sprd,soc = "pike2";
// 15 表示圆角的弧度
sprd,corner-radius = <15>;
/* output port */
port {
dispc0_out: endpoint@0 {
remote-endpoint = <&dsi0_in>;
};
};
};
... ...
}
十九、UIAutomator 使用ADB抓取方法
由于DDMS的 UIAutomator 不管使用,但是又无法解决Eclipse 的异常问题,同时又不得不看界面的一些属性。

网上搜索了一些解决方案,建议使用以下方法
C:\Users\Administrator>adb shell uiautomator dump /sdcard/app4.uix
UI hierchary dumped to: /sdcard/app4.uix
C:\Users\Administrator>adb shell screencap -p /sdcard/app4.png
C:\Users\Administrator>adb pull /sdcard/app4.uix .
/sdcard/app4.uix: 1 file pulled. 2.5 MB/s (13044 bytes in 0.005s)
C:\Users\Administrator>adb pull /sdcard/app4.png .
/sdcard/app4.png: 1 file pulled. 7.2 MB/s (52692 bytes in 0.007s)
C:\Users\Administrator>
然后通过 DDMS打开pull出的文件即可

二十、开机动画到Launcher界面闪黑屏解决方案
开机动画到Launcher界面闪黑屏,分析好长时间才发现,存储格式的bootanimation.zip
的开机动画包中的desc.txt 需要在最后一行保留一个空行,不然就会出现开机动画结束闪黑屏问题,具体是BootAnimation.cpp 代码中控制的。
把锁屏功能设置为None ,黑屏行为更明显,会出现以下类似问题。

部分代码如下:
namespace android {
... ...
bool BootAnimation::parseAnimationDesc(Animation& animation)
{
String8 desString;
if (!readFile(animation.zip, "desc.txt", desString)) {
return false;
}
char const* s = desString.string();
#ifdef BOOTANIMATION_EXT
ALOGE("before allowed, soundplay");
if (playSoundsAllowed()) {
ALOGE("soundplay called");
soundplay();
}
#endif
// Parse the description file
for (;;) {
const char* endl = strstr(s, "\n");
if (endl == NULL) break;
String8 line(s, endl - s);
const char* l = line.string();
int fps = 0;
int width = 0;
int height = 0;
int count = 0;
int pause = 0;
char path[ANIM_ENTRY_NAME_MAX];
char color[7] = "000000"; // default to black if unspecified
char clockPos1[TEXT_POS_LEN_MAX + 1] = "";
char clockPos2[TEXT_POS_LEN_MAX + 1] = "";
char pathType;
if (sscanf(l, "%d %d %d", &width, &height, &fps) == 3) {
// ALOGD("> w=%d, h=%d, fps=%d", width, height, fps);
if (property_get_bool("ro.sprd.superresolution", 0)) {
animation.width = mWidth;
animation.height = mHeight;
} else {
animation.width = width;
animation.height = height;
}
animation.fps = fps;
} else if (sscanf(l, " %c %d %d %s #%6s %16s %16s",
&pathType, &count, &pause, path, color, clockPos1, clockPos2) >= 4) {
//ALOGD("> type=%c, count=%d, pause=%d, path=%s, color=%s, clockPos1=%s, clockPos2=%s",
// pathType, count, pause, path, color, clockPos1, clockPos2);
Animation::Part part;
part.playUntilComplete = pathType == 'c';
part.count = count;
part.pause = pause;
part.path = path;
part.audioData = NULL;
part.animation = NULL;
if (!parseColor(color, part.backgroundColor)) {
ALOGE("> invalid color '#%s'", color);
part.backgroundColor[0] = 0.0f;
part.backgroundColor[1] = 0.0f;
part.backgroundColor[2] = 0.0f;
}
parsePosition(clockPos1, clockPos2, &part.clockPosX, &part.clockPosY);
animation.parts.add(part);
}
else if (strcmp(l, "$SYSTEM") == 0) {
// ALOGD("> SYSTEM");
Animation::Part part;
part.playUntilComplete = false;
part.count = 1;
part.pause = 0;
part.audioData = NULL;
part.animation = loadAnimation(String8(SYSTEM_BOOTANIMATION_FILE));
if (part.animation != NULL)
animation.parts.add(part);
}
s = ++endl;
}
return true;
}
... ...
}
二十一、优化少数特定App冷启动方案
此方案仅适用于优化一些使用频率很高,客户又强烈要求的app,主要实现思想是将特定app设置为系统persistent app,但是这样做的一个坏处是需要占用部分内存空间。
将app 设置为persistent app的方法如下:
1.有app 源码的方案
修改AndroidManifest.xml 文件,将android:persistent
设置为true即可。
修改参考如下:
<application
android:persistent="true|false">
</application>
2.没有app 源码的修改方案
没有app源码,我们需要修改AMS(frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java)
中的startPersistentApps方法,将 所需要设置为常驻系统内存的app 添加进去即可。
修改方案如下:
public class ActivityManagerService extends IActivityManager.Stub
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
void startPersistentApps(int matchFlags) {
if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL) return;
synchronized (this) {
try {
final List<ApplicationInfo> apps = AppGlobals.getPackageManager()
.getPersistentApplications(STOCK_PM_FLAGS | matchFlags).getList();
// add start for twitter
ApplicationInfo chromeInfo = mContext.getPackageManager().getApplicationInfo("com.twitter.android", 0);
apps.add(chromeInfo);
//add start for twitter
for (ApplicationInfo app : apps) {
if (!"android".equals(app.packageName)) {
addAppLocked(app, null, false, null /* ABI override */);
}
}
} catch (Exception ex) {
}
}
}
}
二十二、SPRD平台判断mode log 打开的方法
SPRD Ylog 由于modem log形式的改变,故现在没有modem log的文件夹,我们可以从kernel log中查看
如下关键字smsg-5-5,看看modem log是否开启。
224[12-27 15:06:20.839] <6>[ 5087.753354] c1 51 active wakeup source: smsg-5-5
友情推荐:
Android 干货分享
至此,本篇已结束,如有不对的地方,欢迎您的建议与指正。同时期待您的关注,感谢您的阅读,谢谢!

网友评论