Saturday, January 26, 2008

I needed to load remote images to my application and bind this image to an ImageView object. HttpURLConnection is used to download the image data and BitmapFactory is used to produce the bitmap which will be used as imageview resources.

Here is the layout file

XML:

< ?xml version="1.0" encoding="utf-8"?>
< LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
< TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, HTTPImage load test"
/>
< Button id="@+id/get_imagebt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Get an image"
android:layout_gravity="center"
/>
< ImageView id="@+id/imview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
/>
< /LinearLayout>


The java code goes like it


import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;

public class HTTPTest extends Activity {


ImageView imView;
String imageUrl="http://11.0.6.23/";
Random r;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
r= new Random();

Button bt3= (Button)findViewById(R.id.get_imagebt);
bt3.setOnClickListener(getImgListener);
imView = (ImageView)findViewById(R.id.imview);
}

View.OnClickListener getImgListener = new View.OnClickListener()
{

@Override
public void onClick(View view) {
// TODO Auto-generated method stub

//i tried to randomize the file download, in my server i put 4 files with name like
//png0.png, png1.png, png2.png so different file is downloaded in button press
int i =r.nextInt()%4;
downloadFile(imageUrl+"png"+i+".png");
Log.i("im url",imageUrl+"png"+i+".png");
}

};


Bitmap bmImg;
void downloadFile(String fileUrl){
URL myFileUrl =null;
try {
myFileUrl= new URL(fileUrl);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
HttpURLConnection conn= (HttpURLConnection)myFileUrl.openConnection();
conn.setDoInput(true);
conn.connect();
int length = conn.getContentLength();
int[] bitmapData =new int[length];
byte[] bitmapData2 =new byte[length];
InputStream is = conn.getInputStream();

bmImg = BitmapFactory.decodeStream(is);
imView.setImageBitmap(bmImg);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}


The code is pretty simple and easy, most of you might already have done this, i am a slow learner, i tried different ways first, i tried to read the whole bytes of image data, do other trial and error method. I was confused about the Bitmap tranformation technology. Then i found that there is a built in class known as BitmapFactory, it can produce bitmap directly from stream. This saved a lot of my efforts. Hope it will come useful to you.

Happy andcoding :)

Friday, January 25, 2008

Yesterday, the whole day i was trying to post a file to a php server. The whole day and evening i tried and failed. I googled, searched in forum and did a lot of other stuffs. I couldn't succed, at last when i was frustrated on me, then i found another tutorial in a forum, this time it worked. mu ha ha :) (Copy paste rulllzz, so i should never try myself anything :(). The code simulates file posting to a php server. So it will work with servers where file upload from a server is supported. Here goes the code

The php code used in server

< ?php

$target_path = "uploads/";

$target_path = $target_path . basename( $_FILES['uploadedfile']['name']);

if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) {
echo "The file ". basename( $_FILES['uploadedfile']['name']).
" has been uploaded";
} else{
echo "There was an error uploading the file, please try again!";
}

? >


The android code goes here

import java.io.BufferedInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

import org.apache.commons.codec.binary.Base64;
import org.apache.http.util.ByteArrayBuffer;

import android.util.Log;

public class HttpFileUploader implements Runnable{

URL connectURL;
String params;
String responseString;
InterfaceHttpUtil ifPostBack;
String fileName;
byte[] dataToServer;

HttpFileUploader(String urlString, String params, String fileName ){
try{
connectURL = new URL(urlString);
}catch(Exception ex){
Log.i("URL FORMATION","MALFORMATED URL");
}
this.params = params+"=";
this.fileName = fileName;

}


void doStart(FileInputStream stream){
fileInputStream = stream;
thirdTry();
}

FileInputStream fileInputStream = null;
void thirdTry(){
String exsistingFileName = "asdf.png";

String lineEnd = "\r\n";
String twoHyphens = "--";
String boundary = "*****";
String Tag="3rd";
try
{
//------------------ CLIENT REQUEST

Log.e(Tag,"Starting to bad things");
// Open a HTTP connection to the URL

HttpURLConnection conn = (HttpURLConnection) connectURL.openConnection();

// Allow Inputs
conn.setDoInput(true);

// Allow Outputs
conn.setDoOutput(true);

// Don't use a cached copy.
conn.setUseCaches(false);

// Use a post method.
conn.setRequestMethod("POST");

conn.setRequestProperty("Connection", "Keep-Alive");

conn.setRequestProperty("Content-Type", "multipart/form-data;boundary="+boundary);

DataOutputStream dos = new DataOutputStream( conn.getOutputStream() );

dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"uploadedfile\";filename=\"" + exsistingFileName +"\"" + lineEnd);
dos.writeBytes(lineEnd);




Log.e(Tag,"Headers are written");

// create a buffer of maximum size

int bytesAvailable = fileInputStream.available();
int maxBufferSize = 1024;
int bufferSize = Math.min(bytesAvailable, maxBufferSize);
byte[] buffer = new byte[bufferSize];

// read file and write it into form...

int bytesRead = fileInputStream.read(buffer, 0, bufferSize);

while (bytesRead > 0)
{
dos.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
}

// send multipart form data necesssary after file data...

dos.writeBytes(lineEnd);
dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);

// close streams
Log.e(Tag,"File is written");
fileInputStream.close();
dos.flush();

InputStream is = conn.getInputStream();
// retrieve the response from server
int ch;

StringBuffer b =new StringBuffer();
while( ( ch = is.read() ) != -1 ){
b.append( (char)ch );
}
String s=b.toString();
Log.i("Response",s);
dos.close();


}
catch (MalformedURLException ex)
{
Log.e(Tag, "error: " + ex.getMessage(), ex);
}

catch (IOException ioe)
{
Log.e(Tag, "error: " + ioe.getMessage(), ioe);
}
}

}

Many of the headers included in the above file is not required, i was trying and failing :).

Now to upload file here is the java code from my activity class


public void uploadFile(){


try {
FileInputStream fis =this.openFileInput(NAME_OF_FILE);
HttpFileUploader htfu = new HttpFileUploader("http://11.0.6.23/test2.php","noparamshere", NAME_OF_FILE);
htfu.doStart(fis);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}



The main advantage is that the way it posts data to the server is similar to a Html Form posting data to a php server. Hope it might be useful for me in future, so i blogged it, if others are helped then that would be great.You can visit www.anddev.org for more and more tutorials. Thanks for reading my bad post :)

Tuesday, January 22, 2008

Did you ever fall in loop when traversing through activities, like one activity launching another and the other launching the previous one, then back pressing returns to that activity. This can be prevented very easily, when you think that the second activity is no more required, you just can call finish() function of that activity. This will solve some problems, though this looping happens only to bad programmers like me :D. Here is an interesting thing, when a subactivity finishes it's job it can send data back to the main activity who started it, for this the main activity has to override a function like this

@Override
protected void onActivityResult(int requestCode, int resultCode,
String data, Bundle extras) {
// TODO Auto-generated method stub
//super.onActivityResult(requestCode, resultCode, data, extras);
if(requestCode == SOME_INTEGER_WHICH_WAS_USED_DURING_CREATION_OF_ACTIVITY_AS_INTEGER_PARAM+OF_INTENT){
String text = "";

// This is a standard resultCode that is sent back if the
// activity doesn't supply an explicit result. It will also
// be returned if the activity failed to launch.
if (resultCode == RESULT_CANCELED) {
text ="Canceled";

// Our protocol with the sending activity is that it will send
// text in 'data' as its result.
} else {
if (data != null) {
text = data;
}
}
}
}


So when finish() function is called from subactivity, this function is called in mainActivity. This code is executed during returning from subactivity class.


setResult(RESULT_OK, "SOMETEXT");
finish();

Most of the codes are copied from APIDemos.

Launching an activity is not all. After launching another subactivity/activity you might want to send some data/parameter to that activity. This is done in a new way known as Bundle. To launch an activity we create an intent. Suppose our intent name is "intent". We can put data with the intent like this

intent.putExtra("keyName", "somevalue");

We can add multiple entries here. This is a key,value pair. So to receive this data from the receiving activity we have to write this code

Bundle extras = getIntent().getExtras();
if(extras !=null)
{
String value = extras.getString("keyName");
}


This is how we can send data to another activity, here simple string is sent, complex structures like array can be also sent through bundle. Didn't use those as i am a bad bad programmmer and very bad at reading documentations ;).

Sunday, January 6, 2008

First create a class extending some activity(Activity/ListActivity/MapActivity etc).
You have to put this activity reference in AndroidManifest xml file like this


< activity class=".nameOfTheClass" / >


so that android can find this activity.

To lauch an activity from an activity, here is a simple code.

Intent i = new Intent(this, newActivity.class);
startSubActivity(i, ACTIVITY_CREATE);

Here Activity_create is a simple integer declared.

I don't know the details so i am not going into those, i understand nothing, i can do copy paste well :D. And google is there ;).

Saturday, January 5, 2008

It's so much easy to show map in Android, just 4 lines of code. In eclipse, create an Android project, in the projects main class extend it by MapActivity. Then in main layout file (main.xml) add the following lines


android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1" />


The java file will look something like it

public class MapViewer extends MapActivity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
}
}


Fix imports by pressing Ctrl+Shift+O
Run the project, u will see the map, no key event is attached so use your mouse to
move or zoomin/out.

Here is the source code

Friday, January 4, 2008

Happy New Year


New year, new journey, new company , new jobs , new works , new learning , new tensions and new challenges. Everything is new but we can't forget the good old days !!!

Happy New Year , let the game begin.

Recently i was in a nasty problem. Whenever i started my emulator it was showing some error message and said that it could not start this/that. And whenever i wanted to access contacts it was showing exceptions. So i started to do what i do, that is googling.

After some googling i decided to remove all the applications installed in my emulator. And that was very easy too. After erasing it all worked well.

Now how to erase those apps,
Go to the home directory of your android sdk through command prompt. Then go to tools. Then in command window type "emulator -wipe-data" and press enter. This will remove all the datas/apps installed in emulator. It solved my exception problems.

How to erase single application from command line:

First,make sure the emulator is running.Then follow below steps:
1. go to tools directory in command
2. adb shell
3. cd /data/app
4. ls (It will display all the .apk installed in your emulator)
5. rm ***.apk(which you want to remove)
6. exit


Check this link

Here is a good article on how to launch an activity during startup of the emulator

launch on startup

You can test the startup by going to the home_directory_of_android_sdk/tools/ then run the emulator.exe, you will see your startup application running after loading the emulator.