Tuesday, March 29, 2011

"Cannot find 'make' program. Please install Cygwin make package" ?

Today I was trying to install Cygwin from in my Machine. I was lazy to download the whole thing and install, so i copied it from a another machine. Then when i ran Ant Release i got this error. After few mins it clicked me to set the environment variables.

1. Set the environment variable CYGWIN=nodosfilewarning
2. Set c:\cygwin\bin to PATH variable
3. Set NDK_ROOT environment variable to point there.

Thursday, March 24, 2011

Recursive (Sub directory) File System Watcher in Android.

Today, I was looking into monitoring directory changes in Android. It looks like FileObserver class in Android does not support recursive sub-directory watching even though it uses Linux internal "inotify".

Android documentations says:

Each FileObserver instance monitors a single file or directory. If a directory is monitored, events will be triggered for all files and subdirectories (recursively) inside the monitored directory.

But it does not work this way.

Anyway, then I looked in more and found
here it's been reported to Google and they have fixed it in 2.3 or 3.0 it seems. I tried to integrate the same code into my code and it failed because it's using Native functions.

Then I found this code on here with few compile errors, then i fixed it and thought of posting it here, because it might help someone else time.

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
import android.os.FileObserver;
import android.util.Log;


public class RecursiveFileObserver extends FileObserver
{
/** Only modification events */
public static int CHANGES_ONLY = CREATE | DELETE | CLOSE_WRITE | MOVE_SELF
| MOVED_FROM | MOVED_TO;

List mObservers;
String mPath;
int mMask;

public RecursiveFileObserver(String path)
{
this(path, ALL_EVENTS);
}

public RecursiveFileObserver(String path, int mask)
{
super(path, mask);
mPath = path;
mMask = mask;
}

@Override
public void startWatching()
{
if (mObservers != null)
return ;

mObservers = new ArrayList();
Stack stack = new Stack();
stack.push(mPath);

while (!stack.isEmpty())
{
String parent = String.valueOf(stack.pop());
mObservers.add(new SingleFileObserver(parent, mMask));
File path = new File(parent);
File[]files = path.listFiles();
if (null == files)
continue;
for (File f: files)
{
if (f.isDirectory() && !f.getName().equals(".") && !f.getName()
.equals(".."))
{
stack.push(f.getPath());
}
}
}

for (SingleFileObserver sfo: mObservers)
{
sfo.startWatching();
}
}

@Override
public void stopWatching()
{
if (mObservers == null)
return ;

for (SingleFileObserver sfo: mObservers)
{
sfo.stopWatching();
}
mObservers.clear();
mObservers = null;
}

@Override
public void onEvent(int event, String path)
{
switch (event)
{
case FileObserver.ACCESS:
Log.i("RecursiveFileObserver", "ACCESS: " + path);
break;
case FileObserver.ATTRIB:
Log.i("RecursiveFileObserver", "ATTRIB: " + path);
break;
case FileObserver.CLOSE_NOWRITE:
Log.i("RecursiveFileObserver", "CLOSE_NOWRITE: " + path);
break;
case FileObserver.CLOSE_WRITE:
Log.i("RecursiveFileObserver", "CLOSE_WRITE: " + path);
break;
case FileObserver.CREATE:
Log.i("RecursiveFileObserver", "CREATE: " + path);
break;
case FileObserver.DELETE:
Log.i("RecursiveFileObserver", "DELETE: " + path);
break;
case FileObserver.DELETE_SELF:
Log.i("RecursiveFileObserver", "DELETE_SELF: " + path);
break;
case FileObserver.MODIFY:
Log.i("RecursiveFileObserver", "MODIFY: " + path);
break;
case FileObserver.MOVE_SELF:
Log.i("RecursiveFileObserver", "MOVE_SELF: " + path);
break;
case FileObserver.MOVED_FROM:
Log.i("RecursiveFileObserver", "MOVED_FROM: " + path);
break;
case FileObserver.MOVED_TO:
Log.i("RecursiveFileObserver", "MOVED_TO: " + path);
break;
case FileObserver.OPEN:
Log.i("RecursiveFileObserver", "OPEN: " + path);
break;
default:
Log.i("RecursiveFileObserver", "DEFAULT(" + event + ";) : " +
path);
break;
}
}

/**
* Monitor single directory and dispatch all events to its parent, with full path.
*/
class SingleFileObserver extends FileObserver
{
String mPath;

public SingleFileObserver(String path)
{
this(path, ALL_EVENTS);
mPath = path;
}

public SingleFileObserver(String path, int mask)
{
super(path, mask);
mPath = path;
}

@Override public void onEvent(int event, String path)
{
String newPath = mPath + "/" + path;
RecursiveFileObserver.this.onEvent(event, newPath);
}
}
}


How to use
-----------

RecursiveFileObserver mObserver;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

File DIRECTORY_DCIM = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);

mObserver = new RecursiveFileObserver(DIRECTORY_PICTURES.getAbsolutePath(), RecursiveFileObserver.CREATE);
mObserver.startWatching();

Toast.makeText(getApplicationContext(), "Watching " + DIRECTORY_PICTURES.getAbsolutePath(), Toast.LENGTH_LONG).show();
}


Android 0, Me 1 :)

Tuesday, March 22, 2011

Reading Emails in Android.

Today I was trying to hack into Android EMail client. When i tried to pull out something from the content://com.android.email.provider/account Uri, i am always throwing an exception like this,

java.lang.SecurityException: Permission Denial: reading com.android.email.provider.EmailProvider uri content://com.android.email.provider/account requires com.android.email.permission.ACCESS_PROVIDER

so decided to decomplie the Android EmailGoogle.apk file :D which contains the classes for com.android.email namespace

AndroidManifest.xml definition looks like this,




It looks like content provider can only be accessed by either the system, or by applications signed with the same key. So my dreams were shattered.

Android 1, Me 0 :|

Tuesday, March 15, 2011

How to export Outlook contacts to Android ?

I used to keep all my contacts on Outlook and today I wanted to sync all my contacts with my Android phone and i could not find a easy way to do it. Finally found a easy work around.

1. Open Outlook -> Select Contacts -> Select all contacts (Ctrl + A) -> Right Click -> Send As Business Card
2. This will popup a new email message window with all the contacts attached.
3. Save all the contacts to a folder.
4. Plug Android phone to PC - Select Disk Drive
5. copy above folder into android SD Card.
6. Open People/Contacts in android.
7. Press Menu Key -> Select Import from SD Card. This will look for all the vCard files in the phone.
8. Then you can select import all or one by one.

good luck

Monday, March 14, 2011

how to send a MMS programmatically in Android

Last couple of day I have been researching on how to send a MMS in android without using Intents, to be honest it is not an easy task and help on Google is limited on this case.

However, one post on stackoverflow.com which helped me immensely.

http://stackoverflow.com/questions/2972845/i-want-send-image-through-using-mms-in-android/2973016#2973016

it seems to be author has looked into the android MMS source code and provided vital information on how to send a MMS. For me, being a rookie hooking up all the MMS code in my project seems to be a nightmare.

When i further look, I found a nice library called "jmmslib" here

which can be directly used in Android to create a MMS but in my cause i found it not to be working very well because sometimes it works, sometime not. (may be something wrong with my code) but it was giving me a hard time and had to look for a better solution.

Then, I found a Nokia Java based MMS impelmentation. You can found it here

you can download the my source code here.
https://github.com/kakopappa/AndroidMMS


Update - 2013-09-17

I just saw TextSecure app is sending MMS messages.. You can find the code here

You guys can use http://androidshell.io/ to connect to remote android devices

Tuesday, March 8, 2011

How to read a file in bytes - Android

private static final int BUFFER_SIZE = 0x1000; // 4K

FileInputStream fin;

try {
fin = new FileInputStream(directory);
BufferedInputStream bis = new BufferedInputStream(fin);
DataInputStream dis = new DataInputStream(bis);
byte fileContent[] = toByteArray(dis);
}
catch(Exception e)
{
}

public static byte[] toByteArray(InputStream in) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
copy(in, out);
return out.toByteArray();
}


public static long copy(InputStream from, OutputStream to) throws IOException {
byte[] buf = new byte[BUFFER_SIZE];
long total = 0;
while (true) {
int r = from.read(buf);
if (r == -1) {
break;
}
to.write(buf, 0, r);
total += r;
}
return total;
}