声明

  • Android系统中包含很多命令行工具,包括一些Linux继承来的工具,也有不少Android系统特有工具/命令,此篇介绍一些比较重要的工具/命令。
  • 这些命令来自Android框架层(源码位置:frameworks/native/cmds、frameworks/base/cmds、frameworks/av/cmds)
  • 此篇中涉及代码及命令来自一台装有LineageOS 14.1的Nexus5手机。
  • 此篇参考了一些书籍及论文,仅供学习使用。只介绍大概理论,不深究,就足够用了。

1 通用工具

1.1 service

service 命令允许与任意在服务管理器中注册了的系统服务进行交互:

hammerhead:/ # service
Usage: service [-h|-?]service listservice check SERVICEservice call SERVICE CODE [i32 N | i64 N | f N | d N | s16 STR ] ...
Options:i32: Write the 32-bit integer N into the send parcel.i64: Write the 64-bit integer N into the send parcel.f:   Write the 32-bit single-precision number N into the send parcel.d:   Write the 64-bit double-precision number N into the send parcel.s16: Write the UTF-16 string STR into the send parcel.

该命令能用于查询,同样也能用于调用来自系统服务的方法。

hammerhead:/ # service list
Found 128 services:
0       sip: [android.net.sip.ISipService]
1       nfc: [android.nfc.INfcAdapter]
2       carrier_config: [com.android.internal.telephony.ICarrierConfigLoader]
3       phone: [com.android.internal.telephony.ITelephony]
4       isms: [com.android.internal.telephony.ISms]
5       iphonesubinfo: [com.android.internal.telephony.IPhoneSubInfo]
6       simphonebook: [com.android.internal.telephony.IIccPhoneBook]
7       telecom: [com.android.internal.telecom.ITelecomService]
8       isub: [com.android.internal.telephony.ISub]
9       cmaudio: [cyanogenmod.media.ICMAudioService]
10      contexthub_service: [android.hardware.location.IContextHubService]
11      netd_listener: [android.net.metrics.INetdEventListener]
......
22      imms: [com.android.internal.telephony.IMms]
23      media_projection: [android.media.projection.IMediaProjectionManager]
24      launcherapps: [android.content.pm.ILauncherApps]
25      shortcut: [android.content.pm.IShortcutService]
26      trust: [android.app.trust.ITrustManager]
27      media_router: [android.media.IMediaRouterService]
28      media_session: [android.media.session.ISessionManager]
29      restrictions: [android.content.IRestrictionsManager]
30      print: [android.print.IPrintManager]
31      graphicsstats: [android.view.IGraphicsStats]
32        statusbar: [com.android.internal.statusbar.IStatusBarService]
......

  接口名称设置在方括号内,允许你浏览 AOSP源文件来找到匹配的定义接口的.aidl文件。也可以使用如下的命令检测一项给定的服务是否存在:

hammerhead:/ # service check power
Service power: found

  可以使用 service call 去直接地调用系统服务的 Binder exposed (暴露绑定) 方法。首先需要了解frameworks/base/core/java/com/android/internal/statusbar/IStatusBarService.aidl中定义了IStatusBarService 接口。

/** @hide */
interface IStatusBarService
{void expandNotificationsPanel();void collapsePanels();void disable(int what, IBinder token, String pkg);void disableForUser(int what, IBinder token, String pkg, int userId);void disable2(int what, IBinder token, String pkg);void disable2ForUser(int what, IBinder token, String pkg, int userId);void setIcon(String slot, String iconPackage, int iconId, int iconLevel, String contentDescription);void setIconVisibility(String slot, boolean visible);......
}

  请注意,service call 实际上需要一个方法的代码,而不仅仅是一个方法的名字。为了找到与接口中定义的方法名称匹配的代码,你需要看一下基于接口定义的aidI工具生成的代码。比如 IStatusBarService.java中的有关摘录,此文件在:out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/com/android/internal/statusbar/IStatusBarService.java

static final int TRANSACTION_expandNotificationsPanel = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_collapsePanels = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
static final int TRANSACTION_disable = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
static final int TRANSACTION_disableForUser = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3);
static final int TRANSACTION_disable2 = (android.os.IBinder.FIRST_CALL_TRANSACTION + 4);
static final int TRANSACTION_disable2ForUser = (android.os.IBinder.FIRST_CALL_TRANSACTION + 5);
......

同时注意,对于整型变量FIRST_CALL_TRANSACTION 在frameworks/base/core/java/android/os/IBinder.java文件中有如下定义:

int FIRST_CALL_TRANSACTION  = 0x00000001;

因此,expandNotificationsPanel()的代码是1,collapsePanels()的代码是2。如下命令将引起状态栏的扩展:

service call statusbar 1

  这是一种非常简单的情况,其作用相当明显且调用的方法不带任何参数。在其他情况下,需要更仔细地查看系统服务的 API及理解设定的参数含义。另外,记住系统服务的接口不一定通过.aidl文件展示。在某些情况下,如活动管理,接口定义是直接通过硬编码在常规的Java 文件中实现而不是自动生成。在基于C的系统服务的情况下Binder的编组和解组都是直接在C 语言代码中完成。

1.2 dumpsys

其可用于查询系统服务的内部状态。事实上,每一个系统服务实现了一个dump()方法,并且可以通过 dumpsys 命令进行查询:

hammerhead:/ # dumpsys --help
usage: dumpsysTo dump all services.
or:dumpsys [-t TIMEOUT] [--help | -l | --skip SERVICES | SERVICE [ARGS]]--help: shows this help-l: only list services, do not dump them-t TIMEOUT: TIMEOUT to use in seconds instead of default 10 seconds--skip SERVICES: dumps all services but SERVICES (comma-separated list)SERVICE [ARGS]: dumps only service SERVICE, optionally passing ARGS to it

默认情况下,如果没有系统服务名称作为参数,dumpsys 将先输出系统服务列表,然后解析它们的状态:

hammerhead:/ # dumpsys
Currently running services:DockObserverSurfaceFlingeraccessibilityaccountactivityalarmandroid.security.keystoreandroid.service.gatekeeper.IGateKeeperServiceappopsappwidgetassetatlasaudiobackupbatterybatterypropertiesbatterystatsbluetooth_managercarrier_configclipboardcmaudiocmhardwarecmlivedisplaycmperformancecmstatusbarcmtelephonymanagercmweathercommontime_managementconnectivityconnectivity_metrics_loggerconnmetricsconsumer_ircontentcontexthub_servicecountry_detectorcpuinfodbinfodevice_policydeviceidledevicestoragemonitordiskstatsdisplaydisplay.qservicedreamsdrm.drmManagerdropboxethernetgfxinfogpugraphicsstatshardware_propertiesimmsinputinput_methodiphonesubinfoismsisubjobschedulerlauncherappslocationlock_settingsmedia.audio_flingermedia.audio_policymedia.cameramedia.camera.proxymedia.codecmedia.drmmedia.extractormedia.playermedia.radiomedia.resource_managermedia.sound_trigger_hwmedia_projectionmedia_routermedia_sessionmeminfomidimountnetdnetd_listenernetpolicynetstatsnetwork_managementnetwork_scorenetwork_time_update_servicenfcnotificationotadexoptpackagepermissionphonepinnerpowerprintprocessinfoprocstatsprofilerecoveryrestrictionsrttmanagersamplingprofilerscheduling_policysearchsensorserviceserialservicediscoveryshortcutsimphonebooksipsoundtriggerstatusbartelecomtelephony.registrytextservicestrustuimodeupdatelockusagestatsusbuservibratorvoiceinteractionvrmanagerwallpaperwebviewupdatewifiwifip2pwifiscannerwindow
-------------------------------------------------------------------------------
DUMP OF SERVICE DockObserver:
Current Dock Observer Service state:reported state: 0previous state: 0actual state: 0
--------- 0.001s was the duration of dumpsys DockObserver
-------------------------------------------------------------------------------
DUMP OF SERVICE SurfaceFlinger:
Build configuration: [sf] [libui] [libgui]
Sync configuration: [using: EGL_ANDROID_native_fence_sync EGL_KHR_wait_sync]
DispSync configuration: app phase 7500000 ns, sf phase 5000000 ns, present offset 0 ns (refresh 16666667 ns)Static screen stats:< 1 frames: 41.227 s (0.2%)< 2 frames: 47.859 s (0.2%)< 3 frames: 4.114 s (0.0%)< 4 frames: 2.872 s (0.0%)< 5 frames: 1.647 s (0.0%)< 6 frames: 2.513 s (0.0%)< 7 frames: 1.409 s (0.0%)7+ frames: 20134.619 s (99.5%)Buffering stats:[Layer name] <Active time> <Two buffer> <Double buffered> <Triple buffered>[com.android.deskclock/com.android.deskclock.DeskClock] 33.40 0.394 0.440 0.560[BootAnimation] 16.25 0.000 0.000 1.000[com.android.settings/com.android.settings.Settings$DevelopmentSettingsActivity] 10.12 0.192 0.551 0.449[ColorFade] 6.19 0.544 0.620 0.380[com.android.settings/com.android.settings.FallbackHome] 5.88 0.000 0.000 1.000[StatusBar] 4.64 0.249 0.336 0.664[NavigationBar] 3.02 0.259 0.460 0.540[com.android.settings/com.android.settings.Settings] 2.09 0.000 0.140 0.860[com.cyanogenmod.trebuchet/com.android.launcher3.Launcher] 1.63 0.000 0.164 0.836[com.android.systemui/com.android.systemui.usb.UsbDebuggingActivity] 1.18 1.000 1.000 0.000Visible layers (count = 11)
+ Layer 0xb688e000 (com.android.systemui.ImageWallpaper)Region transparentRegion (this=0xb688e240, count=1)[  0,   0,   0,   0]Region visibleRegion (this=0xb688e008, count=1)[1080,   0, 2160, 1920]Region surfaceDamageRegion (this=0xb688e044, count=1)[  0,   0,   0,   0]layerStack=   0, z=    21000, pos=(0,0), size=(2160,1920), crop=(   0,   0,2160,1920), finalCrop=(   0,   0,  -1,  -1), isOpaque=1, invalidate=0, alpha=0xff, blur=0xff, flags=0x00000002, tr=[1.00, 0.00][0.00, 1.00]client=0xb5c91a40format= 2, activeBuffer=[2160x1920:2176,  3], queued-frames=0, mRefreshPending=0mTexName=5 mCurrentTexture=-1mCurrentCrop=[0,0,0,0] mCurrentTransform=0mAbandoned=0-BufferQueue mMaxAcquiredBufferCount=1, mMaxDequeuedBufferCount=2, mDequeueBufferCannotBlock=0 mAsyncMode=0, default-size=[2160x1920], default-format=2, transform-hint=00, FIFO(0)={}[00:0x0] state=FREE[01:0x0] state=FREE[02:0x0] state=FREE
+ LayerDim 0xb5178400 (animation background stackId=1)Region transparentRegion (this=0xb5178640, count=1)
......

  显然,其输出是非常详细的,最重要的是,它需要你理解相应的系统服务的内部情况。如果你实现你自己的系统服务,能够查询其在运行时的状态是至关重要的。当然,如果你对解析系统服务状态不是很感兴趣,你只需要提供你想获取信息的特定服务的名称作为 dumpsys命令的一个参数:

hammerhead:/ # dumpsys power
...输出省略...

1.3 dumpstate

在某些情况下,你想要做的是获取整个系统的一个快照,而不仅仅只是系统服务,可以用dumpstate命令。

hammerhead:/ # dumpstate -h
begin
dumpstate id: 1
Dumpstate command line: dumpstate -h
usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file [-d] [-p] [-t][-z] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]-h: display this help message-b: play sound file instead of vibrate, at beginning of job-e: play sound file instead of vibrate, at end of job-o: write to file (instead of stdout)-d: append date to filename (requires -o)-p: capture screenshot to filename.png (requires -o)-t: only captures telephony sections-z: generate zipped file (requires -o)-s: write output to control socket (for init)-S: write file location to control socket (for init; requires -o and -z)  -q: disable vibrate-B: send broadcast when finished (requires -o)-P: send broadcast when started and update system properties on progress (requires -o and -B)-R: take bugreport in remote mode (requires -o, -z, -d and -B, shouldn't be used with -P)-V: sets the bugreport format version (valid values: 1.0)

默认情况下,如果没有系统服务名称作为参数,dumpstate 它可以查询系统的好几个部分来给你提供完整的系统状态的快照。

hammerhead:/ # dumpstate
...输出省略...

在大多数情况下,dumpstate 命令实际上是调用其他的命令如 logcat、dumpsys、ps 来检索它的信息同样其输出信息非常冗长。

1.4 rawbu

在一些情况下,你可能想要备份和恢复 /data 目录下的内容。你可以使用 rawbu 命令:

hammerhead:/ # rawbu help
Usage: rawbu COMMAND [options] [backup-file-path]
commands are:help            Show this help text.backup          Perform a backup of /data.restore         Perform a restore of /data.
options include:-h              Show this help text.-a              Backup all files.backup-file-path Defaults to /sdcard/backup.dat .On devices that emulate the sdcard, you will need toexplicitly specify the directory it is mapped to,to avoid recursive backup or deletion of the backup fileduring restore.Eg. /data/media/0/backup.datThe rawbu command allows you to perform low-level
backup and restore of the /data partition.  This is
where all user data is kept, allowing for a fairly
complete restore of a device's state.  Note that
because this is low-level, it will only work across
builds of the same (or very similar) device software.

用它创建一个备份:

rawbu backup /sdcard/backup.dat

  该命令做的第一件事就是停止 Zygote,从而停止所有的系统服务。然后创建一个进程来从 /data 复制所有的数据,通过重启 Zygote 来结束复制,一旦数据阻塞,你能在稍后还原它:

rawbu restore /sdcard/backup.dat

显然,这个命令的输出意味着这是一个弱操作,同时你也应该意识到结果会变动。

2 特定服务工具

  正如我们前面看到的,已经存在许多的系统服务。通常情况下,使用这些系统服务需要写代码来与其 Binder-exposed 的API以某种方式进行交互。然而,在某些情况下,AOSP 包括命令行实用工具来直接与某些系统服务进行交互。这些工具是非常强大,允许我们通过命令行直接进入 Android 的功能。

2.1 am

hammerhead:/ # amusage: am [subcommand] [options]
usage: am start [-D] [-N] [-W] [-P <FILE>] [--start-profiler <FILE>][--sampling INTERVAL] [-R COUNT] [-S][--track-allocation] [--user <USER_ID> | current] <INTENT>am startservice [--user <USER_ID> | current] <INTENT>am stopservice [--user <USER_ID> | current] <INTENT>am force-stop [--user <USER_ID> | all | current] <PACKAGE>am kill [--user <USER_ID> | all | current] <PACKAGE>am kill-allam broadcast [--user <USER_ID> | all | current] <INTENT>am instrument [-r] [-e <NAME> <VALUE>] [-p <FILE>] [-w][--user <USER_ID> | current][--no-window-animation] [--abi <ABI>] <COMPONENT>am profile start [--user <USER_ID> current] [--sampling INTERVAL] <PROCESS> <FILE>am profile stop [--user <USER_ID> current] [<PROCESS>]am dumpheap [--user <USER_ID> current] [-n] <PROCESS> <FILE>am set-debug-app [-w] [--persistent] <PACKAGE>am clear-debug-appam set-watch-heap <PROCESS> <MEM-LIMIT>am clear-watch-heapam bug-report [--progress | --telephony]am monitor [--gdb <port>]am hang [--allow-restart]am restartam idle-maintenanceam screen-compat [on|off] <PACKAGE>am package-importance <PACKAGE>am to-uri [INTENT]am to-intent-uri [INTENT]am to-app-uri [INTENT]am switch-user <USER_ID>am start-user <USER_ID>am unlock-user <USER_ID> [TOKEN_HEX]am stop-user [-w] [-f] <USER_ID>am stack start <DISPLAY_ID> <INTENT>am stack movetask <TASK_ID> <STACK_ID> [true|false]am stack resize <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>am stack resize-animated <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>am stack resize-docked-stack <LEFT,TOP,RIGHT,BOTTOM> [<TASK_LEFT,TASK_TOP,TASK_RIGHT,TASK_BOTTOM>]am stack size-docked-stack-test: <STEP_SIZE> <l|t|r|b> [DELAY_MS]am stack move-top-activity-to-pinned-stack: <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>am stack positiontask <TASK_ID> <STACK_ID> <POSITION>am stack listam stack info <STACK_ID>am stack remove <STACK_ID>am task lock <TASK_ID>am task lock stopam task resizeable <TASK_ID> [0 (unresizeable) | 1 (crop_windows) | 2 (resizeable) | 3 (resizeable_and_pipable)]am task resize <TASK_ID> <LEFT,TOP,RIGHT,BOTTOM>am task drag-task-test <TASK_ID> <STEP_SIZE> [DELAY_MS]am task size-task-test <TASK_ID> <STEP_SIZE> [DELAY_MS]am get-configam suppress-resize-config-changes <true|false>am set-inactive [--user <USER_ID>] <PACKAGE> true|falseam get-inactive [--user <USER_ID>] <PACKAGE>am send-trim-memory [--user <USER_ID>] <PROCESS>[HIDDEN|RUNNING_MODERATE|BACKGROUND|RUNNING_LOW|MODERATE|RUNNING_CRITICAL|COMPLETE]am get-current-useram start: start an Activity.  Options are:-D: enable debugging-N: enable native debugging-W: wait for launch to complete--start-profiler <FILE>: start profiler and send results to <FILE>--sampling INTERVAL: use sample profiling with INTERVAL microsecondsbetween samples (use with --start-profiler)-P <FILE>: like above, but profiling stops when app goes idle-R: repeat the activity launch <COUNT> times.  Prior to each repeat,the top activity will be finished.-S: force stop the target app before starting the activity--track-allocation: enable tracking of object allocations--user <USER_ID> | current: Specify which user to run as; if notspecified then run as the current user.--stack <STACK_ID>: Specify into which stack should the activity be put.
am startservice: start a Service.  Options are:--user <USER_ID> | current: Specify which user to run as; if notspecified then run as the current user.am stopservice: stop a Service.  Options are:--user <USER_ID> | current: Specify which user to run as; if notspecified then run as the current user.am force-stop: force stop everything associated with <PACKAGE>.--user <USER_ID> | all | current: Specify user to force stop;all users if not specified.am kill: Kill all processes associated with <PACKAGE>.  Only kills.processes that are safe to kill -- that is, will not impact the userexperience.--user <USER_ID> | all | current: Specify user whose processes to kill;all users if not specified.am kill-all: Kill all background processes.am broadcast: send a broadcast Intent.  Options are:--user <USER_ID> | all | current: Specify which user to send to; if notspecified then send to all users.--receiver-permission <PERMISSION>: Require receiver to hold permission.am instrument: start an Instrumentation.  Typically this target <COMPONENT>is the form <TEST_PACKAGE>/<RUNNER_CLASS> or only <TEST_PACKAGE> if thereis only one instrumentation.  Options are:-r: print raw results (otherwise decode REPORT_KEY_STREAMRESULT).  Use with[-e perf true] to generate raw output for performance measurements.-e <NAME> <VALUE>: set argument <NAME> to <VALUE>.  For test runners acommon form is [-e <testrunner_flag> <value>[,<value>...]].-p <FILE>: write profiling data to <FILE>-w: wait for instrumentation to finish before returning.  Required fortest runners.--user <USER_ID> | current: Specify user instrumentation runs in;current user if not specified.--no-window-animation: turn off window animations while running.--abi <ABI>: Launch the instrumented process with the selected ABI.This assumes that the process supports the selected ABI.am trace-ipc: Trace IPC transactions.start: start tracing IPC transactions.stop: stop tracing IPC transactions and dump the results to file.--dump-file <FILE>: Specify the file the trace should be dumped to.am profile: start and stop profiler on a process.  The given <PROCESS> argumentmay be either a process name or pid.  Options are:--user <USER_ID> | current: When supplying a process name,specify user of process to profile; uses current user if not specified.am dumpheap: dump the heap of a process.  The given <PROCESS> argument maybe either a process name or pid.  Options are:-n: dump native heap instead of managed heap--user <USER_ID> | current: When supplying a process name,specify user of process to dump; uses current user if not specified.am set-debug-app: set application <PACKAGE> to debug.  Options are:-w: wait for debugger when application starts--persistent: retain this valueam clear-debug-app: clear the previously set-debug-app.am set-watch-heap: start monitoring pss size of <PROCESS>, if it is at orabove <HEAP-LIMIT> then a heap dump is collected for the user to reportam clear-watch-heap: clear the previously set-watch-heap.am bug-report: request bug report generation; will launch a notificationwhen done to select where it should be delivered. Options are:--progress: will launch a notification right away to show its progress.--telephony: will dump only telephony sections.am monitor: start monitoring for crashes or ANRs.--gdb: start gdbserv on the given port at crash/ANRam hang: hang the system.--allow-restart: allow watchdog to perform normal system restartam restart: restart the user-space system.am idle-maintenance: perform idle maintenance now.am screen-compat: control screen compatibility mode of <PACKAGE>.am package-importance: print current importance of <PACKAGE>.am to-uri: print the given Intent specification as a URI.am to-intent-uri: print the given Intent specification as an intent: URI.am to-app-uri: print the given Intent specification as an android-app: URI.am switch-user: switch to put USER_ID in the foreground, startingexecution of that user if it is currently stopped.am start-user: start USER_ID in background if it is currently stopped,use switch-user if you want to start the user in foreground.am stop-user: stop execution of USER_ID, not allowing it to run anycode until a later explicit start or switch to it.-w: wait for stop-user to complete.-f: force stop even if there are related users that cannot be stopped.am stack start: start a new activity on <DISPLAY_ID> using <INTENT>.am stack movetask: move <TASK_ID> from its current stack to the top (true) or   bottom (false) of <STACK_ID>.am stack resize: change <STACK_ID> size and position to <LEFT,TOP,RIGHT,BOTTOM>.am stack resize-docked-stack: change docked stack to <LEFT,TOP,RIGHT,BOTTOM>and supplying temporary different task bounds indicated by<TASK_LEFT,TOP,RIGHT,BOTTOM>am stack size-docked-stack-test: test command for sizing docked stack by<STEP_SIZE> increments from the side <l>eft, <t>op, <r>ight, or <b>ottomapplying the optional [DELAY_MS] between each step.am stack move-top-activity-to-pinned-stack: moves the top activity from<STACK_ID> to the pinned stack using <LEFT,TOP,RIGHT,BOTTOM> for thebounds of the pinned stack.am stack positiontask: place <TASK_ID> in <STACK_ID> at <POSITION>
am stack list: list all of the activity stacks and their sizes.am stack info: display the information about activity stack <STACK_ID>.am stack remove: remove stack <STACK_ID>.am task lock: bring <TASK_ID> to the front and don't allow other tasks to run.am task lock stop: end the current task lock.am task resizeable: change resizeable mode of <TASK_ID>.0 (unresizeable) | 1 (crop_windows) | 2 (resizeable) | 3 (resizeable_and_pipable)am task resize: makes sure <TASK_ID> is in a stack with the specified bounds.Forces the task to be resizeable and creates a stack if no existing stackhas the specified bounds.am task drag-task-test: test command for dragging/moving <TASK_ID> by<STEP_SIZE> increments around the screen applying the optional [DELAY_MS]between each step.am task size-task-test: test command for sizing <TASK_ID> by <STEP_SIZE>   increments within the screen applying the optional [DELAY_MS] betweeneach step.am get-config: retrieve the configuration and any recent configurationsof the device.
am suppress-resize-config-changes: suppresses configuration changes due touser resizing an activity/task.am set-inactive: sets the inactive state of an app.am get-inactive: returns the inactive state of an app.am send-trim-memory: send a memory trim event to a <PROCESS>.am get-current-user: returns id of the current foreground user.am supports-multiwindow: returns true if the device supports multiwindow.<INTENT> specifications include these flags and arguments:[-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>][-c <CATEGORY> [-c <CATEGORY>] ...][-e|--es <EXTRA_KEY> <EXTRA_STRING_VALUE> ...][--esn <EXTRA_KEY> ...][--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...][--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...][--el <EXTRA_KEY> <EXTRA_LONG_VALUE> ...][--ef <EXTRA_KEY> <EXTRA_FLOAT_VALUE> ...][--eu <EXTRA_KEY> <EXTRA_URI_VALUE> ...][--ecn <EXTRA_KEY> <EXTRA_COMPONENT_NAME_VALUE>][--eia <EXTRA_KEY> <EXTRA_INT_VALUE>[,<EXTRA_INT_VALUE...]](mutiple extras passed as Integer[])[--eial <EXTRA_KEY> <EXTRA_INT_VALUE>[,<EXTRA_INT_VALUE...]](mutiple extras passed as List<Integer>)[--ela <EXTRA_KEY> <EXTRA_LONG_VALUE>[,<EXTRA_LONG_VALUE...]](mutiple extras passed as Long[])[--elal <EXTRA_KEY> <EXTRA_LONG_VALUE>[,<EXTRA_LONG_VALUE...]](mutiple extras passed as List<Long>)[--efa <EXTRA_KEY> <EXTRA_FLOAT_VALUE>[,<EXTRA_FLOAT_VALUE...]](mutiple extras passed as Float[])[--efal <EXTRA_KEY> <EXTRA_FLOAT_VALUE>[,<EXTRA_FLOAT_VALUE...]](mutiple extras passed as List<Float>)[--esa <EXTRA_KEY> <EXTRA_STRING_VALUE>[,<EXTRA_STRING_VALUE...]](mutiple extras passed as String[]; to embed a comma into a string,escape it using "\,")[--esal <EXTRA_KEY> <EXTRA_STRING_VALUE>[,<EXTRA_STRING_VALUE...]](mutiple extras passed as List<String>; to embed a comma into a string,escape it using "\,")[--f <FLAG>][--grant-read-uri-permission] [--grant-write-uri-permission][--grant-persistable-uri-permission] [--grant-prefix-uri-permission][--debug-log-resolution] [--exclude-stopped-packages][--include-stopped-packages][--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] [--activity-clear-task][--activity-task-on-home][--receiver-registered-only] [--receiver-replace-pending][--receiver-foreground][--selector][<URI> | <PACKAGE> | <COMPONENT>]

  有四种可用的应用程序开发的组件类型:活动、服务、广播接收器和内容提供者。前三个类型的组件是通过意图 (Intent) 激活,am 命令个主要的特点是它拥有直接从命令行发送意图的能力。

am start -a android.intent.action.VIEW -d http://www.baidu.com
am broadcast -a com.test.mxr.TEST_BROADCAST
am start -n com.android.settings/.Settings

am命令实际上是个shell脚本:

#!/system/bin/sh
#
# Script to start "am" on the device, which has a very rudimentary
# shell.
#
base=/system
export CLASSPATH=$base/framework/am.jar
exec app_process $base/bin com.android.commands.am.Am "$@"

  上面这段脚本使用 app_process 来启动 Java 代码实现 am 的功能。命令行里传递的所有的参数实际上传递给了 Java 代码。am profile 命令允许我们生成的数据通过 traceview 命令在主机上进行可视化。am monitor 命令通过活动管理器允许我们监控程序运行。这里例举了一个场景我先启动该命令然后启动几个应用:

hammerhead:/ # am monitor
** Activity starting: com.cyanogenmod.trebuchet
** Activity starting: com.android.dialer
** Activity starting: com.cyanogenmod.trebuchet
** Activity starting: com.android.messaging
** Activity starting: com.cyanogenmod.trebuchet
** Activity starting: org.lineageos.jelly
** Activity starting: com.cyanogenmod.trebuchet

  这种监控能力也将让你捕获ANRS(Application Not Responding,应用程序不响应)。am命令有很强大功能,更多可看它的help信息。

2.2 pm

包管理器,跟活动管理器类似,它拥有它自己的命令行工具。

hammerhead:/ # pm
usage: pm path [--user USER_ID] PACKAGEpm dump PACKAGEpm install [-lrtsfd] [-i PACKAGE] [--user USER_ID] [PATH]pm install-create [-lrtsfdp] [-i PACKAGE] [-S BYTES][--install-location 0/1/2][--force-uuid internal|UUID]pm install-write [-S BYTES] SESSION_ID SPLIT_NAME [PATH]pm install-commit SESSION_IDpm install-abandon SESSION_IDpm uninstall [-k] [--user USER_ID] PACKAGEpm set-installer PACKAGE INSTALLERpm move-package PACKAGE [internal|UUID]pm move-primary-storage [internal|UUID]pm clear [--user USER_ID] PACKAGEpm enable [--user USER_ID] PACKAGE_OR_COMPONENTpm disable [--user USER_ID] PACKAGE_OR_COMPONENTpm disable-user [--user USER_ID] PACKAGE_OR_COMPONENTpm disable-until-used [--user USER_ID] PACKAGE_OR_COMPONENTpm default-state [--user USER_ID] PACKAGE_OR_COMPONENTpm hide [--user USER_ID] PACKAGE_OR_COMPONENTpm unhide [--user USER_ID] PACKAGE_OR_COMPONENTpm grant [--user USER_ID] PACKAGE PERMISSIONpm revoke [--user USER_ID] PACKAGE PERMISSIONpm reset-permissionspm set-app-link [--user USER_ID] PACKAGE {always|ask|never|undefined}pm get-app-link [--user USER_ID] PACKAGEpm set-install-location [0/auto] [1/internal] [2/external]pm get-install-locationpm set-permission-enforced PERMISSION [true|false]pm trim-caches DESIRED_FREE_SPACE [internal|UUID]pm create-user [--profileOf USER_ID] [--managed] [--restricted] [--ephemeral] [--guest] USER_NAMEpm remove-user USER_IDpm get-max-usersNOTE: 'pm list' commands have moved! Run 'adb shell cmd package'to display the new commands.pm path: print the path to the .apk of the given PACKAGE.pm dump: print system state associated with the given PACKAGE.pm install: install a single legacy package
pm install-create: create an install session-l: forward lock application-r: replace existing application-t: allow test packages-i: specify the installer package name-s: install application on sdcard-f: install application on internal flash-d: allow version code downgrade (debuggable packages only)-p: partial application install-g: grant all runtime permissions-S: size in bytes of entire sessionpm install-write: write a package into existing session; path maybe '-' to read from stdin-S: size in bytes of package, required for stdinpm install-commit: perform install of fully staged session
pm install-abandon: abandon sessionpm set-installer: set installer package namepm uninstall: removes a package from the system. Options:-k: keep the data and cache directories around after package removal.pm clear: deletes all data associated with a package.pm enable, disable, disable-user, disable-until-used, default-state:these commands change the enabled state of a given package orcomponent (written as "package/class").pm grant, revoke: these commands either grant or revoke permissionsto apps. The permissions must be declared as used in the app'smanifest, be runtime permissions (protection level dangerous),and the app targeting SDK greater than Lollipop MR1.pm reset-permissions: revert all runtime permissions to their default state.pm get-install-location: returns the current install location.0 [auto]: Let system decide the best location1 [internal]: Install on internal device storage2 [external]: Install on external mediapm set-install-location: changes the default install location.NOTE: this is only intended for debugging; using this can causeapplications to break and other undersireable behavior.0 [auto]: Let system decide the best location1 [internal]: Install on internal device storage2 [external]: Install on external mediapm trim-caches: trim cache files to reach the given free space.pm create-user: create a new user with the given USER_NAME,printing the new user identifier of the user.pm remove-user: remove the user with the given USER_IDENTIFIER,deleting all data associated with that user
#列出系统内已经安装的包
pm list packages
#安装apk
pm install xx.apk
#卸载apk
pm uninstall 包名

pm同样也是启动Java代码的Shell脚本:

#!/system/bin/sh
# Script to start "pm" on the device, which has a very rudimentary
# shell.
#
base=/system
export CLASSPATH=$base/framework/pm.jar
exec app_process $base/bin com.android.commands.pm.Pm "$@"

2.3 svc

svc 有点像瑞士军刀,提供控制多个系统服务的能力。

hammerhead:/ # svc
Available commands:help     Show information about the subcommandspower    Control the power managerdata     Control mobile data connectivitywifi     Control the Wi-Fi managerusb      Control Usb statenfc      Control NFC functions

请注意svc 命令的能力受限于允许和禁止指定的系统服务的行为:

hammerhead:/ # svc help power
Control the power managerusage: svc power stayon [true|false|usb|ac|wireless]Set the 'keep awake while plugged in' setting.svc power reboot [reason]Perform a runtime shutdown and reboot device with specified reason.svc power shutdownPerform a runtime shutdown and power off the device.hammerhead:/ # svc help data
Control mobile data connectivityusage: svc data [enable|disable]Turn mobile data on or off.hammerhead:/ # svc help wifi
Control the Wi-Fi managerusage: svc wifi [enable|disable]Turn Wi-Fi on or off.

2.4 ime

  ime 指令让你与输人法系统服务通信来控制可用输人法的系统使用。ime命令在一个脚本中使用app_process 启动Java代码。正如svc命令、ime 命令是一个值得记住、但可能不经常使用的命令。

# Script to start "pm" on the device, which has a very rudimentary
# shell.
#
base=/system
export CLASSPATH=$base/framework/ime.jar
exec app_process $base/bin com.android.commands.ime.Ime "$@"
hammerhead:/ # ime
usage: ime list [-a] [-s]ime enable IDime disable IDime set IDThe list command prints all enabled input methods.  Use
the -a option to see all input methods.  Use
the -s option to see only a single summary line of each.The enable command allows the given input method ID to be used.The disable command disallows the given input method ID from use.The set command switches to the given input method ID.

2.5 input

input 连接到窗口管理系统服务并将文本或按键事件注人系统。

# Script to start "input" on the device, which has a very rudimentary
# shell.
#
base=/system
export CLASSPATH=$base/framework/input.jar
exec app_process $base/bin com.android.commands.input.Input "$@"
hammerhead:/ # input
Usage: input [<source>] <command> [<arg>...]The sources are:keyboardmousejoysticktouchnavigationtouchpadtrackballdpadstylusgesturegamepadtouchscreenThe commands and default sources are:text <string> (Default: touchscreen)keyevent [--longpress] <key code number or name> ... (Default: keyboard)tap <x> <y> (Default: touchscreen)swipe <x1> <y1> <x2> <y2> [duration(ms)] (Default: touchscreen)press (Default: trackball)roll <dx> <dy> (Default: trackball)

frameworks/base/core/java/android/view/KeyEvent.java中有各个按键编号:

public class KeyEvent extends InputEvent implements Parcelable {/** Key code constant: Unknown key code. */public static final int KEYCODE_UNKNOWN         = 0;/** Key code constant: Soft Left key.* Usually situated below the display on phones and used as a multi-function* feature key for selecting a software defined function shown on the bottom left* of the display. */public static final int KEYCODE_SOFT_LEFT       = 1;/** Key code constant: Soft Right key.* Usually situated below the display on phones and used as a multi-function* feature key for selecting a software defined function shown on the bottom right* of the display. */public static final int KEYCODE_SOFT_RIGHT      = 2;/** Key code constant: Home key.* This key is handled by the framework and is never delivered to applications. */public static final int KEYCODE_HOME            = 3;/** Key code constant: Back key. */public static final int KEYCODE_BACK            = 4;/** Key code constant: Call key. */public static final int KEYCODE_CALL            = 5;/** Key code constant: End Call key. */public static final int KEYCODE_ENDCALL         = 6;/** Key code constant: '0' key. */public static final int KEYCODE_0               = 7;/** Key code constant: '1' key. */public static final int KEYCODE_1               = 8;/** Key code constant: '2' key. */public static final int KEYCODE_2               = 9;/** Key code constant: '3' key. */public static final int KEYCODE_3               = 10;/** Key code constant: '4' key. */public static final int KEYCODE_4               = 11;
......

2.6 monkey

  monkey 命令可以用于提供随机而又可重复的输人给你的应用程序。例如,这个命令将50 个伪随机输人到浏览器的应用程序,可通过如下命令实现:

monkey -p com.android.browser -v 50

还可以实现更多功能:

hammerhead:/ # monkey
usage: monkey [-p ALLOWED_PACKAGE [-p ALLOWED_PACKAGE] ...][-c MAIN_CATEGORY [-c MAIN_CATEGORY] ...][--ignore-crashes] [--ignore-timeouts][--ignore-security-exceptions][--monitor-native-crashes] [--ignore-native-crashes][--kill-process-after-error] [--hprof][--pct-touch PERCENT] [--pct-motion PERCENT][--pct-trackball PERCENT] [--pct-syskeys PERCENT][--pct-nav PERCENT] [--pct-majornav PERCENT][--pct-appswitch PERCENT] [--pct-flip PERCENT][--pct-anyevent PERCENT] [--pct-pinchzoom PERCENT][--pct-permission PERCENT][--pkg-blacklist-file PACKAGE_BLACKLIST_FILE][--pkg-whitelist-file PACKAGE_WHITELIST_FILE][--wait-dbg] [--dbg-no-events][--setup scriptfile] [-f scriptfile [-f scriptfile] ...][--port port][-s SEED] [-v [-v] ...][--throttle MILLISEC] [--randomize-throttle][--profile-wait MILLISEC][--device-sleep-time MILLISEC][--randomize-script][--script-log][--bugreport][--periodic-bugreport][--permission-target-system]COUNT

  还可以为 monkey 提供一个脚本运行一组预定义的输入而不是提供随机输人。这是用于开发、测试、现场诊断的一个非常有用的功能。比如写一个名为monkey_script的脚本。

type= raw events
count= 10
speed= 1.0
start data >>
Tap(942,1472);
Drag(1064,1858,875,933,1);
Tap(334,882);
Tap(1058,950);
Tap(991,339);
Tap(464,1195);
Tap(350,1391);
Drag(118,1578,1018,298,1);
Tap(572,426);
Drag(575,1387,80,1531,1);
Tap(253,1788);
Tap(713,887);
Tap(795,721);
Tap(199,1513);
Drag(877,559,854,1440,1);
Drag(125,1039,70,1413,1);
Tap(766,120);
Tap(783,1646);
Drag(866,1173,84,1075,1);
Tap(1018,157);
Drag(642,1012,893,1135,1);
Tap(1004,1565);
Drag(927,1731,201,190,1);
Tap(106,1106);
Tap(824,1659);
Tap(741,1780);
Drag(12,1174,847,1914,1);
Tap(322,1290);
Drag(332,1645,914,104,1);

按照这个脚本命令执行monkey:

monkey -f monkey_script 1

2.7 bmgr

Android 拥有了备份功能,允许用户将他们拥有的数据备份到云中,以便以后如果丢失或更换它们的设备后,还能对数据进行还原。有一个工具 bmgr,允许你从命令行控制备份管理系统服务的行为。

hammerhead:/ # bmgr
usage: bmgr [backup|restore|list|transport|run]bmgr backup PACKAGEbmgr enable BOOLbmgr enabledbmgr list transportsbmgr list setsbmgr transport WHICHbmgr restore TOKENbmgr restore TOKEN PACKAGE...bmgr restore PACKAGEbmgr runbmgr wipe TRANSPORT PACKAGEbmgr fullbackup PACKAGE...bmgr backupnow --all|PACKAGE...

3 Dalvik工具

3.1 dalvikvm

  我们知道如何通过 am 命令来发送事件,因而触发新的应用程序启动,这些应用程序中的每一个都有自己的 Zygote-forked Dalvik 实例。我们也看到app_process 命令是如何使用Android 的运行时刻(Runtime)来启动Java 编码的命令行工具的。然而,某些情况下,你可能想放弃所有的 Android 特定的层,并直接参与到 Dalvik 中。可以通过以下命令:

hammerhead:/ # dalvikvm -help
dalvikvm: [options] class [argument ...]The following standard options are supported:-classpath classpath (-cp classpath)-Dproperty=value-verbose:tag ('gc', 'jit', 'jni', or 'class')-showversion-help-agentlib:jdwp=options-agentpath:library_path=options (Experimental feature, requires -Xexperimental:agent, some features might not be supported)The following extended options are supported:-Xrunjdwp:<options>-Xbootclasspath:bootclasspath-Xcheck:tag  (e.g. 'jni')-XmsN (min heap, must be multiple of 1K, >= 1MB)-XmxN (max heap, must be multiple of 1K, >= 2MB)-XssN (stack size)-XintThe following Dalvik options are supported:-Xzygote-Xjnitrace:substring (eg NativeClass or nativeMethod)-Xstacktracefile:<filename>-Xgc:[no]preverify-Xgc:[no]postverify-XX:HeapGrowthLimit=N-XX:HeapMinFree=N-XX:HeapMaxFree=N-XX:NonMovingSpaceCapacity=N-XX:HeapTargetUtilization=doublevalue-XX:ForegroundHeapGrowthMultiplier=doublevalue-XX:LowMemoryMode-Xprofile:{threadcpuclock,wallclock,dualclock}-Xjitthreshold:integervalueThe following unique to ART options are supported:-Xgc:[no]preverify_rosalloc-Xgc:[no]postsweepingverify_rosalloc-Xgc:[no]postverify_rosalloc-Xgc:[no]presweepingverify-Ximage:filename-Xbootclasspath-locations:bootclasspath(override the dex locations of the -Xbootclasspath files)-XX:+DisableExplicitGC-XX:ParallelGCThreads=integervalue-XX:ConcGCThreads=integervalue-XX:MaxSpinsBeforeThinLockInflation=integervalue-XX:LongPauseLogThreshold=integervalue-XX:LongGCLogThreshold=integervalue-XX:ThreadSuspendTimeout=integervalue-XX:DumpGCPerformanceOnShutdown-XX:DumpJITInfoOnShutdown-XX:IgnoreMaxFootprint-XX:UseTLAB-XX:BackgroundGC=none-XX:LargeObjectSpace={disabled,map,freelist}-XX:LargeObjectThreshold=N-XX:DumpNativeStackOnSigQuit=booleanvalue-XX:MadviseRandomAccess:booleanvalue-XX:SlowDebug={false,true}-Xmethod-trace-Xmethod-trace-file:filename  -Xmethod-trace-file-size:integervalue-Xps-min-save-period-ms:integervalue-Xps-save-resolved-classes-delay-ms:integervalue-Xps-hot-startup-method-samples:integervalue-Xps-min-methods-to-save:integervalue-Xps-min-classes-to-save:integervalue-Xps-min-notification-before-wake:integervalue-Xps-max-notification-before-wake:integervalue-Xps-profile-path:file-path-Xcompiler:filename-Xcompiler-option dex2oat-option-Ximage-compiler-option dex2oat-option-Xpatchoat:filename-Xusejit:booleanvalue-Xjitinitialsize:N-Xjitmaxsize:N-Xjitwarmupthreshold:integervalue-Xjitosrthreshold:integervalue-Xjitprithreadweight:integervalue-X[no]relocate-X[no]dex2oat (Whether to invoke dex2oat on the application)-X[no]image-dex2oat (Whether to create and use a boot image)-Xno-dex-file-fallback (Don't fall back to dex files without oat files)-Xplugin:<library.so> (Load a runtime plugin, requires -Xexperimental:runtime-plugins)-Xexperimental:runtime-plugins(Enable new and experimental agent support)-Xexperimental:agents(Enable new and experimental agent support)The following previously supported Dalvik options are ignored:-ea[:<package name>... |:<class name>]-da[:<package name>... |:<class name>](-enableassertions, -disableassertions)-esa-dsa(-enablesystemassertions, -disablesystemassertions)-Xverify:{none,remote,all,softfail}-Xrs-Xint:portable, -Xint:fast, -Xint:jit-Xdexopt:{none,verified,all,full}-Xnoquithandler-Xjniopts:{warnonly,forcecopy}-Xjnigreflimit:integervalue-Xgc:[no]precise-Xgc:[no]verifycardtable-X[no]genregmap-Xverifyopt:[no]checkmon-Xcheckdexsum-Xincludeselectedop-Xjitop:hexopvalue[-endvalue][,hexopvalue[-endvalue]]*-Xincludeselectedmethod-Xjitblocking-Xjitmethod:signature[,signature]* (eg Ljava/lang/String\;replace)-Xjitclass:classname[,classname]*-Xjitcodecachesize:N-Xjitoffset:offset[,offset]-Xjitconfig:filename-Xjitcheckcg-Xjitverbose-Xjitprofile-Xjitdisableopt-Xjitsuspendpoll-XX:mainThreadStackSize=N

  dalvikvm 实际上是一个原始的没有连接到任何“Android”上的 Dalvik 虚拟机。它不依赖于 Zygote,同时它也不包含 Android 的运行时库。它只是启动一个虚拟机来运行你提供的所有类或JAR 文件。实际上 AOSP 本身并不经常使用它,可能是因为在AOSP中没有太多不运行在“Android”上下文中的情况。

3.2 dexdump

如果你想要反向开发Android 应用程序或者JAR 文件,你可以通过dexdump 命令实现:

hammerhead:/ # dexdump
dexdump: no file specified
Copyright (C) 2007 The Android Open Source Projectdexdump: [-c] [-d] [-f] [-h] [-i] [-l layout] [-m] [-t tempfile] dexfile...-c : verify checksum and exit-d : disassemble code sections-f : display summary information from file header-h : display file header details-i : ignore checksum failures-l : output layout, either 'plain' or 'xml'-m : dump register maps (and nothing else)-t : temp file name (defaults to /sdcard/dex-temp-*)

Android 系统的分区和文件系统(5)- Android Framework层上的工具和命令相关推荐

  1. Android 系统的分区和文件系统(1)- Android 系统源码结构分析

    声明 本文分析Android系统源码各目录存放文件用途. 其中参考了一些书籍内容,仅供学习使用. 本文采用 LinesgeOS cm-14.1(等同于AOSP Android 7.1.1) 1. 整体 ...

  2. android frp分区,android系统的分区结构

    android系统的分区结构 转载 ANTIBili_MC 关注 (一)Android的主要分区 Modem分区bootloader分区boot分区recoverty分区system分区data分区1 ...

  3. android 手机分区失败怎么办,一种Android系统Data分区自修复方法及系统专利_专利查询 - 天眼查...

    1.一种Android系统Data分区自修复方法,其特征在于,包括: 步骤1: Android智能终端开机进入Android系统后,判断Data分区是否损坏,对Data分 区进行挂载,然后读取Data ...

  4. Android系统的分区及img文件、移植烧写过程

    一.引言 本章介绍Android的几个分区,已经编译后生成的.img镜像文件,对于大家移植整个Android有一定的帮助.本人也首次接触Android,有不正确的地方,欢迎指正! 二.Android的 ...

  5. Android 系统的分区

    1.modem分区,主要是手机短信的通讯模块: 2.bootloader分区,主要用于线刷: 3.recovery分区,只有用于普通刷机: 4.boot分区,用于启动: 5.system分区,系统分区 ...

  6. 把android系统装到sd卡,在Android系统中将软件安装在SD卡的方法

    这样就可以装上更多自己喜欢的软件了. 在Android手机刚面世的时候,系统版本1.5至后来的2.1都不支持把程序装到SD卡上,由于系统内置的空间较小,装不了太多软件,于是人们 想出App2SD的概念 ...

  7. Android 系统(57)---深入理解Android输入系统

    <深入理解Android 卷III>第五章 深入理解Android输入系统 <深入理解Android 卷III>即将发布,作者是张大伟.此书填补了深入理解Android Fra ...

  8. Android之 震动(Vibrator)如何贯通Android系统 (从硬件设计 -- 驱动 -- HAL -- JNI -- Framework -- Application)

        在Android 2.3(Gingerbread) 系统的时候,我写过一篇关于"Android 震动马达系统"的文章,当时的Linux内核还是2.6版本的.写那篇文章的目的 ...

  9. android系统签名app自动更新,【Android 进阶】Apk 使用系统签名

    刚入职的时候,固件中 app 需要在源码中编译,不是很理解,为什么不使用 IDE 编译,然后 copy 到 /system/app/*,咨询导师,得到反馈 app 需要使用系统的权限 在 Androi ...

最新文章

  1. Elasticsearch如何做到亿级数据查询毫秒级返回?
  2. 算术表达式求解背景_1.8 C++算术运算符与表达式
  3. python教材免费版-北大内部教材python版算法与数据结构PDF电子书免费下载
  4. 工作中常用的 6 种设计模式!
  5. VisualStudio解决方案配置Debug和Release选项
  6. 真正解决ASP.NET每一个页面首次访问超级慢的问题 (转载)
  7. Java并发编程-多线程基础
  8. [python] raw string,反斜杠\,re Lib
  9. 《解析几何》吕林根,徐子道第四版 习题 1.4.7,1.4.8,1.4.9
  10. 2021-09-13强化学 习 原理及技术介绍
  11. Oracle数据库的安装及使用教程
  12. Hypermesh-优化案例学习笔记-cclip
  13. vrep和matlab联合仿真
  14. 打造地图拼接利器(五)地图采集与拼接
  15. 【项目实战】Airbnb爱彼迎-数据分析与建模
  16. html中并列式的应用,并列式结构梳理
  17. python基础学海拾遗
  18. Python模块之Pandas 格式化数据
  19. 微信小程序原生tabBar基础模板
  20. Angular-CLI工具使用文档翻译

热门文章

  1. 联想电脑首次重装系统(BIOS无USB问题解决)
  2. Java CAS详解
  3. python人脸口罩识别训练模型_【每天进步一点点】基于ModelArts,跑通口罩检测案例(Python版本)——模型训练与转化部分...
  4. Pytorch入门——MNIST手写数字识别代码
  5. 洛谷—P5020 货币系统(背包问题)
  6. 每天一个linux命令---wall/wirte
  7. Ubuntu 16.04 pycharm 设置桌面快捷方式
  8. 野火挑战者V2开发板CubeMX+LWIP+FreeRTOS+TCP_Server+TCP_Client实现
  9. 代码随想录十八天|513,112,113,106,105
  10. 【矩阵乘法】【倍增】WYC(luogu 3597)