Showing posts with label Android. Show all posts
Showing posts with label Android. Show all posts

Sunday, December 29, 2019

TVplus Go on Laptop

Watch free ISDB-T digital TV on laptop (or any x86_64 computer) using the ABS-CBN TVplus Go USB dongle.



As of this writing, the TVplus Go dongle only works on Android operating system. So the way to make it work on an x86 platform is either install the Android-x86 or simply use an Android emulator. This demo will use the official emulator running on Ubuntu 18.04 64-bit host OS. Other OS types, like Windows 10, might also work but will still initially require *nix-based tools for modifying the virtual device's ramdisk cpio archive and system ext4 image file.

The TVplus Go Android app, as of version 1.0.28, only works on ARM CPUs (armeabi-v7a and arm64-v8a only). Running the ARM emulator is not advisable because it's too slow and unusable. So the only option now is to install libhoudini (ARM translator) on the x86 emulator.



Guide:
1. Download the Android command line tools (installing the whole Android studio is only optional).
https://developer.android.com/studio, e.g. extract sdk-tools-linux-4333796.zip to ~/android/sdk.

2. Open a terminal, change directory to ~/android/sdk, and set the following environment variables:
$ export JAVA_OPTS='-XX:+IgnoreUnrecognizedVMOptions --add-modules java.se.ee'
$ export ANDROID_HOME=$HOME/android/sdk
$ export ANDROID_SDK_ROOT=$ANDROID_HOME

3. Download the emulator, platform-tools, and the system-image. Android Nougat (API-25) is selected because easier to modify compared to with the recent versions.
$ ./tools/bin/sdkmanager "platform-tools" "platforms;android-25" "emulator"
$ ./tools/bin/sdkmanager --install "system-images;android-25;google_apis;x86_64"


4. Go to $ANDROID_SDK_ROOT/system-images/android-25/google_apis/x86_64 and increase the size of the system.img (create a backup first!). Allocate at least 128MB for the additional files.
$ cd $ANDROID_SDK_ROOT/system-images/android-25/google_apis/x86_64
$ dd if=/dev/zero bs=1M count=512 >> ./system.img
$ e2fsck -f system.img
$ resize2fs system.img


5. Copy libhoudini binaries. Mount first the system.img before extracting the files.
$ wget http://dl.android-x86.org/houdini/7_y/houdini.sfs -O houdini_7_y.sfs
$ mkdir -p systemfs
$ sudo mount -o loop -t ext4 system.img systemfs
$ sudo unsquashfs -d systemfs/lib/arm houdini_7_y.sfs
$ sudo cp systemfs/lib/arm/libhoudini.so systemfs/lib/
$ sudo cp systemfs/lib/arm/houdini systemfs/bin/

Either set the selinux to permissive (add -selinux permissive option on the emulator) or set the security context of the libhoudini files.
$ sudo setfattr -n security.selinux -v u:object_r:system_file:s0 systemfs/bin/houdini
$ sudo setfattr -n security.selinux -v u:object_r:system_file:s0 systemfs/lib/libhoudini.so
$ sudo setfattr -n security.selinux -v u:object_r:system_file:s0 systemfs/lib/arm
$ sudo setfattr -n security.selinux -v u:object_r:system_file:s0 systemfs/lib/arm/*
$ sudo setfattr -n security.selinux -v u:object_r:system_file:s0 systemfs/lib/arm/nb/*

6. Allows ARM executable file formats
$ sudo mkdir -p systemfs/etc/binfmt_misc
$ echo ":arm_dyn:M::\x7f\x45\x4c\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x28::/system/bin/houdini:" | sudo tee systemfs/etc/binfmt_misc/arm_dyn
$ echo ":arm_exe:M::\x7f\x45\x4c\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28::/system/bin/houdini:" | sudo tee systemfs/etc/binfmt_misc/arm_exe

$ sudo nano systemfs/build.prop
add the following properties to the build.prop (overwrite if existing):
ro.enable.native.bridge.exec=1

ro.product.cpu.abilist=x86_64,x86,armeabi-v7a,armeabi
ro.product.cpu.abilist32=x86,armeabi-v7a,armeabi


7. Enable access to the TVPlus Go USB dongle (vendor id 0x048d, product id 0x9308)
$ echo '<permissions><feature name="android.hardware.usb.host"/></permissions>' | sudo tee systemfs/etc/permissions/android.hardware.usb.host.xml
$ echo 'SUBSYSTEM=="usb", ATTRS{idVendor}=="048d", ATTRS{idProduct}=="9308", GROUP="kvm"' | sudo tee /etc/udev/rules.d/89-usb-android.rules
$ sudo udevadm control --reload-rules

8. Hide from "root-detection" and "running-on-emulator-detection"
i. rename the su executable
$ sudo mv systemfs/xbin/su systemfs/xbin/_s_u
ii. edit again build.prop, check these answers on which properties to be modified. Replace, at least, the "generic" string from ro.product.device and ro.build.fingerprint. (not the actual workaround)

iii. (optional) Install Google Play, if you want to watch the encrypted channels - need to pay P20 for the registration (in-app purchase). Copy "Phonesky.apk" from opengapps.org to systemfs/priv-app/Phonesky

iv. finally, unmount the image.
$ sync
$ sudo umount systemfs

9. Extract ramdisk, and edit default.prop
$ mkdir -p ramdiskfs
$ cd ramdiskfs
$ gzip -dc ../ramdisk.img | cpio -i

$ nano default.prop


Replace ro.dalvik.vm.native.bridge=0 with ro.dalvik.vm.native.bridge=libhoudini.so

10. Edit an init configuration file (e.g. init.ranchu.rc) to register the libhoudini by adding these lines:
# Enable native bridge for target executables
on early-init
    mount binfmt_misc binfmt_misc /proc/sys/fs/binfmt_misc

on property:ro.enable.native.bridge.exec=1
    copy /system/etc/binfmt_misc/arm_exe /proc/sys/fs/binfmt_misc/register
    copy /system/etc/binfmt_misc/arm_dyn /proc/sys/fs/binfmt_misc/register

11. Repack the new ramdisk
$ cd ..
$ wget https://github.com/xiaolu/mkbootimg_tools/raw/master/mkbootfs
$ chmod +x mkbootfs
$ ./mkbootfs ./ramdiskfs | gzip > ramdisk.img

12. Create the AVD named "avd_7_1_x86_64" based on "Android TV (720p)" device.
$ ./tools/bin/avdmanager --verbose create avd --force --name "avd_7_1_x86_64" --device "tv_720p" \
  --package "system-images;android-25;google_apis;x86_64" --tag "google_apis" --abi "x86_64"


13. Now launch the emulator.
$ ./tools/emulator @avd_7_1_x86_64 -show-kernel -verbose -memory 2048 \
  -qemu -usb -device usb-host,vendorid=0x048d,productid=0x9308

14. Install the TVplus Go Android app, either via the Google Play or via adb install
$ adb install ../apks/TVplus\ GO_v1.0.28_apkpure.com.apk


15. Finally, plugin the TVplus Go dongle to a USB port and then launch now the app on the emulator




Monday, May 9, 2016

Android-Arduino Communication via USB OTG


USB On-the-go capability in Android devices has now become more available in the market. And why wouldn’t it be? This feature, nicknamed OTG, enables you to use your flash drives, keyboards, mice and even printers with just your phone! What’s more interesting is it can also enable you to communicate and control your microprocessors using your Android device without the need for additional modules – just a cable. In this article, we will see how this communication can become possible. To demonstrate, we will control the behavior of an LED and send messages to another very popular item in the electronics world – the Arduino.


The shorter end of the stick is Arduino’s side. In your Arduino, simply upload this code:

int ledPin = 13;

void setup(){  
  Serial.begin(9600);
  Serial.setTimeout(200);
  pinMode(ledPin, OUTPUT);  
}  

void loop(){
  if (Serial.available()){
    String c = Serial.readString();
    if (c.equals("TONLED")) digitalWrite(ledPin, HIGH); 
    else if (c.equals("TOFFLED")) digitalWrite(ledPin, LOW);
    else Serial.print(c);
  }
}

In the above sketch, we are simply waiting for the data arriving at our serial line and performing actions based on the data received. For instance, turning on the LED ledPin requires a TONLED message from our Android device. You’ve probably noticed that there are no special libraries or methods in our Arduino sketch.  That’s a great thing because it tells us that the system is not exclusive to Arduino and will work with any microcontroller that supports serial communication.

Let’s now move on to Android’s side. The first step is to create an Android project and add the necessary components. In the project we created, we added extra components for user convenience. For learning and testing purposes, only the following are necessary:
  • Text Field – used to get input data by the user, which will be sent to and echoed by the Arduino
  • Toggle Button – used to control the behavior of the LED
  • Start Button – used to open the serial port
  • Send Button – used to send messages to Arduino
  • Text View – used to display logs
To simplify the setup and processes, we will use the UsbSerial library by felHR85. There are a lot of libraries you can choose from. In case you have other preferences, feel free to modify and adapt to your preferred library.

In the build.gradle of your project, add jitpack. Jitpack is a very awesome tool that enables us to get a Git project into our build.

allprojects {
    repositories {
        jcenter()
        maven { url "https://jitpack.io" }
    }
}

Now, add the dependency to your module’s build.gradle.

compile 'com.github.felHR85:UsbSerial:4.3'

Moving on to our main activity, there are some variables that we wish to declare globally for convenience.

private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";

UsbDevice device;
UsbDeviceConnection connection;
UsbManager usbManager;
UsbSerialDevice serialPort;
PendingIntent pendingIntent;

The next items that we will present here will not be discussed thoroughly, but you can refer to Android's official documentation for details.

Before trying to start the communication, you must seek permission from the user. To do this, create a broadcast receiver. This receiver listens for the intent that gets broadcasted when you call requestPermission(). Only when granted can we proceed to opening the connection and setting parameters for the Serial communication.

private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(ACTION_USB_PERMISSION)) {
            boolean granted = intent.getExtras().getBoolean(UsbManager.EXTRA_PERMISSION_GRANTED);
            if (granted) {
                connection = usbManager.openDevice(device);
                serialPort = UsbSerialDevice.createUsbSerialDevice(device, connection);
                if (serialPort != null) {
                    if (serialPort.open()) {
                        serialPort.setBaudRate(9600);
                        serialPort.setDataBits(UsbSerialInterface.DATA_BITS_8);
                        serialPort.setStopBits(UsbSerialInterface.STOP_BITS_1);
                        serialPort.setParity(UsbSerialInterface.PARITY_NONE);
                        serialPort.setFlowControl(UsbSerialInterface.FLOW_CONTROL_OFF);
                        serialPort.read(mCallback); 
                    } else {
                        Log.d("SERIAL", "PORT NOT OPEN");
                    }
                } else {
                    Log.d("SERIAL", "PORT IS NULL");
                }
            } else {
                Log.d("SERIAL", "PERMISSION NOT GRANTED");
            }
        } else if (intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)) {
            onClickStart(startButton);
        } else if (intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_DETACHED)) {
            //can add something to close the connection
        }
    };
};

On your onCreate method, declare the intent and register your broadcast receiver to start and stop the serial connection.

pendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
registerReceiver(broadcastReceiver, filter);

In our application, we created a start button to start the connection when pressed. In the method that corresponds to the onClick action of our button, we add the following:

public void onClickStart(View view) {

    if (!isSerialStarted) {
        usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);

        HashMap<String, UsbDevice> usbDevices = usbManager.getDeviceList();
        if (!usbDevices.isEmpty()) {
            boolean keep = true;
            for (Map.Entry<String, UsbDevice> entry : usbDevices.entrySet()) {
                device = entry.getValue();
                int deviceVID = device.getVendorId();

                if (deviceVID == 1027 || deviceVID == 9025) { //Arduino Vendor ID
                    usbManager.requestPermission(device, pendingIntent); 
                    keep = false;
                } else {
                    connection = null;
                    device = null;
                }
                if (!keep)
                    break;
            }
        }
    }
}

The code above searches for vendor IDs 1027 or 9025 – the vendor ID’s associated to FTDI or Arduino. The vendor ID equal to 9025 is the more popular and more common value based on other articles in the internet, but mine has an ID of 1027. The easiest way to know is to just print the vendor IDs detected by the Android device.  If the vendor ID matches the expected ID for our device, we will call the requestPermission() method. With this, the intent will be broadcasted and picked up by our receiver, starting and opening the connection.

Once communication is opened, we can start sending and receiving data. To receive from Arduino, simply add the codes below. Note that we are appending the data received to the text view.

private UsbSerialInterface.UsbReadCallback mCallback = new UsbSerialInterface.UsbReadCallback() {
    //Defining a Callback which triggers whenever data is read.
    @Override
    public void onReceivedData(byte[] arg0) {
        String data = null;
        try {
            data = new String(arg0, "UTF-8");
            data.concat("/n");
            tvAppend(displayView, data);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }
};

private void tvAppend(final TextView tv, final CharSequence text) {
    runOnUiThread(new Runnable() {
        @Override public void run() {
            if (text != null) {
                tv.append(text); 
            }
        }
    });
}

Sending data is easier. We only need to get user input from the text field, and send it to the connected device.

public void onClickSend(View view) {
    String textInput = inputView.getText().toString();
    serialPort.write(textInput.getBytes());
}

To control the LED in Arduino, simply add the code below. You are free to change TONLED and TOFFLED to whatever names you want. Just don’t forget to adjust the Arduino code as well.

public void onClickToggle(View view) {
    if (isLedON == false) {
        isLedON = true;
        tvAppend(displayView, "\nLED TURNED ON\n");
        serialPort.write("TONLED".getBytes());
    } else {
        isLedON = false;
        serialPort.write("TOFFLED".getBytes());
        tvAppend(displayView, "\nLED TURNED OFF\n");
    }
}

You can close the connection using:

serialPort.close();

We are almost done. In your manifest file, add the following so that your application will be notified of an attached USB device. 

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="yourpackage.com.name">

    <uses-feature android:name="android.hardware.usb.host" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:theme="@style/AppTheme.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
            </intent-filter>
            <meta-data
                android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
                android:resource="@xml/device_filter" />
            <intent-filter>
                <action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" />
            </intent-filter>
        </activity>
    </application>
</manifest>

Create an xml folder inside the res folder and add device_filter.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <usb-device
        vendor-id="9025"/>
</resources>

And… were done! Additional tips, we can add a checker to confirm that the serial connection is already open. This saves us from crashes due to attempts to send serial data while the connection is still closed. We can also add clear buttons, or place the text view inside a scroll view then automatically scroll to end of page using: 

mScrollView.smoothScrollTo(0, displayView.getBottom());

That’s it. If you want to extend your phone’s sensors, or if you want to add storage, wireless and messaging capability, camera and orientation sensors in your microprocessor project with just one device, USB On-the-Go, may be your way to go.

A demo application, SimpleArDroid by YMSoftLabs can be downloaded from Google Play. Here's a video of how the system works.




References:
UsbSerial: A serial port driver library for Android v3.0
USBSerial
Communicate with Your Arduino Through Android


Sunday, June 14, 2015

Bluetooth Joystick Updated To v2.1


Android Bluetooth Dual-Joystick App is now available on Google Play.



Sunday, April 22, 2012

Android-OpenCV Object-Tracking


Tracking a ping-pong ball using Android-OpenCV Library


source code:
svn co http://yus-repo.googlecode.com/svn/trunk/Android/apps/objtrack
* needs Android-NDK to build.
modify objtrack.cpp to detect other objects/colors


pre-built installer: Object-Track.apk
* only for Android phones with ARMv7-capable CPU and Gingerbread OS.

references:
OpenCV for Android (see Tutorial 2 Advanced - 1. Add Native OpenCV)
Tracking colored objects in OpenCV
Android-OpenCV Google-Group

##############################################
edit 05-05-12
interfacing the app to philrobokit-Anito board (observe the LEDs+buzzer states with respect to the ball position).

* Data are being transmitted via the usb2serial adapter (built-in to the kit) using android-serialport-api.

Wednesday, February 15, 2012

Bluetooth Joystick



Android Bluetooth Dual-Joystick Controller

Sends 5 bytes every 200ms (or every 3 sec if idle).
data format: [ STX : radiusL : angleL : radiusR : angleR ]
where: STX = 0x55
           radius = {0..10}
           angle = {0..35} (or actual/10)

sample:

will send [ 0x55 : 0x0A : 0x12 : 0x05 : 0x09 ]
(**left-joystick is pulled backward; right-joystick leaning to the left)

Source code:
svn co https://yus-repo.googlecode.com/svn/trunk/Android/apps/btjoystick

Installer: BTJoystick.apk .

Joystick widget from Mobile-Anarchy.


demo on my quadruped:


#---------------------------------
edit 10/15/12
version 2: BTJoystick.v2.apk   45.8 KB



modifications:
* preference menu (e.g. "Menu->Connect" & "Menu->Options" )
* add four customizable buttons (send either an ascii char or a string)
* immediately send joystick data when a joystick returns to center position
* selectable data format, intervals and timeout
* prevent accidental closing



Thursday, February 3, 2011

MARG sensors + Bluetooth

MARG (Magnetic, Angular Rate, and Gravity) sensor array used for AHRS (Attitude and Heading Reference Systems).



Android OpenGL 3D display on Samsung Spica (i5700).


Sparkfun 9DOF sensor stick SEN-10389, later replaced by SEN-10321.

Using ATmega328P, operated at 3.3V supply and 8MHz crystal. At this speed, reading sensors' measurements and computing "AHRSupdate" take about 31ms to complete. Default compiler setting is used on WinAVR. With 25Hz sampling rate, this leaves mega328p extra 9ms to do other tasks. Bluetooth SPP (serial) communication is buffered and interrupt driven, so no processing time is wasted in reading and sending data to the android phone.



References:
(1) Sebastian Madgwick's Alternative AHRS (MARG) algorithm - Quaternion implementation of Mayhony's DCM filter incorporating magnetic distortion compensation.
(2) Fabio Varesano's FreeIMU. Also using Madgwick's implementation of the DCM filter on Arduino platform.
(3) Rotation convertions by Martin Baker. Very good discussion on quaternions and other 3D representation like Euler angles and transformation matrix.
(4) OpenGL Transformation Matrix by Song Ho Ahn
(5) Similar discusion on diydrones.com started by Harinath

Android project examples:
Android Bluetooth
Bluetooth Chat
Android OpenGL Projects
OpenGL ES tutorial
Android Bluetooth Oscilloscope

Special thanks to the generous guy who gave me these toys, Thank you very much!


Wednesday, January 19, 2011

Thursday, September 23, 2010

Android Bluetooth Oscilloscope


*This application is tested only with Samsung Galaxy GT-i5700 Spica (rooted Android 2.1 OS, i570EXXJD1 Baseband version).
The transmitter circuit uses Microchip's dsPIC33FJ16GS504 for the analog-to-digital conversion of the input signals on two channels. The processed data on the dsPIC are then transmitted to the phone (for waveform display) via the LMX9838 bluetooth SPP module.


specs/ranges:
  • time per division: {5us, 10us, 20us, 50us, 100us, 200us, 500us, 1ms, 2ms, 5ms, 10ms, 20ms, 50ms }
  • volt per division: {10mV, 20mV, 50mV, 100mV, 200mV, 500mV, 1V, 2V, GND}
  • analog input (depends on external pre-amplifier configuration): {-8V to +8V }


The source codes for the bluetooth communication is based on Bluetooth Chat example from http://developer.android.com. That example contains three java source files. And, I've completely copied the "DeviceListActivity.java", which is used for searching remote bluetooth devices. Then I've modified the "BluetoothChatService.java" to use only the RFCOMM Client functions, and used the well-known UUID "00001101-0000-1000-8000-00805F9B34FB" for the Bluetooth RFCOMM/SPP.
 
For the plotting of waveforms, I'm using SurfaceView object to draw on its canvas. This tutorial found on www.helloandroid.com helps me a lot for this task: "How to use canvas in your android".



The rest of the job mainly involves porting of my previous Python S60 script to JAVA language. It was too painful on my side, because I had to convert a single script file to multiple java + xml source files! Nonetheless, it was a good experience for me on learning the Android SDK (JAVA programming).

Project source codes for Android and dsPIC (with APK and HEX) :
AndroidBluetoothOscilloscope.zip

Electronicslab.ph forum link : Android Bluetooth Oscilloscope

Here are some interesting projects that are also based on the Bluetooth Chat example:
Bluetooth Controlled Model Car
SPRIME

Special thanks to:
Samdroid Forum  for the customized/rooted firmwares for our Spica.
Tipidcp Spica users for sharing their tips and experiences with this android phone.

----------------------------------------------------------------------
#edit (10-15-2010)
Here's now my circuit. Nothing special on it, all are based on existing circuits.

*The dsPIC I have used is most probably NOT the best choice for this project because of the many left unused peripherals (extra pins). But, this is the only part readily available in my bin and it has the fastest ADC (2 x 2MSps) among the chips I have.
*If you prefer to change the input range via the op-amp preamp, the computation is located on the "adc.xmcd" file.
*You can use other SPP bluetooth modules aside from LMX. (accdg to manufacturer, it's already obsolete)

----------------------------------------------------------------------
#edit (9-14-2011)

It's almost a year now, and yet some people are still interested in this project (considered to be obsolete). So I've decided to place the source repository also on Google Code site. You can either Browse or use git to have your own local copy:

   git clone https://code.google.com/p/android-bluetooth-oscilloscope/

See also the Changes, if you want also to learn on how to modify the code. I've started the first 'commit' with a simple "hello world" from the SDK project template. And then changes were made until the desired final oscilloscope application is achieved.