Cannot record screen video with python and on real tv devices: always creates an empty file of 0 bytes

Hello everyone!

I’m having a problem with screen recording on real Android TV devices. I’m using Python + Behave, so I’m using the before_scenario and after_scenario hooks to start and stop recording:

That is the code, with minimal changes since I joined the project. My previous colleague, who I am replacing, wrote this code, and from a video he has from April as a knowledge transfer, at that time the video was created and attached correctly in allure and jira issue.

Now, the file is created (and attached in allure report and jira issue) but it is empty and with 0 bytes, which in addition, jira identifies as an empty attachment and although it returns a 200 response (and as I said, it attaches the file in the issue), I get an error that stops the execution.

HOOK-ERROR in after_scenario: JIRAError: JiraError HTTP None
text: Added empty attachment?!: Response: <Response [200]>
Attachment: recording.mp4

This error is not my main problem (I only mention it because it is annoying, since it prevents the last command, which is the jira issue state transition, from being executed).
What worries me and I can not solve is that apparently it is not recording anything and creates an empty mp4 file and I do not understand why 6 months ago it worked and now it does not.

The environment I’m using is as follows (I do not know which one was used by my former colleague):

  • Appium: 2.1.3 and I have upgraded to the latest version → 2.2.1. Does not work with either.
  • Appium_Python_Client: 3.0.0 and I have upgraded to the latest version → 3.1.0. Does not work with either.
  • Selenium: 4.12.0 and I have upgraded to the latest version → 4.14.0. Does not work with either.
  • Devices: Technicolor and SDMC TV decos

To conclude, here is the appium log:

appium_logs_1.log (16.0 KB)

Thank you and kind regards.

The attached log looks like a mess to me:

2023-10-26 07:49:27:265 [HTTP] ← POST /wd/hub/session/b321b20f-22aa-4cad-b625-b256cc98196f/appium/start_recording_screen 200 745 ms - 12

Here the screen recording is started. Then a new session is requested without ending the previous one and a request to stop the recording from that second session (pay attention to the session id in the URL path):

2023-10-26 07:49:50:044 [HTTP] → POST /wd/hub/session/dd700fd3-d127-4db3-8cdd-26e196faf079/appium/stop_recording_screen

Of course this won’t work. Also, you can manually verify if the device under test is capable of recording any videos by running adb shell screenrecord

1 Like

Hello mykola,

You are absoluty right. I didn’t notice that in the log, and as soon as you remarked it, I knew what was the problem.
Indeed, two sessions were being created, and the first one, which is the one that started the recording, was not closing, and the one that tried to close it at the end of the scenario was the second one.

Once I fixed this, the recording works perfectly.

This was happening because when I updated selenium, I had to change the way in which I passed the capabilities to the driver and in top of that, they also removed the reset() method so I solved this problem with this workaround:

image

But I didn’t realice that with this, I was creating another session without even closing the first one. I guess I could stop the recording and close the session here before I create the new one. Probably there is a better way to do this, but I don’t know how.

Anyway, thank you so much for you help.
Kind regards.

I don’t understand why It is necessary to recreate a session. There are APIs that allow to reset the application without affecting the session state

My problem here is that for some scenarios I need to reset the application, but for the vast majority of them, I don’t need to. This had easy solution: I have the noReset capability set to True and then, in the scenarios I need to reset, I use a behave step with the reset() method implemented.

But since this method was deprecated in the latest versions of Selenium and I start the capabilities in the before_all hook, the only way I found to do this was, instead of using the reset() method, to change the reset capability value to False when I use that behave step, which forces me to create a new session with the updated capabilities.

I looked for a solution for this, but found nothing, and the only thing I could come up with was this.

I don’t know those APIs that could allow me to reset the app. If you know them, please, could you tell me which ones?

Thanks.

I assume you use UIA2 driver. Then https://github.com/appium/appium-uiautomator2-driver#mobile-clearapp might be of use

Yes, that’s right, we are using the UIA2 driver. The problem is that when I try to call the clear method with the driver, nothing appears. Other methods that are on that page you put, like install_app or background_app, do appear and I can use them, but clear_app or something related does not come up in my case. In fact, if I go to applications.py module, which is in appium/webdriver/extensions in my case, there is nothing about a clear or reset method.
I don’t know if it’s because it’s python, and it doesn’t exist in python. Maybe in Java exists, I don’t know.

Actually, I think I tried this before, the clean_app method, but I couldn’t find it either.

I found this thread where the removal of some methods, including resetApp() is discussed:
https://github.com/appium/appium/issues/15807
Speaking on this subject, the first comment says: […] In their place, users should rely on standard Appium session management (new session + caps, delete session)[…]
Which is more and less, I think, what I did.

It also recommends the clearApp() method but, as I said, it doesn’t exist for me.
I read the thread quickly, so maybe I missed something else (I will read it more carefully), but it seems that it’s pretty much this: or use clearApp(), or mess with sessions or remove/install app, which right now it’s not an option.

why not just use with Android simple

adb shell pm clear <package name>
1 Like

Not sure what you mean under does not exist. You cannot find how to call it from Appium python client?

It could be done similar to https://github.com/appium/python-client/blob/1e281bf085138ee85187770c263ffd91e5a83e58/test/functional/android/activities_tests.py#L25C1-L25C1

Just replace the first argument with mobile: clearApp and the second with the actual method arguments documented above

1 Like

@Aleksei I tried your solution and it worked like a charm. Also superfast. The only thing is that when I start the Appium server, I have to set “–allow-insecure=adb_shell” in the command, because if not, I get a security error.

@mykola-mokhnach What I mean by does not exist is that the IDE does not show me the option. For example, I type driver. and I get a bunch of methods that I can use but none that contain clear or clean or anything related. And if I look in the modules or classes from which these methods come from in the appium/selenium environment, I can’t find anything either.

Anyway, I have also tried your solution but I don’t know if I am doing something wrong because it gives me an error all the time.
The error is this one:

Traceback (most recent call last):
File “/Users/user/WSP/auto-android-stb/.venv/lib/python3.11/site-packages/behave/model.py”, line 1329, in run
match.run(runner.context)
File “/Users/user/WSP/auto-android-stb/.venv/lib/python3.11/site-packages/behave/matchers.py”, line 98, in run
self.func(context, *args, **kwargs)
File “src/test/features/steps/app_steps.py”, line 29, in step_impl
driver.execute_script(“mobile: clearApp”, {“component”: “app”})
File “/Users/user/WSP/auto-android-stb/.venv/lib/python3.11/site-packages/selenium/webdriver/remote/webdriver.py”, line 404, in execute_script
return self.execute(command, {“script”: script, “args”: converted_args})[“value”]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/Users/user/WSP/auto-android-stb/.venv/lib/python3.11/site-packages/selenium/webdriver/remote/webdriver.py”, line 344, in execute
self.error_handler.check_response(response)
File “/Users/user/WSP/auto-android-stb/.venv/lib/python3.11/site-packages/appium/webdriver/errorhandler.py”, line 125, in check_response
raise exception_class(msg=message, stacktrace=format_stacktrace(stacktrace))
selenium.common.exceptions.InvalidArgumentException: Message: ‘appId’ argument must be provided
Stacktrace:
InvalidArgumentError: ‘appId’ argument must be provided
at requireArgs (/Users/user/.appium/node_modules/appium-uiautomator2-driver/node_modules/appium-android-driver/lib/utils.js:16:13)
at AndroidUiautomator2Driver.mobileClearApp (/Users/user/.appium/node_modules/appium-uiautomator2-driver/node_modules/appium-android-driver/lib/commands/app-management.js:165:32)
at AndroidUiautomator2Driver.executeMobile (/Users/user/.appium/node_modules/appium-uiautomator2-driver/lib/commands/general.js:177:84)
at AndroidUiautomator2Driver.execute (/Users/user/.appium/node_modules/appium-uiautomator2-driver/lib/commands/general.js:139:27)
at commandExecutor (/opt/homebrew/lib/node_modules/appium/node_modules/@appium/base-driver/lib/basedriver/driver.ts:107:18)
at /opt/homebrew/lib/node_modules/appium/node_modules/async-lock/lib/index.js:171:12
at AsyncLock._promiseTry (/opt/homebrew/lib/node_modules/appium/node_modules/async-lock/lib/index.js:304:31)
at exec (/opt/homebrew/lib/node_modules/appium/node_modules/async-lock/lib/index.js:170:9)
at AsyncLock.acquire (/opt/homebrew/lib/node_modules/appium/node_modules/async-lock/lib/index.js:187:3)
at AndroidUiautomator2Driver.executeCommand (/opt/homebrew/lib/node_modules/appium/node_modules/@appium/base-driver/lib/basedriver/driver.ts:123:39)
at processTicksAndRejections (node:internal/process/task_queues:95:5)
at defaultBehavior (/opt/homebrew/lib/node_modules/appium/lib/appium.js:722:14)
at AppiumDriver.executeWrappedCommand (/opt/homebrew/lib/node_modules/appium/lib/appium.js:828:16)
at AppiumDriver.executeCommand (/opt/homebrew/lib/node_modules/appium/lib/appium.js:734:17)
at asyncHandler (/opt/homebrew/lib/node_modules/appium/node_modules/@appium/base-driver/lib/protocol/protocol.js:393:19)

I don’t know if I understood properly the way I should build the method. I have something like this:

driver.execute_script(
“mobile: clearApp”,
{
“component”: “appPackage/appActivity”,
},
)

I tried a bunch of combinations for the value of the component but none has worked. I also tried removing the commas at the end.
I really would like this to work because for Android I’ve got the adb command, but for iOS I will need a solution, and this seems a good one.

mobile: clearApp only for Android. For iOS the only way is remove app and install again :frowning:

Ufff that’s a drag for me right now. I would prefer to have it as I have it so far, which is to quit the session started at the beginning, change the noReset capability and start a new session again.

Thank you so much for all the help!