android有趣功能实现,adb命令实现一些有趣的功能

下载ADB工具集,手机连接电脑后,用Windows自带命令行进入ADB工具,输入以下命令即可免root实现神奇功能

1.电量显示:

adb shell content insert --uri content://settings/system --bind name:s:status_bar_show_battery_percent --bind value:i:1

2.全屏沉浸:

adb shell settings put global policy_control immersive.full=*

3.沉浸状态栏:

adb shell settings put global policy_control immersive.status=*

4.沉浸导航栏:

adb shell settings put global policy_control immersive.navigation=*

5.我们还可以单独控制哪些app不沉浸,例如以下代码设置google即时桌面不沉浸,其他程序沉浸:

adb shell settings put global policy_control immersive.full=apps,-com.google.android.googlequicksearchbox

6.如果想恢复到正常模式,运行下面的代码:

adb shell settings put global policy_control null

7.截图命令screencap

adb shell screencap -p /sdcard/screen.png

8.命令行下拉和收缩状态栏

adb shell service call statusbar 1 //下拉显示命令行

adb shell service call statusbar 2 //收缩状态栏

在nexus6吧发现了上面这个帖子,感谢nexus6吧的机友,亲测可用,很强大,可以正常使用输入法,使用虚拟按键时从底部上滑即可,比贴吧里那个使用全能助手隐藏虚拟键的方法好些,adb工具用刷机精灵也可以,我是把第四条和第五条命令综合一下,nova启动器不隐藏虚拟键,其他全部隐藏虚拟键,但状态栏都不隐藏,指令:

adb shell settings put global policy_control immersive.navigation=apps,-com.teslacoilsw.launcher

adb shell settings put global policy_control immersive.navigation=apps,-com.teslacoilsw.launcher,-com.motorola.camera

由于机友反映打开相机无法呼出虚拟键,今天把指令改进了一下,这个adb指令可以让nova启动器和moto相机都不隐藏虚拟键,从而解决了隐藏虚拟键后打开相机上滑无法呼出虚拟键。

moto z/z play按一下指纹键就可以自动呼出虚拟键,不用上滑呼出的,所以,这种方法还是可以的,不用root,不影响OTA和保修。

(注意:1.adb工具也可以下载刷机精灵,使用其工具中的adb命令行;2.输入adb命令时记得切换到英文;3.apps后面的文件名,可以在手机上打开,然后去设置中的正在运行的程序中查看,或者下载安装文件名查看器查看 )

adb shell am 的用法

C:\Users\Administrator>adb shell am

usage: am [subcommand] [options]

start an Activity: am start [-D] [-W]

-D: enable debugging

-W: wait for launch to complete

start a Service: am startservice

send a broadcast Intent: am broadcast

start an Instrumentation: am instrument [flags]

-r: print raw results (otherwise decode REPORT_KEY_STREAMRESULT)

-e : set argument to

-p : write profiling data to

-w: wait for instrumentation to finish before returning

start profiling: am profile start

stop profiling: am profile stop

start monitoring: am monitor [--gdb ]

--gdb: start gdbserv on the given port at crash/ANR

specifications include these flags:

[-a ] [-d ] [-t ]

[-c [-c ] ...]

[-e|--es ...]

[--esn ...]

[--ez ...]

[-e|--ei ...]

[-n ] [-f ]

[--grant-read-uri-permission] [--grant-write-uri-permission]

[--debug-log-resolution]

[--activity-brought-to-front] [--activity-clear-top]

[--activity-clear-when-task-reset] [--activity-exclude-from-recents]

[--activity-launched-from-history] [--activity-multiple-task]

[--activity-no-animation] [--activity-no-history]

[--activity-no-user-action] [--activity-previous-is-top]

[--activity-reorder-to-front] [--activity-reset-task-if-needed]

[--activity-single-top]

[--receiver-registered-only] [--receiver-replace-pending]

[]

使用实例:

如启动一个 Activity:

格式:

adb shell am start -n 包名/包名+类名(-n 类名,-a action,-d date,-m MIME-TYPE,-c category,-e 扩展数据,等)。

实例1:

C:\Users\Administrator>adb shell am start -n com.android.camera/.Camera

Starting: Intent { cmp=com.android.camera/.Camera }

实例2:(带extra 的 intent)

C:\Users\Administrator>adb shell am start -n com.android.camera/.Camera -e abc hello

Starting: Intent { cmp=com.android.camera/.Camera (has extras) }

其中 extra 的 key 为 abc ,value 为字串 "hello"

还可以发送命令模拟手机低电环境:

实例:

adb shell am broadcast -a android.intent.action.BATTERY_CHANGED --ei "level" 3 --ei "scale" 100

ANDROID: 设置显示窗口的SIZE和DENSITY

Android系统中有一个wm命令,可以设置显示窗口的尺寸(重新设置屏幕的罗辑分辩率)和屏幕的dpi。

设置显示窗口的尺寸

$ adb shell wm size 540x960

显示窗口的尺寸可以比屏幕的物理分辨率大,也可以比它小。重置用如下命令:

$ adb shell wm size reset

设置完之后,你会发现SurfaceFlinger中的Layer的尺寸也发生的变化。

以Nexus4为例,原来Live Wallpaper: PhaseBeam Layer的尺寸为768×1280:

$ adb shell dumpsys SurfaceFlinger

...

+ Layer 0xb7bbf3b0 (com.android.phasebeam.PhaseBeamWallpaper)

Region transparentRegion (this=0xb7bbf510, count=1)

[ 0, 0, 0, 0]

Region visibleRegion (this=0xb7bbf3b8, count=1)

[ 0, 50, 768, 1184]

layerStack= 0, z= 21000, pos=(0,0), size=( 768,1280), crop=( 0, 50, 768,1184), isOpaque=1, invalidate=0, alpha=0xff, flags=0x00000002, tr=[1.00, 0.00][0.00, 1.00]

client=0xb7bad728

format= 2, activeBuffer=[ 768x1280: 768, 3], queued-frames=0, mRefreshPending=0

mTexName=10 mCurrentTexture=0

mCurrentCrop=[0,0,0,0] mCurrentTransform=0

mAbandoned=0

-BufferQueue mMaxAcquiredBufferCount=1, mDequeueBufferCannotBlock=0, default-size=[768x1280], default-format=2, transform-hint=00, FIFO(0)={}

>[00:0xb7bbef08] state=ACQUIRED, 0xb7b18260 [ 768x1280: 768, 3]

[01:0xb7baf328] state=FREE , 0xb7badaa8 [ 768x1280: 768, 3]

[02:0xb7b1a5d0] state=FREE , 0xb7bad9a0 [ 768x1280: 768, 3]

...

将显示窗口的尺寸设为1080×1920之后:

$ adb shell dumpsys SurfaceFlinger

...

+ Layer 0xb7d596b8 (com.android.phasebeam.PhaseBeamWallpaper)

Region transparentRegion (this=0xb7d59818, count=1)

[ 0, 0, 0, 0]

Region visibleRegion (this=0xb7d596c0, count=1)

[ 0, 50, 1080, 1824]

layerStack= 0, z= 21000, pos=(0,0), size=(1080,1920), crop=( 0, 50,1080,1824), isOpaque=1, invalidate=0, alpha=0xff, flags=0x00000002, tr=[1.00, 0.00][0.00, 1.00]

client=0xb7dbf270

format= 2, activeBuffer=[1080x1920:1152, 3], queued-frames=0, mRefreshPending=0

mTexName=10 mCurrentTexture=2

mCurrentCrop=[0,0,0,0] mCurrentTransform=0

mAbandoned=0

-BufferQueue mMaxAcquiredBufferCount=1, mDequeueBufferCannotBlock=0, default-size=[1080x1920], default-format=2, transform-hint=00, FIFO(0)={}

[00:0xb7dd1fb0] state=FREE , 0xb7dd0048 [1080x1920:1152, 3]

[01:0xb7d5c2c8] state=FREE , 0xb7d39ca8 [1080x1920:1152, 3]

>[02:0xb7d1d578] state=ACQUIRED, 0xb7d5cb18 [1080x1920:1152, 3]

...

可以想象得到,系统把这个layer对应的窗口当成了一个1080p屏幕来布局和绘制了。

设置屏幕的dpi

$ adb shell wm density 320

Android 将实际屏幕尺寸和密度的范围 分为:

1.四种通用尺寸:小、正常、 大 和超大

2.六种通用的密度:

ldpi(低)~120dpi

mdpi(中)~160dpi

hdpi(高)~240dpi

xhdpi(超高)~320dpi

xxhdpi(超超高)~480dpi

xxxhdpi(超超超高)~640dpi

5c2bf91b1ff8

常用的dpi有160(mdpi), 240(hdpi), 320(xhdpi), 480(xxhdpi)。重置可用如下命令:

$ adb shell wm density reset

如何实现 ,以设置显示窗口尺寸为例(@android-5.1.1)

首先看一下wm命令如何通知WindowManagerService更新配置:

代码:frameworks/base/cmds/wm/src/com/android/commands/wm/Wm.java

public class Wm extends BaseCommand {

...

public void onRun() throws Exception {

mWm = IWindowManager.Stub.asInterface(ServiceManager.checkService(

Context.WINDOW_SERVICE));

if (mWm == null) {

System.err.println(NO_SYSTEM_ERROR_CODE);

throw new AndroidException("Can't connect to window manager; is the system running?");

}

String op = nextArgRequired();

if (op.equals("size")) {

runDisplaySize();

} else if (op.equals("density")) {

runDisplayDensity();

} else if (op.equals("overscan")) {

runDisplayOverscan();

} else {

showError("Error: unknown command '" + op + "'");

return;

}

}

...

private void runDisplaySize() throws Exception {

String size = nextArg();

int w, h;

if (size == null) {

Point initialSize = new Point();

Point baseSize = new Point();

try {

mWm.getInitialDisplaySize(Display.DEFAULT_DISPLAY, initialSize);

mWm.getBaseDisplaySize(Display.DEFAULT_DISPLAY, baseSize);

System.out.println("Physical size: " + initialSize.x + "x" + initialSize.y);

if (!initialSize.equals(baseSize)) {

System.out.println("Override size: " + baseSize.x + "x" + baseSize.y);

}

} catch (RemoteException e) {

}

return;

} else if ("reset".equals(size)) {

w = h = -1;

} else {

int div = size.indexOf('x');

if (div <= 0 || div >= (size.length()-1)) {

System.err.println("Error: bad size " + size);

return;

}

String wstr = size.substring(0, div);

String hstr = size.substring(div+1);

try {

w = Integer.parseInt(wstr);

h = Integer.parseInt(hstr);

} catch (NumberFormatException e) {

System.err.println("Error: bad number " + e);

return;

}

}

try {

if (w >= 0 && h >= 0) {

// TODO(multidisplay): For now Configuration only applies to main screen.

mWm.setForcedDisplaySize(Display.DEFAULT_DISPLAY, w, h);

} else {

mWm.clearForcedDisplaySize(Display.DEFAULT_DISPLAY);

}

} catch (RemoteException e) {

}

}

...

}

先获取WindowManagerService再调用它的setForcedDisplaySize()方法。

代码:frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java

public class WindowManagerService extends IWindowManager.Stub

implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {

...

@Override

public void setForcedDisplaySize(int displayId, int width, int height) {

if (mContext.checkCallingOrSelfPermission(

android.Manifest.permission.WRITE_SECURE_SETTINGS) !=

PackageManager.PERMISSION_GRANTED) {

throw new SecurityException("Must hold permission " +

android.Manifest.permission.WRITE_SECURE_SETTINGS);

}

if (displayId != Display.DEFAULT_DISPLAY) {

throw new IllegalArgumentException("Can only set the default display");

}

final long ident = Binder.clearCallingIdentity();

try {

synchronized(mWindowMap) {

// Set some sort of reasonable bounds on the size of the display that we

// will try to emulate.

final int MIN_WIDTH = 200;

final int MIN_HEIGHT = 200;

final int MAX_SCALE = 2;

final DisplayContent displayContent = getDisplayContentLocked(displayId);

if (displayContent != null) {

width = Math.min(Math.max(width, MIN_WIDTH),

displayContent.mInitialDisplayWidth * MAX_SCALE);

height = Math.min(Math.max(height, MIN_HEIGHT),

displayContent.mInitialDisplayHeight * MAX_SCALE);

setForcedDisplaySizeLocked(displayContent, width, height);

Settings.Global.putString(mContext.getContentResolver(),

Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height);

}

}

} finally {

Binder.restoreCallingIdentity(ident);

}

}

...

// displayContent must not be null

private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) {

Slog.i(TAG, "Using new display size: " + width + "x" + height);

synchronized(displayContent.mDisplaySizeLock) {

displayContent.mBaseDisplayWidth = width;

displayContent.mBaseDisplayHeight = height;

}

reconfigureDisplayLocked(displayContent);

}

...

// displayContent must not be null

private void reconfigureDisplayLocked(DisplayContent displayContent) {

// TODO: Multidisplay: for now only use with default display.

configureDisplayPolicyLocked(displayContent);

displayContent.layoutNeeded = true;

boolean configChanged = updateOrientationFromAppTokensLocked(false);

mTempConfiguration.setToDefaults();

mTempConfiguration.fontScale = mCurConfiguration.fontScale;

if (computeScreenConfigurationLocked(mTempConfiguration)) {

if (mCurConfiguration.diff(mTempConfiguration) != 0) {

configChanged = true;

}

}

if (configChanged) {

mWaitingForConfig = true;

startFreezingDisplayLocked(false, 0, 0);

mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);

}

performLayoutAndPlaceSurfacesLocked();

}

...

}

setForcedDisplaySize()->setForcedDisplaySizeLocked()->reconfigureDisplayLocked()->SEND_NEW_CONFIGURATION

这里可以看到可以设置的屏幕窗口最小为(200,200),最大小显示屏分辨率的两倍。

而WindowManagerService又是如何通知DisplayManagerService更新配置:

WindowsManagerService$H.handleMessage(SEND_NEW_CONFIGURATION)

->WindowManagerService.sendNewConfiguration()

->ActivityManagerService.updateConfiguration() x2

->WindowManagerService.setNewConfiguration()

->WindowManagerService.performLayoutAndPlaceSurfacesLocked()

->WindowManagerService.performLayoutAndPlaceSurfaceLockedLoop()

->WindowManagerService.performLayoutAndPlaceSurfaceLockedInner()

->DisplayManagerService$LocalService.performTraversalInTransactionFromWindowManager()

->DisplayManagerService.access$4200()

->DisplayManagerService.performTraversalInTransactionFromWindowManagerInternal()

->DisplayManagerService.performTraversalInTransactionLocked()

->DisplayManagerService.configureDisplayInTransactionLocked()

->LogicalDisplay.configureDisplayInTransactionLocked()

到这里就会去设置layer stack的尺寸和在屏幕上的位置:

final class LogicalDisplay {

...

/**

* Applies the layer stack and transformation to the given display device

* so that it shows the contents of this logical display.

*

* We know that the given display device is only ever showing the contents of

* a single logical display, so this method is expected to blow away all of its

* transformation properties to make it happen regardless of what the

* display device was previously showing.

*

* The caller must have an open Surface transaction.

*

* The display device may not be the primary display device, in the case

* where the display is being mirrored.

*

* @param device The display device to modify.

* @param isBlanked True if the device is being blanked.

*/

public void configureDisplayInTransactionLocked(DisplayDevice device,

boolean isBlanked) {

final DisplayInfo displayInfo = getDisplayInfoLocked();

final DisplayDeviceInfo displayDeviceInfo = device.getDisplayDeviceInfoLocked();

// Set the layer stack.

device.setLayerStackInTransactionLocked(isBlanked ? BLANK_LAYER_STACK : mLayerStack);

// Set the refresh rate

device.requestRefreshRateLocked(mRequestedRefreshRate);

// Set the viewport.

// This is the area of the logical display that we intend to show on the

// display device. For now, it is always the full size of the logical display.

mTempLayerStackRect.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight);

// Set the orientation.

// The orientation specifies how the physical coordinate system of the display

// is rotated when the contents of the logical display are rendered.

int orientation = Surface.ROTATION_0;

if ((displayDeviceInfo.flags & DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT) != 0) {

orientation = displayInfo.rotation;

}

// Apply the physical rotation of the display device itself.

orientation = (orientation + displayDeviceInfo.rotation) % 4;

// Set the frame.

// The frame specifies the rotated physical coordinates into which the viewport

// is mapped. We need to take care to preserve the aspect ratio of the viewport.

// Currently we maximize the area to fill the display, but we could try to be

// more clever and match resolutions.

boolean rotated = (orientation == Surface.ROTATION_90

|| orientation == Surface.ROTATION_270);

int physWidth = rotated ? displayDeviceInfo.height : displayDeviceInfo.width;

int physHeight = rotated ? displayDeviceInfo.width : displayDeviceInfo.height;

// Determine whether the width or height is more constrained to be scaled.

// physWidth / displayInfo.logicalWidth => letter box

// or physHeight / displayInfo.logicalHeight => pillar box

//

// We avoid a division (and possible floating point imprecision) here by

// multiplying the fractions by the product of their denominators before

// comparing them.

int displayRectWidth, displayRectHeight;

if (physWidth * displayInfo.logicalHeight

< physHeight * displayInfo.logicalWidth) {

// Letter box.

displayRectWidth = physWidth;

displayRectHeight = displayInfo.logicalHeight * physWidth / displayInfo.logicalWidth;

} else {

// Pillar box.

displayRectWidth = displayInfo.logicalWidth * physHeight / displayInfo.logicalHeight;

displayRectHeight = physHeight;

}

int displayRectTop = (physHeight - displayRectHeight) / 2;

int displayRectLeft = (physWidth - displayRectWidth) / 2;

mTempDisplayRect.set(displayRectLeft, displayRectTop,

displayRectLeft + displayRectWidth, displayRectTop + displayRectHeight);

device.setProjectionInTransactionLocked(orientation, mTempLayerStackRect, mTempDisplayRect);

}

...

}

->DisplayDevice.setProjectionInTransactionLocked()

通知SurfaceFlinger:

abstract class DisplayDevice {

...

/**

* Sets the display projection while in a transaction.

*

* @param orientation defines the display's orientation

* @param layerStackRect defines which area of the window manager coordinate

* space will be used

* @param displayRect defines where on the display will layerStackRect be

* mapped to. displayRect is specified post-orientation, that is

* it uses the orientation seen by the end-user

*/

public final void setProjectionInTransactionLocked(int orientation,

Rect layerStackRect, Rect displayRect) {

if (mCurrentOrientation != orientation

|| mCurrentLayerStackRect == null

|| !mCurrentLayerStackRect.equals(layerStackRect)

|| mCurrentDisplayRect == null

|| !mCurrentDisplayRect.equals(displayRect)) {

mCurrentOrientation = orientation;

if (mCurrentLayerStackRect == null) {

mCurrentLayerStackRect = new Rect();

}

mCurrentLayerStackRect.set(layerStackRect);

if (mCurrentDisplayRect == null) {

mCurrentDisplayRect = new Rect();

}

mCurrentDisplayRect.set(displayRect);

SurfaceControl.setDisplayProjection(mDisplayToken,

orientation, layerStackRect, displayRect);

}

}

...

}

最后,SurfaceFlinger就会跟据这些信息对Layer进行合成,显示在屏幕上。

代码:frameworks/native/services/surfaceflinger/DisplayDevice.cpp

void DisplayDevice::setProjection(int orientation,

const Rect& newViewport, const Rect& newFrame) {

Rect viewport(newViewport);

Rect frame(newFrame);

const int w = mDisplayWidth;

const int h = mDisplayHeight;

Transform R;

DisplayDevice::orientationToTransfrom(orientation, w, h, &R);

if (!frame.isValid()) {

// the destination frame can be invalid if it has never been set,

// in that case we assume the whole display frame.

frame = Rect(w, h);

}

if (viewport.isEmpty()) {

// viewport can be invalid if it has never been set, in that case

// we assume the whole display size.

// it's also invalid to have an empty viewport, so we handle that

// case in the same way.

viewport = Rect(w, h);

if (R.getOrientation() & Transform::ROT_90) {

// viewport is always specified in the logical orientation

// of the display (ie: post-rotation).

swap(viewport.right, viewport.bottom);

}

}

dirtyRegion.set(getBounds());

Transform TL, TP, S;

float src_width = viewport.width();

float src_height = viewport.height();

float dst_width = frame.width();

float dst_height = frame.height();

if (src_width != dst_width || src_height != dst_height) {

float sx = dst_width / src_width;

float sy = dst_height / src_height;

S.set(sx, 0, 0, sy);

}

float src_x = viewport.left;

float src_y = viewport.top;

float dst_x = frame.left;

float dst_y = frame.top;

TL.set(-src_x, -src_y);

TP.set(dst_x, dst_y);

// The viewport and frame are both in the logical orientation.

// Apply the logical translation, scale to physical size, apply the

// physical translation and finally rotate to the physical orientation.

mGlobalTransform = R * TP * S * TL;

const uint8_t type = mGlobalTransform.getType();

mNeedsFiltering = (!mGlobalTransform.preserveRects() ||

(type >= Transform::SCALE));

mScissor = mGlobalTransform.transform(viewport);

if (mScissor.isEmpty()) {

mScissor = getBounds();

}

mOrientation = orientation;

mViewport = viewport;

mFrame = frame;

}

aapt命令获取apk详细信息(包名、版本号、版本名称、兼容api级别、启动Activity等)

找到sdk的根目录,然后找到build-tools文件夹,然后会看到一些build-tools的版本号,随便点开一个,就可以看到aapt

5c2bf91b1ff8

获取apk的详细信息

aapt dump badging app-debug.apk

5c2bf91b1ff8

5c2bf91b1ff8

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值