Android

Acer rooten

ICS_rooting_A10x_A5xx.zip laden, entpacken, Tablet anschließen, runit-win.bat starten. Achtung, unter Windows 10 löschte mir der Defender den Exploit zum Rooten nach dem Entpacken gleich von der Platte, sodass das Rooten nicht funktioniert. Zum Entpacken und Rooten muss der Defender kurz ausgeschaltet werden.

root

Tablet rebootet

root

Mit SuperSU und anderen Tools anschließend auf Root-Rechte prüfen (aus Google Play)

Python installieren

Scripting Layer for Android SL4A als apk auf den Gerätespeicher des Acer schieben sowie Python Interpreter

Dateien von hier: Python for Android

Oder Download von bachfeld.com

sl4a-r6.1.1-arm-debug.apk

PythonForAndroid-debug.apk

Nach der Installation der beiden Pakete lädt Py4A einen aktuellen Interpreter aus dem Netz nach sowie weitere Python-Libs.

Alternativ kann man die nachzuladenden Dateien auch lokal im Wurzelverzeichnis (bzw storage/emulated/0/) des Android-Dateisystems in einem Order com.googlecode.pythonforandroid speichern und dann über den Punkt “Local Installation” installieren.

pythoninterpreter

pythoninterpreter

Die mitgelieferten Skripte liegen im Stammverzeichnis im Ordner SL4A ( storage/emulated/0/sl4a/scripts/). Eigene Skripte kann man dort ebenfalls ablegen.

pythoninterpreter

Dann sollte alles für erste Versuche startklar sein.

leider funktionieren der Python-Interpreter auf den Acer A500 nicht, der Python-Blob verursacht nur ein Segementation Fault. Interessanterweise ist auf dem A500 bereits ein Python 2.6 vorinstalliert.

Ok, versuchen wir es mit dem Galaxy J1

Rooten des Galaxy J1 SM-100H

in kurzen Worten: Bootloader unlocken mit veränderter Firmware, die spielt man über Odinv3 ein. Handy runterfahen, mit Power+Home+Volume down in das “alternate Firmware”-Menü starten und mit Vol-up bestätigen. Odin meldet “added” und dann “Ok” zum Flashen des Bootloaders

Anschließend muss man noch den eigentlichen Root-Vorgang mit einer App duechführen. KingoRoot beispielsweise. Allerdings hat man nachher einiges an Adds drauf, die aber immerhin abschaltbar sind.

Auf dem Galaxy J1 läuft der Python-Interpreter ohne Probleme. Libs, Binaries etc liegen übrigens hier:

/data/user/0/com.googlecode.pythonforandroid/files/python/bin
/data/user/0/com.googlecode.pythonforandroid/files/python/lib
/data/user/0/com.googlecode.pythonforandroid/files/python/share

Das Programmieren auf einem Smartphone oder Tablet ist allerdings etwas umständlich, es sein denn, man schließt eine Tastatur an. Alternativ programmiert man auf einem PC und schiebt die Skripte dann per Dropbox oder USB auf das Gerät.

Noch praktischer ist eine Verbindung mit SSH auf das Gerät und die Skripte dann in einer Shell zu schreiben. Gut funktioniert beispielsweise der SSH Server von Ice Cold Apps. Im Unterschied zu SSHDroid kann er sogar Rootrechte anfordern, sodass man in/mit der Shell überall hingelangt und auch jeden Befehl ausführen kann.

pythoninterpreter

Vor dem Start muss man einen Nutzer mit Name und Passwort anlegen. Beim Connect mit Putty unter Windows gibt es nichts weiter zu beachten. Unter Ubuntu muss der allerdings die Option für DSS kEys hinzufügen

ssh dab@192.168.2.135 -p 33333 -o 'HostkeyAlgorithms +ssh-dss'

Um die Skripte zu starten, muss man allerdings über die Oberfläche von SL4A gehen und manuell den Start initiieren.

Grundlagen SL4a

Hier gibts ein paar Einstiege in SL4A und Py4A

SL4A - Quick Guide

Python Android Scripting Layer (SL4A) Tutorial

serielle Schnittstelle

Wozu sollte man nun eigentlich Android programmieren wollen. Neben dem Auslesen von Sensoren interessiert mich besonders, ob man Smartphones als MSR-Rechner nutzen kann. Zu Kommunikation mit der Außenwelt kann man WLAN, Bluetooth und USB nutzen. USB ist praktisch, um beispielsweise mit einem Arduino zu kommunizieren. USB direkt zu programmieren ist jedoch schwer. Unter Python lässt sich recht einfach die serielle Schnittstelle programmieren. Geräte mit serieller Schnittstelle lassen sich also direkt ansprechen, oder solche mit USB2Seriell-Wandler wie FTDI oder Prolific - zumindest in der Theorie. In der Praxis fehlen Android - zumindest bei den von mir getesteten Versionen - die Treiber dafür. Was jedoch funktioniert ist der Anschluss von Geräten wie “USB communication device (CDC)” mit dem Untertypen “abstract control model” (ACM). Das ist genau das was Arduino unterstützt.

Damit ist es möglich, mit einem Arduino über die serielle Schnittstelle zu kommunizieren. Allerdings gibt es noch einen Haken: Die Python-Skripte haben zunächst keine Zugriffsrechte auf /dev/ttyACMO.

[ 4133.627408] usb 2-1: new full-speed USB device number 2 using msm_hsusb_host
[ 4133.747616] notifying plugin
[ 4133.790097] usb 2-1: New USB device found, idVendor=2341, idProduct=0043
[ 4133.790738] usb 2-1: New USB device strings: Mfr=1, Product=2, SerialNumber=220
[ 4133.791043] usb 2-1: Manufacturer: Arduino (www.arduino.cc)
[ 4133.791714] usb 2-1: SerialNumber: 952383433343517021A0
[ 4133.799954] cdc_acm 2-1:1.0: ttyACM0: USB ACM device
root@deb:/ #

Problem

beim Zugriff auf die serielle gibt es Permission denied. a) su chmod 666 /dev/ttyACM0 bringt alleine nichts, weil SELinux unter Android weiterhin den Zugriff verhindert. in der Shell

su
setenforce 0

Allerdings hakelt das manchmal und Android meldet so komische Sachen wie

130|root@deb:tmp-mksh: 0 not found

Randnotiz

It appears that Samsung modified the shell domain to also block access to this command. http://www.all-things-android.com/content/se-android-commands

Modul pyserial nachinstallieren

Um mit der seriellen Schnittstelle sprechen zu können, benötigt Python das Modul pyserial. Das Original Modul lässt sich jedoch nicht einbinden. Auf der Seite von “Kuri” gibt es nur eine egg-Datei, die allerdings ebenfalls einen Fehler produziert, weil eine Info-Datei fehlt. Glücklicherweise ist das egg-Format eigentlich nichts anderes als eine zip-Datei. Abhilfe bringt es deshalb , die Datei pyserial von .egg in .zip umzubenennen und anschließend über Import Modul von Py4A das Modul zu installieren.

Download: pyserial-2.6-py2.6.zip

Beispiel: “Empfangen von Daten”

C-Code auf dem Arduino

void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
Serial.println ("test");
delay (1000);
}

Python-Code auf dem Tablet

import serial
ser = serial.Serial('/dev/ttyACM0',9600,)


while True:
        bla = ser.readline()
        print bla

Beispiel: Senden von Daten

Das Python-Skript sendet ein Zeichen. Sobald der Arduino es empfängt, toogelt er die LED.

import serial
import time

#ser = serial.Serial('COM9',57600,)
ser = serial.Serial('/dev/ttyACM0',57600,)

while True:

        ser.write('\x80')
        print "print"
        time.sleep(1)
ser.close()
void setup() {
        Serial.begin(57600);     // opens serial port, sets data rate to 9600 bps
        pinMode(13, OUTPUT);
}

void loop() {

        if (Serial.available() > 0) {

                incomingByte = Serial.read();


                digitalWrite(13, !digitalRead(13));   // Toggle led
        }
}

Andere Geräte seriell ansprechen

Schön wäre es, wenn man über die serielle auch andere Geräte als den Arduino ansprechen könnte. Wie oben bereits geschrieben, mangelt es jedoch unter Android an nativen FTDI-oder Prolific-Treibern, um von seriell auf USB umzusetzen. Doch Moment mal, warum nicht einfach einen Arduino UNO dafür benutzen? Auf dem Arduino übernimmt ein 16u2 die Umsetzung von USB auf seriell, der die Daten über die Leitungen Rx und Tx an den ATmega 328(P) weiterleitet. Beide Leitungen lassen sich auf den Steckerleisten anzapfen. Damit der ATmega nicht unerwünscht dazwischenfunkt, hebelt man ihn in der Version mit dem IC-Sockel einfach heraus.

arduino

Im Bild ist ein alter Stecker einer PS/2-Maus angeschlossenn, der als Adapter für einen Roomba dient.

ps2-stecker

import time
from roombaclass import Roomba
dist=100

robot = Roomba()
robot.wake()
time.sleep(1)
#robot.brushesON()
robot.goDistance(dist)
robot.turnRight(90)
robot.goDistance(dist)
robot.turnRight(90)
robot.goDistance(dist)
robot.turnRight(90)
robot.goDistance(dist)
robot.turnRight(90)
#robot.findCharger()
````
Die dazugehörige Klasse roombaclass gibt es hier y[roombaclass.py](http://www.bachfeld.com/android/roombaclass.py)

Code zum Testen der Verbindung (Auslesen von Sensoren und kurze Vorwärtsfahrt)

```python
import serial
import time
ser=serial.Serial('/dev/ttyUSB0',115200)
ser.write('\x80')
ser.write('\x83')

ser.write('\x8e\x03')
print('geschrieben')
line = ser.read(10)
for i in range (0,10):
    print ord(line[i])

#x84 schaltet licht aus -> Full mode
#ser.write('\x84')
#x83 schaltet safe mode wieder ein
#ser.write('\x80\x83')
ser.write('\x89\x00\x64\x80\x00')
time.sleep(1)
#ser.write('\x84')
#ser.write('\x83')
ser.write('\x80')

Mit Skript andere Anwendungen starten

Ziel ist es, einen kleinen Webserver in Python zum Steuern des Roombas zu starten, der wiederum Skype startet. Die API dokumnetiert folgendes

startActivity(
   String action,
   String uri[optional],
   String type[optional]: MIME type/subtype of the URI,
   JSONObject extras[optional]: a Map of extras to add to the Intent,
   Boolean wait[optional]: block until the user exits the started activity,
   String packagename[optional]: name of package. If used, requires classname to be useful,
   String classname[optional]: name of class. If used, requires packagename to be useful)

Folgender Beispielcode ist aus dem Netz und startet die Twitter-App

import android
droid = android.Android()
droid.startActivity('android.intent.action.MAIN',
                    None, None, None, False,
                    'com.twitter.android',
                    'com.twitter.android.StartActivity'
                   )

Wie die jeweiligen Apps heißen, sieht man mit einem Root-Browser unter /data/app.

Skype firmiert dort unter dem Namen “com.skype.raider-1”. Das “raider” ist eine Namenskonvention, u

Auf Google Play firmiert Skype unter “https://play.google.com/store/apps/details?id=com.skype.raider” Die Name sind eindeutig “unique”.

Bei mir funktionierte der Start von Skype mit

droid.startActivity('android.intent.action.MAIN', None, None, None, False, 'com.skype.raider', 'com.skype.raider.StartActivity')

jedoch nicht.

Alternativ funktionierte der Start mit Angabe der Skype-URI

droid.startActivity('android.intent.action.VIEW', 'skype:daniel@bachfeld.com')

Telepräsenz-Skript

from roombaclass import Roomba
import BaseHTTPServer
import socket
import urlparse
import time
import os
import android

droid = android.Android()
os.system("su -c 'chmod 777 /dev/ttyACM0'")

robot = Roomba()
robot.wake()
time.sleep(1)

droid.startActivity('android.intent.action.VIEW', 'skype:daniel@bachfeld.com')


HOST_NAME   = ''
PORT_NUMBER = 9090

PAGE_TEMPLATE = '''
<html>

<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Remote Control</title>
</head>
<body>
<form name="myform" method="get">
    <button type="submit" name="action" value="0" style="color: transparent; background-color: transparent; border-color: transparent; cursor: default; height:150px; width:150px" ></button>

    <button type="submit" name="action" value="1" style="height:150px; width:150px" >START</button>

    <p></p>


    <button type="submit" name="action" value="3" style="height:150px; width:150px" >LEFT</button>
    <button type="submit" name="action" value="5" style="height:150px; width:150px" >STOP</button>
    <button type="submit" name="action" value="4" style="height:150px; width:150px" >RIGHT</button>
    <p></p>
    <button type="submit" name="action" value="0" style="color: transparent; background-color: transparent; border-color: transparent; cursor: default; height:150px; width:150px" ></button>
    <button type="submit" name="action" value="2" style="height:150px; width:150px" >BACK</button>



</form>

</body>
</html>
'''

def play( id ):
  if   (id=='1'):
    print ("forward")
    robot.goForward()
  elif (id=='2'):
    print ("back")
    robot.goBackward()
  elif (id=='3'):
    print ("left")
    robot.spinLeft()
  elif (id=='4'):
    print ("right")
    robot.spinRight()
  elif (id=='5'):
    print ("stop")
    robot.stopMoving()

class DroidHandler(BaseHTTPServer.BaseHTTPRequestHandler):

  def do_HEAD(s):
    s.send_response(200)
    s.send_header("Content-type", "text/html; charset=utf-8")
    s.end_headers()

  def do_GET(s):
    s.send_response(200)

    url = urlparse.urlsplit(s.path)
    print url.path
    query = url.query
    args = urlparse.parse_qsl(query)

    action = ''
    for arg in args:
      if arg[0] == 'action':
        action = arg[1].strip().replace('\r', '')
        print(action)
        play(action)
        break


    s.send_header("Content-type", "text/html; charset=utf-8")
    s.end_headers()

    html = PAGE_TEMPLATE
    s.wfile.write(html)

print 'web server running on port %s' % PORT_NUMBER
droid.wakeLockAcquireBright()
my_srv = BaseHTTPServer.HTTPServer((HOST_NAME, PORT_NUMBER), DroidHandler)
my_srv.serve_forever()

skripte über shell/terminal starten

 am start -a com.googlecode.android_scripting.action.LAUNCH_BACKGROUND_SCRIPT -n com.googlecode.android_scripting/.activity.ScriptingLayerServiceLauncher -e com.googlecode.android_scripting.extra.SCRIPT_PATH/sdcard/sl4a/scripts/beach/server.py

mit Superuserrechten!

in ein Skript gegossen:

#! /system/bin/sh
chmod 777 /dev/ttyACM0
cd /storage/emulated/0/sl4a/scripts/beach
[ -z "$1" ] && exec echo "please specify the name of a script to run"
am start -a com.googlecode.android_scripting.action.LAUNCH_BACKGROUND_SCRIPT -n com.googlecode.android_scripting/.activity.ScriptingLayerServiceLauncher -e com.googlecode.android_scripting.extra.SCRIPT_PATH
 /sdcard/sl4a/scripts/beach/${1}
 ```

damit kann man alles Skripte im jeweiligen Ordner starten
(/storage/emulated/0/sl4a/scripts/beach)



## ip webcam

Universal Webcam per IP mit KOnfigurationsoberfläche zum Drehen, Auflösung etc

https://play.google.com/store/apps/details?id=com.pas.webcam&hl=de
 Aufruf über http://server:8080 und andere /video  


## Termux

Termux bietet eine Linux-Umgebung mit apt-Tools etc
Python3 ist vorinstalliert. Node.js lässt sich recht einfach nachinstallieren. Leider bricht die Installation des Packets serialport mit der Fehlermeldung ab, gyp (node-gyp) sei nicht mit der Python-Version kompatibel.

Abhilfe bringt es, Python 3 zu deinstallieren und Python 2 zu installieren:

```bash
apt install python2
apt remove python

Der nachfolgende Lauf bricht dann wegen fehlendem make und Compiler ab. BTW unter Termux ist clang der Standcompiler

apt install make
apt install clang

Der Installationsvorgang samt compilieren läuft ohne Fehler durch. Leider lässt sich das Packet später trotzdem nicht nutzen.

bash-4.4$ node
> var serialport = require("serialport");
WARNING: linker: /data/data/com.termux/files/home/node_modules/serialport/build/Release/serialport.node has text relocations. This is wasting memory and prevents security hardening. Please fix.
Segmentation fault

Python-Paket ohne pip-Tool installieren

Python 2.7.14 (default, Oct  8 2017, 19:47:34)
[GCC 4.2.1 Compatible Android Clang 5.0.300080 ] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import pip
>>> import serial
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named serial
>>> pip.main(['install','pyserial'])
Collecting pyserial
  Downloading pyserial-3.4-py2.py3-none-any.whl (193kB)
    100% |████████████████████████████████| 194kB 532kB/s
Installing collected packages: pyserial
Successfully installed pyserial-3.4
0

USB OTG bzw Host

Nexus S und Galaxy J1 haben keinen USB Host Mode, damit kann man nur mit Bluetooth und WLAN mit der Außenwelt kommunizieren

Geräteverwaltung Installation von Dateien unbekannter Herkunft zulasseb Unbekannte Herkunft - Installation von Nicht-Market-Apps zulassen