Tuesday, October 7, 2014

Android Widget Creation and facebook messenger like Chathead

I recently developed an Android widget which pops up an Facebook messenger like image when clicked. This pop-up is similar to the Facebook messenger. Here is a screenshot of the app.

What did I learn from this app:
* How to create a widget
* How the facebook messenger and Button savior app is implemented

The icon can be dragged by touching within the WindowManager (except the Notification bar on top and SoftKey at bottom if any). Now i can create a bunch of wonderful apps which can run on top of all the apps and the whole UI. Wonderful. :-)





The MainActivity.java looks like this:

package com.app.samplewidget;

import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.content.Intent;
import android.widget.RemoteViews;
import android.widget.Toast;

public class MainActivity extends AppWidgetProvider {

    @Override
    public void onDeleted(Context context, int[] appWidgetIds) {
        super.onDeleted(context, appWidgetIds);
        Toast.makeText(context, "onDeleted called",Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager,
            int[] appWidgetIds) {
        super.onUpdate(context, appWidgetManager, appWidgetIds);
        Intent in = new Intent(context,ChatThread.class);
        PendingIntent pi = PendingIntent.getService(context, 0, in, 0);
        
        final int N = appWidgetIds.length;
        for(int i=0; i<N ; i++){
            int awId = appWidgetIds[i]; 
            RemoteViews v = new RemoteViews(context.getPackageName(), R.layout.widget);
            v.setOnClickPendingIntent(R.id.bwidgetOpen, pi);
            appWidgetManager.updateAppWidget(awId, v);
        }
        
    }
}
The ChatThread.java looks like this:

package com.app.samplewidget;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.os.IBinder;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;

public class ChatThread extends Service {

    public static final String TAG = "ChatThread";
    Context c;
    public static boolean status = false;
    private WindowManager windowManager;
    private ImageView chatHead;
    WindowManager.LayoutParams params;

    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();

        windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);

        chatHead = new ImageView(this);
        chatHead.setImageResource(R.drawable.ic_launcher);

        params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_PHONE,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                PixelFormat.TRANSLUCENT);

        params.gravity = Gravity.TOP | Gravity.LEFT;
        params.x = 0;
        params.y = 100;

        windowManager.addView(chatHead, params);
        chatHead.setOnTouchListener(new View.OnTouchListener() {
            private int initialX;
            private int initialY;
            private float initialTouchX;
            private float initialTouchY;

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    initialX = params.x;
                    initialY = params.y;
                    initialTouchX = event.getRawX();
                    initialTouchY = event.getRawY();
                    return true;
                case MotionEvent.ACTION_UP:
                    return true;
                case MotionEvent.ACTION_MOVE:
                    params.x = initialX
                            + (int) (event.getRawX() - initialTouchX);
                    params.y = initialY
                            + (int) (event.getRawY() - initialTouchY);
                    windowManager.updateViewLayout(chatHead, params);
                    return true;
                }
                return false;
            }
        });

    }

    @Override
    public void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
        Log.i(TAG, "onDestroy Called");
        if (chatHead != null)
            windowManager.removeView(chatHead);
    }

    @Override
    public boolean onUnbind(Intent intent) {
        // TODO Auto-generated method stub
        return super.onUnbind(intent);

    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // TODO Auto-generated method stub
        if (status) {
            status = false;
            this.stopSelf();
        } else {
            status = true;
        }
        Log.i(TAG, "onStartCommand - " + status);
        return super.onStartCommand(intent, flags, startId);

    }

}


In addition to the above two file, AndroidManifest.xml is also important:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.app.samplewidget"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="14" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <service 
            android:name=".ChatThread">
        </service>`
        
        <receiver android:name=".MainActivity"
            android:label="@string/app_name">
            <intent-filter >
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
            </intent-filter>
            <meta-data android:name="android.appwidget.provider"
                android:resource="@xml/widget_stuff"/>
        </receiver>
    </application>
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
    
</manifest>




Code is shared on github SampleWidget.

Reference:
Widget Creation Thenewboston Android videos (160-164)
Chathead basics: http://www.piwai.info/chatheads-basics/

Wednesday, September 3, 2014

Adding Timeline to Google Site

I came across a Timeline which can be embedded in the Google site. Check the video here.


Reference: http://timeline.knightlab.com/

I followed the exact steps as per the video. However the timeline was not being displayed in the Google site. On digging further in the issue I found out that Google doesn't allow the http pages in the iFrame.

The solution is to convert the http to https page as follows:


Yeyy.. it works for me...!!! :-)

Sunday, July 13, 2014

Socket Server to transfer Accelerometer Sensor data to PC

Hi Guys,

Recently, I have been trying to get the accelerometer data on PC in real time. Here is how to make it work.

The idea basically is to create a socket server in the Android device and a socket client in local PC to transfer data over wifi. Now lets create a socket server in the Android device which transmits the linear acceleration data.

Create an android Project in Eclipse:
package com.example.myserver;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import android.app.Activity;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.TextView;

public class MainActivity extends Activity implements SensorEventListener {
    String mClientMsg = "";
    Thread myCommsThread = null;
    public static final String TAG = "SocketServer";
    private CommsThread commsThread = null;
    TextView tv;
    PrintWriter out;
    private float ax, ay, az;
    private long timenow = 0, timeprev = 0, timestamp =0 ;

    private SensorManager sm;
    private Sensor sensor;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv = (TextView) findViewById(R.id.textView1);
        sm = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        sensor = sm.getSensorList(Sensor.TYPE_LINEAR_ACCELERATION).get(0);
    }

    @Override
    protected void onResume() {
        // TODO Auto-generated method stub
        super.onResume();
        sm.registerListener(this, sensor, SensorManager.SENSOR_DELAY_UI);
        this.commsThread = new CommsThread();
        this.myCommsThread = new Thread(this.commsThread);
        this.myCommsThread.start();
    }

    @Override
    protected void onPause() {
        // TODO Auto-generated method stub
        super.onPause();
        sm.unregisterListener(this);
        if (commsThread != null) {
            commsThread.stopComms();
        }
    }    

    Handler myHandler = new Handler(){
        public void handleMessage(Message msg){
            TextView status = (TextView) findViewById(R.id.textView3);
            status.setText("Status: Streaming Now!");
        }
    };

    class CommsThread implements Runnable {
        private volatile boolean stopFlag = false;
        private ServerSocket ss = null;
        private static final int SERVERPORT = 6000;
        public void run() {
            Socket s = null;
            try {
                ss = new ServerSocket(SERVERPORT);
            } catch (IOException e) {
                e.printStackTrace();
            }
            
            try {
                s = ss.accept();
            } catch (IOException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
            myHandler.sendEmptyMessage(0);
            
            while(!stopFlag){
                try {
                    out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(s.getOutputStream())), true);
                    out.printf("*#%3.2f#%3.2f#%3.2f#%2d#*\n",ax,ay,az,(int)timestamp );
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }

        public void stopComms() {
            // TODO Auto-generated method stub
            this.stopFlag = true;
            if(ss != null){
                try {
                    ss.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }         
        }
    }

    @Override
    public void onAccuracyChanged(Sensor arg0, int arg1) {
        // TODO Auto-generated method stub       
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        // TODO Auto-generated method stub
        ax = event.values[0];
        ay = event.values[1];
        az = event.values[2];
        timenow = event.timestamp;
        timestamp = (timenow - timeprev)/1000000;
        refreshDisplay();
    }

    private void refreshDisplay() {
        // TODO Auto-generated method stub
        String output = String.format("time: %d -- x:%03.2f | Y:%03.2f | Z:%03.2f", timestamp, ax,ay,az);
        timeprev = timenow;
        tv.setText(output);
    }
}


In the AndroidManifest.xml add the following lines:
    <uses-permission android:maxSdkVersion="19" android:name="android.permission.INTERNET"/>
    <uses-permission android:maxSdkVersion="19" android:name="android.permission.ACCESS_NETWORK_STATE"/>

Now install the socket server on the Android device and launch the program. The server is up and running. It now waits for the client to connect and then transmit the real-time linear acceleration data to the client.

Now lets write a simple client to read the data on Ubuntu PC.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h> 

void error(const char *msg)
{
    perror(msg);
    exit(0);
}

int main(int argc, char *argv[])
{
    int sockfd, portno, n;
    struct sockaddr_in serv_addr;
    struct hostent *server;

    char buffer[256] = "\0";
    if (argc < 3) {
       fprintf(stderr,"usage %s hostname port\n", argv[0]);
       exit(0);
    }

    portno = atoi(argv[2]);
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) 
        error("ERROR opening socket");
    server = gethostbyname(argv[1]);

    if (server == NULL) {
        fprintf(stderr,"ERROR, no such host\n");
        exit(0);
    }

    bzero((char *) &serv_addr, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    bcopy((char *)server->h_addr, 
         (char *)&serv_addr.sin_addr.s_addr,
         server->h_length);
    serv_addr.sin_port = htons(portno);
    if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) 
        error("ERROR connecting");

    //printf("Please enter the message: ");
    bzero(buffer,256);

    //fgets(buffer,255,stdin);
    n = write(sockfd,buffer,strlen(buffer));
    if (n < 0) 
         error("ERROR writing to socket");
    while(1){
        bzero(buffer,256);
        n = read(sockfd,buffer,255);
        if (n < 0) 
            error("ERROR reading from socket");
        printf("%s\n",buffer);
    }
    close(sockfd);
    return 0;
}



compile the above code using
gcc -o socketclient client.c
To connect to the server over wifi network:
./socketclient 192.168.1.2 6000
to connect to the server via USB cable:
adb forward tcp:1234 tcp:6000
./socketclient localhost 1234
Now the data will be streaming on the Ubuntu PC. I'll try to plot this data in my next blog.

References:
C socket programming:
1. http://www.linuxhowtos.org/C_C++/socket.htm 
USB port forwarding:
2. http://www.anothem.net/archives/2010/02/15/communicating-over-the-usb-cable/
Android Socket Programming:
3. http://thinkandroid.wordpress.com/2010/03/27/incorporating-socket-programming-into-your-applications/
4. http://www.edumobile.org/android/android-development/socket-programming/ 

Sunday, July 6, 2014

adb port forwarding via USB



Here is a way to create a socket connection between Android phone and Ubuntu 14.04 desktop.

Pre-requites:
1. Android Terminal Emulator App (On Android Device)
2. Android SDK installed on host computer

create a socket on the device using nc command:
jai@jai-server:~$ adb shell
shell@mako:/ $ nc -l -p 1234
---//
The above command could be executed on the terminal Emulator as follows:



On the host machine:
jai@jai-server:~$ adb forward tcp:1235 tcp:1234
jai@jai-server:~$ nc localhost 1235
--//
Connection is established and you are good to go. Start writing on any of the device. It should be reflected on other device.

Reference: http://bharathisubramanian.wordpress.com/2012/03/10/android-socket-communication-thru-adb/

Wednesday, April 24, 2013

Running programs on server using Screens command

In my last blog I have discussed a way of connecting to your server PC at home from anywhere over the internet either on another desktop or on mobile device. I faced a problem of getting disconnected from the server when the phone signals were week on the move. So tasks like compiling of android source code was halted as soon as I get disconnected from the ssh client. Here is a way to overcome this problem which i found on the internet:

Login to the server using the ssh client and start a screen on the server. Now the shell will actually be running on the server rather than the client.
$ screen
Any other ssh client can now get connected to this screen and can view a copy the screen on their local shell. Even if the client gets disconnected due to any reason, the shell will still be running on the server.

To display the screens running on server:

jaiprakash@jaiprakash-Inspiron-1525:~$ screen -ls

There are screens on:

    2941.pts-4.jaiprakash-Inspiron-1525    (Wednesday 24 April 2013 11:15:52  IST)    (Attached)

    2811.pts-0.jaiprakash-Inspiron-1525    (Wednesday 24 April 2013 11:14:33  IST)    (Attached)

2 Sockets in /var/run/screen/S-jaiprakash.

To connect to a particular screen:
$ screen -x 2941.pts-4.jaiprakash-Inspiron-1525        --> to get a copy of the screen i.e. the shell running on the server.

if only one screen is running the simply use the command
$ screen -x

To disconnect from the screen (but process should be running on the server, in other words only to disconnect the client) use ctrl+A and ctrl+D or ctrl+A and type :detach
You would now be disconnected from the screen. but the process would still be running on the server.

I found it very useful for myself while using the ssh over internet. The screen command is very useful when the client gets disconnected abruptly. Hope this helps to remote developers :-P.

Reference: http://www.howtogeek.com/howto/ubuntu/keep-your-ssh-session-running-when-you-disconnect/

Sunday, April 21, 2013

Accessing my computer from anywhere over internet using ssh and port forwarding

1. Creating a free account on noip.com
Create an account on noip.com. You'll receive a confirmation mail from noip.com. Confirm the link.

Login to your account on noip.com and goto
My Account > Hosts/Redirects > Manage Hosts > Add a host
Chose a proper host name (ex: myserver) and a free domain (ex: zapto.org) from the available list and click on "Update host" when completed.

2. Installing the noip client on device to be accessed
Now Download the noip2 tool from the site under Hosts/Redirects > Download Client

Unzip the noip-duc-linux.tar.gz and install it
$ tar -xzvf noip-duc-linux.tar.gz
$ cd noip-2.1.9-1
$ sudo make install
$ sudo noip2 -C
[sudo] password for user: 

Auto configuration for Linux client of no-ip.com.

Please enter the login/email string for no-ip.com youremail@gmail.com
Please enter the password for user 'youremail@gmail.com'  ********

2 hosts are registered to this account.
Do you wish to have them all updated?[N] (y/N)  n
Do you wish to have host [myserver.no-ip.biz] updated?[N] (y/N)  n
Do you wish to have host [myserver.zapto.org] updated?[N] (y/N)  y
Please enter an update interval:[30]  
Do you wish to run something at successful update?[N] (y/N)  n

New configuration file '/usr/local/etc/no-ip2.conf' created.

To check the status:
 $ sudo noip2 -S

No noip2 processes active.
 
Configuration data from /usr/local/etc/no-ip2.conf.
Account youremail@gmail.com
configured for:
    host  myserver.zapto.org
Updating every 30 minutes via /dev/wlan0 with NAT enabled.

3. Port Forwarding of local wifi network to be accessible from anywhere over internet
Now we need to give access to wifi router to access ssh port from anywhere in the internet. I followed the tutorial from this site and it worked well for me. For my beetel wifi router on airtel network on the browser, login to wifi http://192.168.1.1
user: admin
password: password
http://portforward.com/english/routers/port_forwarding/Beetel/450TC1/defaultguide.htm

4. Changing default ssh port
So we are almost done now. However its recommended to change the ssh port from default (default port 22) settings while forwarding it to internet for security reasons.

To change the ssh port:
sudo vi /etc/ssh/sshd_config and change the following line to custom port address

 ListenAddress 0.0.0.0:44812 

--> make sure that this port number matches the port address described in the portforward.com tutorial.

Also you can make your device ip static. For Raspberry pi, i have mentioned the modifications in the comments of previous post.

5. Accessing over internet using ssh client
Now, to access the device from anywhere from the internet. I am using the ConnectBot client in Android to access my device remotely.

 ssh username@myserver.zapto.org:44812

--> you should be connected to your device now. Cheers, now I can access my device from anywhere using my android phone :-).

Friday, March 15, 2013

Setting up wifi on Raspberry Pi

I recently bought a "NETGEAR wifi dongle" fo my Raspberry Pi so free it from the wired ethernet connections. The details of the wifi dongle is as follows:
$lsusb
Bus 001 Device 004: ID 0846:9041 NetGear, Inc. WNA1000M 802.11bgn [Realtek RTL8188CUS]

To configure it to the local wifi network:

modify /etc/network/interfaces as follows
For example if my wifi network's name is "~Jaguar~" and password is "Password123"
auto lo

iface lo inet loopback
iface eth0 inet dhcp
allow-hotplug wlan0
auto wlan0
iface wlan0 inet dhcp
        wpa-ssid "~Jaguar~"
        wpa-psk "Password123"

Softreboot the system and wifi should be working.
$ sudo shutdown "now" -r

To re-confirm
pi@raspberrypi ~ $ ifconfig
eth0      Link encap:Ethernet  HWaddr b8:27:eb:ae:b2:aa  
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:95 errors:0 dropped:0 overruns:0 frame:0
          TX packets:84 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:9356 (9.1 KiB)  TX bytes:13962 (13.6 KiB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:6402 errors:0 dropped:0 overruns:0 frame:0
          TX packets:6402 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:19282157 (18.3 MiB)  TX bytes:19282157 (18.3 MiB)

wlan0     Link encap:Ethernet  HWaddr 84:1b:5e:92:bf:e8  
          inet addr:192.168.1.8  Bcast:192.168.1.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:2182 errors:0 dropped:2359 overruns:0 frame:0
          TX packets:2001 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:289214 (282.4 KiB)  TX bytes:1055742 (1.0 MiB)
and
 pi@raspberrypi ~ $ iwconfig  
lo        no wireless extensions. 
 
wlan0     IEEE 802.11bg  ESSID:"~Jaguar~"  Nickname:"<WIFI@REALTEK>"
          Mode:Managed  Frequency:2.412 GHz  Access Point: 80:A1:D7:8D:A3:24   
          Bit Rate:54 Mb/s   Sensitivity:0/0  
          Retry:off   RTS thr:off   Fragment thr:off
          Power Management:off
          Link Quality=100/100  Signal level=100/100  Noise level=0/100
          Rx invalid nwid:0  Rx invalid crypt:0  Rx invalid frag:0
          Tx excessive retries:0  Invalid misc:0   Missed beacon:0  
 
eth0      no wireless extensions.  
For Internet to work: use
$ sudo /sbin/route add -net 0.0.0.0 -gw 192.168.1.1 wlan0
where 192.168.1.1 is gateway of my router.

Hope this post helps. :-)

Saturday, March 9, 2013

Remote Desktop of Raspberry Pi onto Ubuntu/Android/Windows

I recently bought a Raspberry Pi board from crazypi.com. Raspberry is a low cost chipset from Broadcom which can host linux and many other OS. It just costs 3K INR if you buy it in India. It is an awesome lowcost chipset with 2 USB ports, one ethernet port, one HDMI port, one TV out and one audio jack port. It also has a micro-USB power input and SD card, from where the OS boots.

Now I am gonna explain how to setup remote desktop from Raspberry Pi to Linux or Windows PC. VNC and RDP protocols are famous for desktop sharing. Both have their advantages and disadvantages. However I prefer RDP over VNC, because VNC often gets stuck while using Desktop sharing. I am gonna explain setting up of both the protocols on Raspberry Pi:

1. Using VNC protocol

Server Configurations on Raspberry Pi:
- Install tightvncserver on the Raspberry
$ sudo apt-get install tightvncserver

- Enter passwords if prompted.

- start the vncserver with the following command

$ vncserver :1 -geometry 800x600 -depth 32 -pixelformat rgb565
   
- Now you are ready to connect to Raspberry Pi remotely from any VNC client either on Ubuntu or Android.

Client Configurations:
On Ubuntu: install vncviewer, to connect remotely, install necesarry packages when prompted.

$ vncviewer 192.168.1.3:5901

   

On Android: Download VNC client app from Android market. I downloaded "androidVNC" app from market, works well on my Galaxy Nexus.

Nickname: raspberry:1

password: <type in the view password set while installing vncserver on Raspberry Pi>

Address: <enter ip address of RPi; ex: 192.168.1.3>

Port: 5901


- To kill the server
$ vncserver -kill :1

However I was unable to browse comfortable using VNC so I decided to use RDP protocol. RDP is faster and preferred over VNC and it performs better.

2. Using RDP protocol
Server Configurations on Raspberry Pi:
- Install the xrdp package on Raspberry Pi

$ sudo apt -get install xrdp

- Thats it, the server is ready on RPi. Restart if required.

Client Configurations:
On Ubuntu: Applications > internet > Terminal server Client

Computer: 192.168.1.3
Protocol: RDPv5
User name: pi
Password: raspberry

Alternatively you can use the rdesktop command from the shell as follows:
$ rdesktop -u pi -p raspberry 192.168.1.3 




On Android: Install a RDP client, I used "AccessToGo Remote Desktop/RDP" and "Ahope RDP Client"from Android market. plugin the details as required.




This is really coooooooooool.

Using Rapberry Pi Command Prompt on other devices:
In addition, to access Raspberry Pi in command shell
On ubuntu: 

$ ssh pi@192.168.1.3 

On android: Download "ConnectBot" app from the Android market. Plugin the details and you are ready to go. :-)

You can expect some more stuff on Raspberry Pi sooner.

See you...

Sunday, December 2, 2012

Taking wireless logs using wifi

Hey Guys,

Recently I have been trying to use connect USB devices to my Nexus S (running Android Jellybean 4.1.2) using an OTG cable. But unfortunately, on connecting the OTG cable we cant take logs to debug. I tried to find a way out of this to take real-time logs using wifi.

On googling I found a way which worked for me.

The task involved two steps:
1. rooting the device
2. using app to start wifi adb

Rooting the device:
a) Download  RootnexussJB.zip from
http://dl.xda-developers.com/attachdl/2b5b28d0b7d10c2d5529e0b8d6d92746/50bb3158/1/2/2/0/8/4/7/RootnexussJB.zip and unzip it in local machine.
b) use "fastboot flash recovery recovery-twrp-2.2.0-crespo.img" to flash recovery binary adn recovery boot using "fastboot reboot recovery".
c) Choose “Mount” > “Mount USB Storage” > Copy the Superuser 3.2_RC.zip to the internal storage of your Nexus S > Choose “Unmount” on your Nexus S.
d) Choose “Install” > Choose “Superuser 3.2_RC.zip”.
e) Choose "Swipe to flash" > Choose “Reboot System”.
f) Nexus S shows now superuser app in launcher. the phone is now rooted. Congratulations... !!!

jai@jai-laptop:~$ adb root
adbd is already running as root
Courtesy: http://forum.xda-developers.com/showthread.php?t=1795167

using app to start wifi adb:
download any of the wifi adb/wireless adb app from the GOOGLE PLAY STORE. I have downloaded "wifi adb" which requires superuser permissions for wifi adb to work.
a) Open the app and click on "Turn On"
b) Grant superuser permissions to the app when prompted.

c) On your PC connect adb using wifi:
$ adb connect 192.168.1.3.:5555
connected to 192.168.1.3:5555 --> on successful connection
$ adb shell
$ cat /proc/kmsg --> to take kernel logs




Hope this helps,
Jai

Friday, October 19, 2012

Creating an overlay on Android Framebuffer

Hey Guys,

Recently I tried something really crazy. I m not really good at Java, so I was trying to find out an easy way of displaying an image on frame buffer without having to write a Java program. Here is how it works

Prerequisites:
1. Phone must be rooted.
2. Android platform build setup ready. I have downloaded the Android jellybean 4.1.1 from source.google.com at $PROJECT = /home/jai/NexusS.


create a folder in lcdtest in $PROJECT/external/ and add the following two files
    $PROJECT/external/lcdtest/lcdtest1.cpp
    $PROJECT/external/lcdtest/Android.mk

lcdtest.cpp looks as follows:

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <sys/ioctl.h>

int main()
{
    int fbfd = 0;
    struct fb_var_screeninfo vinfo;
    struct fb_fix_screeninfo finfo;
    long int screensize = 0;
    char *fbp = 0;
    int x = 0, y = 0;
    long int location = 0;

    // Open the file for reading and writing
    fbfd = open("/dev/graphics/fb0", O_RDWR);  //use "/dev/fb0" in linux
    if (fbfd == -1) {
        perror("Error: cannot open framebuffer device");
        exit(1);
    }
    printf("The framebuffer device was opened successfully.\n");

    // Get fixed screen information
    if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo) == -1) {
        perror("Error reading fixed information");
        exit(2);
    }

    // Get variable screen information
    if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo) == -1) {
        perror("Error reading variable information");
        exit(3);
    }

    printf("%dx%d, %dbpp\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel);

    // Figure out the size of the screen in bytes
    screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
    // Map the device to memory
    fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);
    if ( fbp == NULL) {
        perror("Error: failed to map framebuffer device to memory");
        exit(4);
    }
    printf("The framebuffer device was mapped to memory successfully.\n");

    x = 100; y = 100;       // Where we are going to put the pixel

    // Figure out where in memory to put the pixel
    for (y = 100; y < 200; y++)
        for (x = 100; x < 200; x++) {

            location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) +
                       (y+vinfo.yoffset) * finfo.line_length;

            if (vinfo.bits_per_pixel == 32) {
                *(fbp + location) = 0;100; //100;        // Some blue
                *(fbp + location + 1) = 255;//15+(x-100)/2;     // A little green
                *(fbp + location + 2) = 0;//200-(y-100)/5;    // A lot of red
                *(fbp + location + 3) = 0;      // No transparency
            } else  { //assume 16bpp
                int b = 10;
                int g = (x-100)/6;     // A little green
                int r = 31-(y-100)/16;    // A lot of red
                unsigned short int t = r<<11 | g << 5 | b;
                *((unsigned short int*)(fbp + location)) = t;
            }

        }
    vinfo.activate |= FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE;
    if(0 > ioctl(fbfd, FBIOPUT_VSCREENINFO, &vinfo)) {
    printf("Failed to refresh\n");
    return -1;
    }
    munmap(fbp, screensize);
    close(fbfd);

    return 0;
}



Contents of Android.mk

ifneq ($(TARGET_SIMULATOR), true)

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:=\
    lcdtest1.cpp

LOCAL_CFLAGS:= -g
LOCAL_MODULE:= lcdtest1
LOCAL_MODULE_TAGS := optional

include $(BUILD_EXECUTABLE)

endif


Now the files are ready. To build the file for Nexus S, first setup the build environment as follows.
Go to $PROJECT directory

$ source build/envsetup.sh
$ lunch full_crespo-eng


Now the build environment is ready. To build the android binary in the shell type

$ make -j4 lcdtest1

This would create a binary at out/target/product/crespo/system/bin/lcdtest1

To run this on Nexus, connected the rooted Nexus S device
$ adb remount
$ adb push out/target/product/crespo/system/bin/lcdtest1 system/lib
$ adb reboot


After phone has restarted:
$ adb shell
# lcdtest1

You would see a green overlay patch as shown.

Green patch on top of display

Good luck and Enjoyy !!!!

Sunday, October 7, 2012

Integrating GAPPS in custom binary

Hey Guys,

As I have mentioned in my last post that Google account is not integrated in the custom source that we download from the Android site. I later learnt that this violates the licensing agreement. So we don't get google account integration with the cyanogenmode binaries. So here is a method I found on the internet to integrated the Google account and apps with the custom binary built from the source code:
Now we are ready to flash on the device:
$ fastboot flash recovery recovery-clockwork-6.0.1.0-crespo.img
$ fastboot reboot recovery 

Device in Recovery boot mode
This will install the recovery binary onto your device. Now we can do a recovery boot to browse the menu and install updates from the sdcard. To browse use vol up, vol down and power button.
  • Go down to "mounts and storage" > "mount USB storage"
  • Copy the GAPPS zip gapps-jb-20120726-signed.zip to device sdcard storage.
  • Select "install zip fron sdcard" > "choose zip from sdcard"
  • locate gapps-jb-20120726-signed.zip.
  • Reboot the device. 
Integrated GAPPS to custom binary
Custom binary properties :-P
 Now google apps are integrated to your custom binary.
 - Jai

References:

http://jim-zimmerman.com/?p=821

Saturday, October 6, 2012

Using Fastboot to download binaries

Hey Guys,

Recently I have been experimenting a lot with The Nexus S. I have also compiled Jellybean Source code in my local machine running on Ubuntu 10.04 (64bit). But unfortunately, the build does not allow you to attach google acount to it :-( . And the default google apps like Play store/Gmail/Maps/Gtalk are absent in the binary. Will look for a method to integrate the Market !!!!

Its easier to flash using Odin (just tar the boot.img, system.img, recovery.img and userdata.img) in Windows platform. For Linux we have two options:

1. Use Fastboot (http://source.android.com/source/building-devices.html)
2. Use Heimdall (http://www.glassechidna.com.au/products/heimdall/)

To download binary using Fastboot:
Download the android-sdk from http://developer.android.com/sdk/index.html
Add tools and platform-tools to PATH variable to use it from any location.

$ gedit ~/.bashrc & and add the following line:
export PATH=$PATH:/home/jai/bin:/home/jai/Android/android-sdk-linux/tools:/home/jai/Android/android-sdk-linux/platform-tools

Now, Download the Nexus Factory image binary from https://developers.google.com/android/nexus/images#sojujro03l

Unzip it. It would have the following 5 files:
  1. bootloader-crespo-i9020xxlc2.img - bootloader binary
  2. flash-all.sh - shell script to install radio, bootloader and platform
  3. flash-base.sh - shell command to install radio and bootloader
  4. image-soju-jro03l.zip - the Platform package
  5. radio-crespo-i9020xxki1.img - Radio binary

I have skipped the bootloader and Radio binary, as its not good to mess with the bootloader. The device will be useless if the bootloader is corrupted. So better don't mess with it. Then unzip image-soju-jro03l.zip to get the following files:
  1. android-info.txt
  2. boot.img
  3. recovery.img
  4. system.img
  5. userdata.img

I modified android-info.txt to add a check my bootloader version:
require board=herring
require version-bootloader=I9020XXLC2|I9020XXKL1
require version-baseband=I9020XXKI1|I9020UCKJ1|M200KRKC1
and zipped them to JAI.zip
 zip JAI.zip android-info.txt boot.img recovery.img system.img userdata.img
Now we are ready to flash the binary. Get the device in fastboot mode using the key combination vol up + power button or just type:
fastboot reboot bootloader
fastboot -w update JAI.zip
To flash the binary made from the workspace.
export ANDROID_PRODUCT_OUT=/home/jai/NexusS/out/target/product/crespo/

fastboot -w flashall 
Now my self compiled binary is flashed. It feels great to see it working :-). For any queries mail me.

Jai

Monday, October 1, 2012

Got my Nexus S

Got my Nexus S from Korea today..... !!!!

I just love it...

Its was KOREAN phone ICS 4.0.4..(model: M200) , before I converted it to international version (I9020) by flashing the factory images from Google (https://developers.google.com/android/nexus/images) using ODIN.

The phone bootloaders are generally locked that means one can not flash custom binary till its unlocked. The bootloader can be unlocked by using fastboot tool (<android-sdk>/platform-tools) provided in the android-sdk.

To unlock the bootloader:
1. Get the phone in fastboot mode by pressing the key combination ( Press and hold volume up + Press and hold Power button) or by using adb type
Device in Fastboot mode

 $ adb rebootbootloader
 
2. Unlock the device by 
 $ fastboot oem unlock
 
3. Chose the unlock option from the menu.

Now the device is ready to download custom binary. Now Korean phone can be converted to Non-Korean by just flashing the Platform binary released from Google (https://developers.google.com/android/nexus/images). I downloaded
Factory Images "soju" for Nexus S (worldwide version, i9020t and i9023) version: 4.1.1 (JRO03L) and unzipped it to get boot.img, system.img, recovery.img and userdata.img.

Now to flash the platform binary using Odin:
1. create proper file for the Odin software 
 tar -cvf PLATFORM.tar boot.img system.img recovery.img userdata.img
2. Put the phone in Odin mode using appropriate key combination (Vol up + vol down + power (less than 1 sec and release power) in Nexus S).
Nexus in Odin mode
3. Once the device gets detected in Odin select PLATFORM.tar from PDA and start the download.

After flashing the device is now upgraded to Jellybean 4.1.1 and moreover its a non-Korean phone now.... !!!!

I am gonna dig more into Nexus S.... So many more things yet to come.... !!! ;-)

Jai

Tuesday, January 17, 2012

cross-compiling binaries for Android device on Windows 7/Ubuntu

C language is most commonly used basic programming language. Here is a method to run a C program on an Android device with ARM processor. We cross compile the program on windows machine and generate binary files for ARM. Cross compiling is a method of compiling executable for other platform other than the one in which compiler is run. Here we are creating an executable for ARM device (running Android) platform by compiling on windows. The same method should work on LINUX platform too.

1. Download and CodeSourcery's toolchain installer for IA32 Windows host from https://sourcery.mentor.com/sgpp/lite/arm/portal/release2029 .

2. Install the setup.

3. The toolchain provides the cross compiler arm-none-linux-gnueabi-gcc. Add directory path in default path variables.

4. write a sample program as follows

#include<stdio.h>
int main(){
     printf("\n Hello World! \n");
     return 0;
}
save the program as hello.c

5. compile hello.c as follows from the cmd/terminal:
$ arm-none-linux-gnueabi-gcc -o hello -static hello.c
6. Copy the binary to phone using adb tool or just copy it to phone memory.
$ adb push hello /data
7. There are two methods to run the program
i) Running on linux shell using adb
- open linux shell of the Android device using
$ adb shell
$ cd /data
$ ./hello

//output must be:

 Hello World!
ii) running it on virtual terminal on the Android device.
- download a virtual terminal emulator from android market (https://github.com/jackpal/Android-Terminal-Emulator/wiki)

-open the virtual terminal and run the program.
$ cd /data
$ ./hello

output displayed on terminal:
Hello world!


Its interesting to see the the C programs running on the linux shell. :) :D

Monday, January 16, 2012

Taking kernel and platform logs of an Android device together

I wanted to take both kernel and platform logs of an Android device together. So here is a piece of code that does that.

1. connect the Android target to Windows.
2. start cmd and type
$ adb shell       
$ logcat -v time -f /dev/kmsg | cat /proc/kmsg > /data/klog_plog.txt
$ exit
$ adb pull /data/klog_plog.txt > myfile.txt 

$ adb shell : this command moves user to linux shell of android device. Make sure adb location has been added to path variables in windows.
$ logcat -v time -f /dev/kmsg | cat /proc/kmsg > /data/klog_plog.txt

$logcat -v time prints the platform logs with time stamps. /dev/kmsg is a local buffer.
cat /proc/kmsg gives the kernel logs. So both platform and kernel logs are written to /data/klog_plog.txt

$ adb pull /data/klog_plog.txt > myfile.txt
it pulls the file from the Android device to local drive.

Saturday, January 14, 2012

Changing the default view in Windows File Explorer

I like the "Tiles view" in Windows  explorer. But by default it comes with some other view. So every time I open a new window I had to switch to the tiles view, as I find it comfortable. To avoid this here is a method to chage the default settings.

1. Open Windows explorer (for example My Computer).
2. Change the view to Tiles.


3. Go to tools menu and click Folder Options

4. Go to view tab and click on Apply to folders.


Sunday, June 26, 2011

Installing OpenCV 2.2.0 in Ubuntu 10.10


Here are the detailed steps required to install OpenCV-2.2.0 in Ubuntu 10.10.
1. Download OpenCV from http://sourceforge.net/projects/opencvlibrary/file/opencvunix/2.2/
2. Extract the files in a folder preferably in home folder eg: 'home/jai/OpenCV'.
3. Install the pre-requisites by typing the following in the terminal
$ sudo apt-get install build-essential libgtk2.0-dev libavcodec-dev libavformat-dev libjpeg62-dev libtiff4-dev cmake libswscale-dev libjasper-dev
$ sudo apt-get install cmake-gui
$ sudo apt-get install cmake
4. create a folder 'build' in 'home/OpenCV'
5. start cmake by typing the following in terminal
$ cmake-gui
give “where the source code is” path as 'home/jai/OpenCV'
give “where to build the binaries” path as 'home/jai/OpenCV/build'
configure it till no more red tab appears. Click on generate. This generates the binaries required to install OpenCV in 'home/jai/OpenCV/build'.
6. Go to the build directory in and install OpenCV by typing as follows in the terminal
$ cd ~/jai/OpenCV/build
$ make
$ sudo make install
7. Now to configure the library. First, open the opencv.conf file with the following code:
$ sudo gedit /etc/ld.so.conf.d/opncv.conf
Add the following line at the end of the file(it may be an empty file, that is ok) and then save it:
/usr/local/lib
8. Run the following code to configure the library:
$ sudo ldconfig
9. Now, Open another file:
$ sudo gedit /etc/bash.bashrc
Add the following two lines and save it.
PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig
export PKG_CONFIG_PATH
10. Restart the computer. OpenCV is installed now.


Compiling any OpenCV programs eg- test.cpp:
go to the working directory by using cd in terminal and type the following
$ gcc `pkg-config --libs --cflags opencv` -o test test.cpp
This creates a binary file with name test. To execute it, just type
$ ./test <arguments_if_any>

References:
1. http://opencv.willowgarage.com/wiki/InstallGuide
2. http://www.samontab.com/web/2010/04/installing-opencv-2-1-in-ubuntu/

Wednesday, June 22, 2011

Adding code blocks to a blog (detailed steps)

First you need to backup your blogger template. In your blogger dashboard, click on 'Design' > 'Edit HTML' and then click on 'download full template' and save your template.

  1. Go to Blogger Dashboard > Design > Edit HTML.
  2. Press CTRL+F to find the code </head>
  3. Copy the below code
  4. <!--SYNTAX HIGHLIGHTER BEGINS--> <link href='http://alexgorbatchev.com/pub/sh/current/styles/shCore.css' rel='stylesheet' type='text/css'/> <link href='http://alexgorbatchev.com/pub/sh/current/styles/shThemeDefault.css' rel='stylesheet' type='text/css'/> <script src='http://alexgorbatchev.com/pub/sh/current/scripts/shCore.js' type='text/javascript'></script> <script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCpp.js' type='text/javascript'></script> <script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCSharp.js' type='text/javascript'></script> <script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCss.js' type='text/javascript'></script> <script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJava.js' type='text/javascript'></script> <script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJScript.js' type='text/javascript'></script> <script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPhp.js' type='text/javascript'></script> <script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPython.js' type='text/javascript'></script> <script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushRuby.js' type='text/javascript'></script> <script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushSql.js' type='text/javascript'></script> <script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushVb.js' type='text/javascript'></script> <script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushXml.js' type='text/javascript'></script> <script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPerl.js' type='text/javascript'></script> <script language='javascript'> SyntaxHighlighter.config.bloggerMode = true; SyntaxHighlighter.config.clipboardSwf = 'http://alexgorbatchev.com/pub/sh/current/scripts/clipboard.swf'; SyntaxHighlighter.all(); </script> <!--SYNTAX HIGHLIGHTER ENDS-->
  5. Paste it on top of </head> this code.
  6. Preview your template and if everything works fine, then save it.
Make the script work

You have just added the script to your blog. If you want to highlight code in your post, then you need to use the following method in order to make your Syntax Highlighter work properly..

In <pre> method... when writing a new post, you need to use <pre> tag in the post. The code of your post needs to go in between <pre class="brush:html"> and </pre> tags, in order to highlight your code properly.

    Tuesday, June 21, 2011