I am using adb shell to delete contacts from phone. For example if I have 50 contacts, how to delete first 10?
I use this to delete one by one, is there a way to delete more contacts at once, by one command, to make process faster?
adb shell content delete --uri content://com.android.contacts/contacts/1
I am not looking to clear all contacts, but to delete some and to leave the rest of the contacts.
First, you can query all your contacts:
$ adb shell content query --uri content://com.android.contacts/contacts
Row: 0 last_time_contacted=0, phonetic_name=NULL, custom_ringtone=NULL, contact_status_ts=NULL, pinned=0, photo_id=NULL, photo_file_id=NULL, contact_status_res_package=NULL, contact_chat_capability=NULL, contact_status_icon=NULL, display_name_alt=Doe, John, sort_key_alt=Doe, John, in_visible_group=0, starred=0, contact_status_label=NULL, phonebook_label=S, is_user_profile=0, has_phone_number=1, display_name_source=40, phonetic_name_style=0, send_to_voicemail=0, lookup=4073r100-4D5331434D4F31394337453333, phonebook_label_alt=S, contact_last_updated_timestamp=1571690183031, photo_uri=NULL, phonebook_bucket=19, contact_status=NULL, display_name=John Doe, sort_key=John Doe, photo_thumb_uri=NULL, contact_presence=NULL, in_default_directory=1, times_contacted=0, _id=100, name_raw_contact_id=100, phonebook_bucket_alt=19
Row: 1 last_time_contacted=0, phonetic_name=NULL, custom_ringtone=NULL, contact_status_ts=NULL, pinned=0, photo_id=NULL, photo_file_id=NULL, contact_status_res_package=NULL, contact_chat_capability=NULL, contact_status_icon=NULL, display_name_alt=Doe, Jane, sort_key_alt=Doe, Jane, in_visible_group=0, starred=0, contact_status_label=NULL, phonebook_label=C, is_user_profile=0, has_phone_number=1, display_name_source=40, phonetic_name_style=0, send_to_voicemail=0, lookup=4073r101-2D374B394D4F3929432B512B312D3D, phonebook_label_alt=B, contact_last_updated_timestamp=1571690183031, photo_uri=NULL, phonebook_bucket=3, contact_status=NULL, display_name=Jane Doe, sort_key=Jane Doe, photo_thumb_uri=NULL, contact_presence=NULL, in_default_directory=1, times_contacted=0, _id=101, name_raw_contact_id=101, phonebook_bucket_alt=2
Row: 2 last_time_contacted=0, phonetic_name=NULL, custom_ringtone=NULL, contact_status_ts=NULL, pinned=0, photo_id=NULL, photo_file_id=NULL, contact_status_res_package=NULL, contact_chat_capability=NULL, contact_status_icon=NULL, display_name_alt=Roe, Jane, sort_key_alt=Roe, Jane, in_visible_group=0, starred=0, contact_status_label=NULL, phonebook_label=A, is_user_profile=0, has_phone_number=1, display_name_source=40, phonetic_name_style=0, send_to_voicemail=0, lookup=4073r102-29432F4B31294D55393F3F, phonebook_label_alt=W, contact_last_updated_timestamp=1571690183031, photo_uri=NULL, phonebook_bucket=1, contact_status=NULL, display_name=Jane Roe, sort_key=Jane Roe, photo_thumb_uri=NULL, contact_presence=NULL, in_default_directory=1, times_contacted=0, _id=102, name_raw_contact_id=102, phonebook_bucket_alt=23
Row: 3 last_time_contacted=0, phonetic_name=NULL, custom_ringtone=NULL, contact_status_ts=NULL, pinned=0, photo_id=NULL, photo_file_id=NULL, contact_status_res_package=NULL, contact_chat_capability=NULL, contact_status_icon=NULL, display_name_alt=Roe, Richard, sort_key_alt=Roe, Richard, in_visible_group=0, starred=0, contact_status_label=NULL, phonebook_label=U, is_user_profile=0, has_phone_number=1, display_name_source=40, phonetic_name_style=0, send_to_voicemail=0, lookup=4073r103-51432B313D2943434F2B4B31315B31, phonebook_label_alt=B, contact_last_updated_timestamp=1571690183031, photo_uri=NULL, phonebook_bucket=21, contact_status=NULL, display_name=Richard Roe, sort_key=Richard Roe, photo_thumb_uri=NULL, contact_presence=NULL, in_default_directory=1, times_contacted=0, _id=103, name_raw_contact_id=103, phonebook_bucket_alt=2
You can use sed to, e.g., select the first three rows and trim them to their ids (i.e., the _id attribute:
$ adb shell content query --uri content://com.android.contacts/contacts | sed -n '1,3 s/^.* _id=\([[:digit:]]\+\),.*$/\1/p'
100
101
102
This sed command says not to print anything by default (the -n switch), but for lines 1 to 3 substitute the lines with the value of the _id and print the result (the p flag at the end of the substitution).
I now tried to loop over this output and issue an adb shell delete for every id, but this does not work. It will only issue a command for the first id. I don’t know exactly why this is, but it must have something to do with what the adb shell command does.
As a workaround, we can do all this directly in the adb shell. So, first execute adb shell and then in that shell you can directly use the content command. For better readability I first save the ids in a file and then loop over its lines. Of course, it’s perfectly possible to just pipe the output of sed into the while loop.
mycomputer$ adb shell
android$ content query --uri content://com.android.contacts/contacts | sed -n '1,3 s/^.* _id=\([[:digit:]]\+\),.*$/\1/p' >ids
android$ while read -r id; do content delete --uri content://com.android.contacts/contacts/"$id"; done <ids
I would like to get an adb command with a response of a code that map to current call state
the call state I mean are those in following link
https://developer.android.com/reference/android/telecom/Call.html#STATE_ACTIVE
those values are more representative and getting those values in command shell upon executing the adb command will be very helpful for me
I have only managed to get them on a log as per following command
adb logcat -d | findstr -i InCallFragment.setCallState
but I couldnot get the state value as a response of any adb command
Any help will be much appreciated
Thanks
for more illustration
please connect a phone to the PC , do a phone call and end it
use the above command to dump the buffer
refer to the state value
You can use adb shell service call telecom [code] command. The codes for getCallState() will be different depending on the Android version:
6.0.1: 26
7.0.0: 27
7.1.0: 27
7.1.2: 27
8.0.0: 29
8.1.0: 29
I have achieved what you want to do by modifying a custom ROM (LineageOS) and adding an android.util.Log line to print every state.
In my case I modified class:
Call
frameworks/opt/telephony/src/java/com/android/internal/telephony/Call.java
And what I did is inside getState(...) method, adding this line:
Log.i(myTAG, "getState state->" + mState.name());
With this what I have to do is search for myTAG in adb logcat.
I think otherwise you wont be able to do it...
You can dumpsys telecomm service:
adb shell dumpsys telecom
CallsManager:
mCalls:
[TC#7, ACTIVE, com.android.phone/com.android.services.telephony.TelephonyConnectionService, tel:***, A, childs(0), has_parent(false), [Capabilities: CAPABILITY_HOLD CAPABILITY_SUPPORT_HOLD CAPABILITY_MUTE CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO], [Properties:]]
mCallAudioManager:
All calls:
TC#7
Active dialing, or connecting calls:
TC#7
Ringing calls:
Holding calls:
Foreground call:
[TC#7, ACTIVE, com.android.phone/com.android.services.telephony.TelephonyConnectionService, tel:***, A, childs(0), has_parent(false), [Capabilities: CAPABILITY_HOLD CAPABILITY_SUPPORT_HOLD CAPABILITY_MUTE CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO], [Properties:]]
mTtyManager:
mCurrentTtyMode: 0
mInCallController:
mInCallServices (InCalls registered):
.
.
Call TC#7 [2018-06-05 14:38:41.505](MO - outgoing)
To address: tel:***
14:38:41.508 - CREATED:PCR.oR#DMA
14:38:41.511 - SET_CONNECTING (ComponentInfo{com.android.phone/com.android.services.telephony.TelephonyConnectionService}, [8c3d1caa626a79d75b154221ea94852a62fee7b3], UserHandle{0}):PCR.oR#DMA
14:38:41.847 - AUDIO_ROUTE (Leaving state QuiescentEarpieceRoute):PCR.oR->CAMSM.pM_2001->CARSM.pM_SWITCH_FOCUS#DMA_2_2
14:38:41.847 - AUDIO_ROUTE (Entering state ActiveEarpieceRoute):PCR.oR->CAMSM.pM_2001->CARSM.pM_SWITCH_FOCUS#DMA_2_2
14:38:43.442 - BIND_CS (ComponentInfo{com.android.phone/com.android.services.telephony.TelephonyConnectionService}):NOCBIR.oR#DMU
14:38:43.519 - CS_BOUND (ComponentInfo{com.android.phone/com.android.services.telephony.TelephonyConnectionService}):SBC.oSC#DMY
14:38:43.519 - START_CONNECTION (tel:***):SBC.oSC#DMY
14:38:43.703 - CAPABILITY_CHANGE (Current: [[ sup_hld mut !v2a]], Removed [[]], Added [[ sup_hld mut !v2a]]):CSW.hCCC#DMg
14:38:43.706 - SET_DIALING (successful outgoing call):CSW.hCCC#DMg
14:38:47.560 - SET_ACTIVE (active set explicitly):CSW.sA#DNM
14:38:47.639 - CAPABILITY_CHANGE (Current: [[ hld sup_hld mut !v2a]], Removed [[]], Added [[ hld]]):CSW.sCC#DNY
Timings (average for this call, milliseconds):
bind_cs: 77.00
outgoing_time_to_dialing: 187.00
PROBLEM:
Every time I run this python function in my monkeyrunner.py script, it opens a new background instance of (cmd, adb, and conhost). And so, in my automation script, if I have a loop that uses that 100 times, I'm going to see 100 of each cmd, adb, and conhost running in the background (I know this because I enter "ps" in powershell to get the list of processes.) The purpose of the function, if you're curious, is to look for logcat messages from the USB attached Android tablet, to see when processes are finished, so that the script knows when to command screen touches to move forward with automation testing.
action = "____"
waitTime = 1
def adb(logMessage, action):
start = time.time()
p = subprocess.Popen("adb logcat -v time", shell=True, cwd="C:\Users\<USERNAME>\AppData\Local\Android\sdk\platform-tools", stdout=subprocess.PIPE)
for line in p.stdout:
if logMessage in line:
print("Found message!")
break
pass
else:
continue
QUESTION:
How can I use "subprocess" to open adb WITHOUT opening a new instance each time? Is there a way to close the subprocess in the same function?
2 things.
adb logcat is a blocking call. It doesn't return unless you send it a SIGINT (ctrl +c). So inside a script you have to send it the "-d" flag. If you forget your script will keep waiting.
you can wait for a subprocess to complete with p.wait()
Therefore you can try this
action = "____"
waitTime = 1
def adb(logMessage, action):
start = time.time()
p = subprocess.Popen("adb logcat -d -v time", shell=True, cwd="C:\Users\<USERNAME>\AppData\Local\Android\sdk\platform-tools", stdout=subprocess.PIPE)
#p.wait()
for line in p.stdout:
if logMessage in line:
print("Found message!")
break
pass
else:
continue
This will ensure that every adb session launched to look at logact terminates properly and its output is looked at only after it returns
EDIT: You are absolutely right, p.wait() isn't needed and is actually wrong! because the logcat writes more than 4kb to stdout in yourcase. You could try to use commuinicate instead to help with that
I figured it out. To prevent a new session of adb from opening in the background per each time this function is called, all I had to do is place the "p" variable outside the function.... like this...
p = subprocess.Popen("adb logcat -v time", shell=True, cwd="C:\Users\<USERNAME>\AppData\Local\Android\sdk\platform-tools", stdout=subprocess.PIPE)
action = "____"
waitTime = 1
def adb(logMessage, action):
start = time.time()
for line in p.stdout:
if logMessage in line:
print("Found message!")
break
pass
else:
continue
There is still the issue of a single adb session that opens and does not close after the script is run. So, now, instead of 180 sessions (or more) opening, there is a single one. If I find out how to close the session I will update this ticket.
I have code that prints out the output of adb logcat into a wx.TextArea box, this all works great, click the button and logcat prints out, it prints out more when phone taps are made and everything works fine.
toolsDir and pkgName are both strings.
params = [toolsDir + "\\adb.exe", "logcat"]
p = Popen(params, stdout=subprocess.PIPE, bufsize=1)
for line in p.stdout:
self.progressBox.AppendText(line.decode('utf-8'))
However I have adapted this code to only print out the logs that are for a particular app, this is done using the windows 'findstr' function, adb logcat | findstr myApp. The code below initially works, but then stops, and doesn't display anything else whatever happens, button tapped, app closed etc.
Its like the buffer has reached the end and doesn't process any further events.
args = [toolsDir + '\\adb.exe', 'logcat']
args2 = ['findstr', pkgName]
process_adb = subprocess.Popen(args, stdout=subprocess.PIPE, shell=False)
process_fs = subprocess.Popen(args2, stdin=process_adb.stdout, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False)
for line in process_fs.stdout:
self.progressBox.AppendText(line.decode('utf-8'))
How come the bottom code, the one that filters the app name, stops printing out real time logs, but the top doesn't? I'm guessing its something to do with the piping of one command to another.
You can use Python to filter lines:
if pkgName in line:
BTW: it can be problem with two processes because probably second waits for EOF (end of file) or other signal (ie. closed pipe) but its stdin is open all the time waiting for new data from first process..
Check this: python-subprocess-interaction-why-does-my-process-work-with-popen-communicate
I'm using the eclipse plugin for android development. When I copy/paste log contents from ddms, I always get the timestamp etc in the copy/paste:
05-16 21:43:09.082: INFO/ActivityManager(110): [message text]
05-16 21:43:09.152: INFO/ActivityManager(110): [message text]
...
Is there any way to clip the timestamp + debug level + pid from the paste as seen above, and only get the [message text] copied? It just gets annoying sometimes when sending log details to others as it's a bit noisy for them to look at,
Thanks
Filter your logs with this one-liner:
perl -pe 's/^(.*?: ){2}//'
Write a 5 line program to remove the first 20 characters of each line to remove the timestamp,
or use line.split(" ") to remove the first 3 parts.
Or use a text editor with block selection such as TextPad