2

手始めに、Python Web ソケットに接続してさまざまな Android イベントを発生させるかなり複雑なシステムがあります。私は多かれ少なかれ、このシステムを Mac Mini で動作する形で与えられました。それ以来、Ubuntu 13.04 に移植し、ある程度の成功を収めました。私が直面している問題は、これらの Android イベントを実際にトリガーするために使用している 2 つの Python スクリプトにあります。

私が持っているのは、run_wsh と performAction の 2 つの .py ファイルです。基本的に、run_wsh はソケット経由で接続され、どのイベントを起動するかを指示します。run_wsh は、performAction のサブプロセスを開始し、入力を performAction にパイプし、performAction の出力を run_wsh に戻します。

最初の主要な呼び出しは、run_wsh の「インストール」です。run_wsh はこれを、while True: ループで実行され、入力を待っている performAction に送信します。ここに問題があるのか​​もしれませんが、よくわかりません。performAction は、次のように設定して読み取ります (python 2 を使用するため、raw_input が標準です)。

input = raw_input()

次に、 performAction は次の方法でそれをチェックします。

if input is None:
    continue
if input == "Install":
    device.installPackage('pathToMyApk.apk')
    runComponent = 'blah/.activityBlah'
    device.startActivity(component=runComponent)
    time.sleep(1)
    subprocess.call(['blah/adb', 'pull', '/pathToTextFileInAndroid.txt', '/pathToTextFileInUbuntu.txt']
    print "Install Successful"

これは、成功したエミュレーターへの最初の waitForConnection 呼び出しの後です。「インストール」が送信されるたびに、何も起こらずにハングします。run_wsh スクリプトから出力を読み取ることができないため、これはわかっています。参考までに、run_wsh の関連ビットを以下に示します。

args = ['pathToMonkeyRunner', 'pathToPerformAction.py']
prog = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
prog.stdout.readline()
#This is to spit out a printed connection statement for when waitForConnection finishes
...
#Inside install call
inputToWrite = "Install"
prog.stdin.write(inputToWrite)
s = prog.stdout.readline()
f = open('/pathToTextFileInUbuntu.txt', 'r')
t = f.read()
#Read from the file and send information back out through the socket

行 s = prog.stdout.readline() がヒットしないことを確認するために、以前に print ステートメントを挿入しました。performAction のさまざまな入力に対する elif ケースは他にもありますが、これも失敗しますが、今のところこのケースだけを見ています。ただし、ここでの本当のバグは、これがハングしたときに、最終的に端末から python プロセスを強制終了することです。インストール部分をコメントアウトしてこれを行った場合(およびapkがadbを介して手動でインストールされている場合)、プロセスが強制終了されると、エミュレーターは最終的に想定どおりにアクティビティページをプルアップします(私はウィンドウはデバッグ目的で開かれますが、通常は -no-window がオンになっています)。世界で最も奇妙なこと。さまざまな time.sleep 呼び出しをコードに挿入しようとしましたが、おそらくデータ競合が発生した場合、何らかの方法でそれを操縦できると考えましたが、残念ながら、

これは大規模なシステムでは大きな問題であることは承知していますが、どんな助けも素晴らしいでしょう。Python、monkey runner、および Android に関する詳細なヘルプを探して Web を精査しましたが、特にこの問題に対処するものは何もありません。

また、コードや私の文章の愚かなタイプミスは無視してください。実際のコピーペーストではなく、vm で端末を見つめてコピーしたコードを手渡しました。さまざまなパスをガベージに変更しましたが、理解するには十分なはずです。ありがとう!

4

1 に答える 1

1

モンキーランナーでも同じ標準入力の問題がありました。(最初は私の C# ホスト アプリの問題だと思っていましたが、代わりにローカルの python 3 プログラムを生成すると、問題なく入力を読み取ることができました。)

別の回答では、Jython 2.5.3 にバグがあり、それを Jython 2.5.4rc1 jar に置き換えることができますが、Windows では修正されませんでした。


私が必要としていたのは、jython プロセスにメッセージを送信する機能だけだったので、標準入力の代わりに最終的に HTTP サーバーを実行することになりました。

import time
from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer

class PostHandler(BaseHTTPRequestHandler):
  def do_POST(self):
    content_len = int(self.headers.getheader('content-length', 0))
    post_body = self.rfile.read(content_len)
    for pair in post_body.split(';'):
      x, y = map(int, pair.split(','))
      device.touch(x, y, MonkeyDevice.DOWN_AND_UP)
      time.sleep(0.08)
    
    self.send_response(200)

if __name__ == '__main__':
  print 'Waiting for device connection...'
  device = MonkeyRunner.waitForConnection()

  server = HTTPServer(('localhost', 8080), PostHandler)
  print 'Got device, starting server, use <Ctrl-C> to stop'
  server.serve_forever()
于 2020-11-01T16:18:21.943 に答える