Tuesday, November 20, 2012

Java Calculator

Hi all!
         This is my first time posting to the REGNARTS blog.
So, this post as is rightfully titled, explains java applet through a simple calculator program which takes in 2 numbers, adds, subtracts, multiplies and divides them. Also it checks for possible errors in the input of the 2 numbers and displays the error if any.

PRE-REQUISITES: A little java education along with the concept of classes and a little experience with the eclipse java ide. For those who want to download the eclipse ide, the link's here.

Now lets look at the program,


If you see the first few lines before the commented boundary in green, they are called packages. Packages are collections of  related classes and interfaces(You'll learn about interfaces in an another post maybe. :P ) eg) to develop windows programs, applets, networking etc. The Java API consists of many such packages. Here "awt" means Abstract Window Tools, "applet" includes all those methods (btw functions in java are called methods) which are required to run this Applet, and "awt.event" controls any action performed within the applet window.

Now after the green commented boundary you'll see a line "public class AplNum extends Applet implements ActionListener". Here public class means objects of this class can be created in different files that are in the same folder as this file. If you are using some other editor then its important to name the file same as the name of the public class in the file in the file. Same reason you can have only one public class in one java file. Now the name of a class has to start with a capital letter as per proper java standards. It extends Applet implies it inherits properties and elements from the class Applet. The term applet is used for small java apps that are usually used for web designing. And finally it implements ActionListener implies the Applet runs the methods in ActionListener interface, that is used to detect any action happening inside the applet window. It contains one method which we are supposed to redefine in our code called as the "actionPerformed". Again first letter of any method is small case as per java standards!

Now inside the class we declare the members of the class, that is labels, buttons and textfields. Where label is used to display a msg, button used to click on something, and textfield is used to input and output data. Notice that all label elements have their names prefixed with 'l', buttons with 'b' and textfields with 't'. That is good program organisation for you!
now we discuss the init() function which is used to create the Applet. In this function you initialise the various members you have already created. first you use GridLayout to brand a layout to the applet. GridLayout gives a table like layout. Here it gives 8 row, 2 column table, with 15 pixel horizontal spacing and 10 pixel vertical spacing between the members. setSize is used to set the size of the applet window. The members are then added in order to the table. For a label, we initialise it to a default text supplied in "" inside the brackets. Textfields are initialised to size of text allowed in the textfield. And if that textfield is not used for inputting then we need to disallow editing using setEditable(false). And buttons are initialised to default display text. addActionListener(this) implies action performed on those members are detected by the actionListener interface. Finally add() is used to add the member to the respective record in the layout. Like this all members of the class are intitialised.

Now lets check the next function used to input numbers and check for errors!
Try catching is an error handling mechanism in java. Here if any error occurs in java, that catch statement is executed that has the erroneous object as its parameter. getNos() function returns true if the inputs are correct and returns false if inputs are wrong. Here flag is set to false meaning default assumption is that the input is erroneous. Then inside try{} we use getText() of textfield to get any string entered in that textfield. Then we use Integer.parseInt() to convert the string into number. If the string doesnt just contain numbers then it throws an error. All errors belong to the Exception class. This error is caught and respective steps are taken to handle it. In this case, we set the format using different functions and display the error msg in tmsg and clear up the tnum1 and tnum2 for further input.If all the numbers are entered correctly then tmsg is cleared.

Now that we have safely input the numbers, lets look at the actionPerformed function that I previously said we need to redefine to suit our code.
First it checks for the integrity of the input numbers given. Then it displays the respective results. If you click the add button, the actionListener gets activated and it raises the actionPerformed function and if the source of the action is the add Button, the sum will be displayed and an "Addition successfull" msg is shown. Same thing goes for subtract, multiply and divide with respective solutions and msges. But for division it also checks for divide by zero error!

Now that you've written the project, compile and run it in eclipse and you will get the following applet window:
I've already performed the operations so you'll see all the textfields are full!
Now for those who want to run the applet though command prompt and you already have jdk installed in your system and your classpaths set up you can first create the following html file named AplNum.html:
then run the command: javac AplNum.java to compile the file and give the class file. then run the command: AppletViewer AplNum.html in your command window and poof! you'll get the same applet window!
I seriously hope you people try it out, and please comment you're reviews about the post and the program!
Also, I have a question for you, Which editor have I used to code the above program? Answer to win a chance to acquire some guaranteed goodies! :)
I thank Regnarts for allowing me to post on his blog.
Dude, you are not always awesome but then that's the beauty of it! ;)
Yours,
anty_kryst
Follow me at twitter "@anty_kryst" or on facebook "antykrissh".
Bye!

Friday, October 19, 2012

Audio Amplifier | LM386

I managed to create a basic audio amplifier using the IC LM386. This post is just a walk through to the creation. LM386 is a very good audio amp, but sometimes it tends to oscillate at low frequencies hence producing a lot of unwanted noise. The basic circuit is

Put this on a bread board. And connect a 3.5mm jack to the other end to input Vin. Use a coupling capacitor of possibly 10uF. The 10K Pot is to control the intensity. Use Vcc of around 9V. I've used a 8ohm speaker.





There is one more mode according to the datasheet. This is supposed to provide a gain of 200.



Sometimes when the gain is more the output is distorted. Be sure to keep that in mind. It is not that powerful. I've always had a hard time handling it, lot of distortions and noise. Check out other modes, experiment, enjoy.




Thursday, October 18, 2012

Android app building | Android Camera

There have been a lot of posts on this blog relating to android but none of them say anything about android application development. This is the first one to be talking about android application development. Yes that's right ".apk". Though its customary for you to build a "Hello, World!" program whenever you start to learn some new language, I took a small detour to teach you guys how easy it will be to utilize real hardware on your phone. This post will outline an app to take pictures from your phone camera("Yes!, it does the same work as your default camera app").

If you don't have Android SDK downloaded and installed along with Eclipse. And ADT plugin configured with it. Do it fast.

Now fire up your IDE and create a new project with appropriate name. Now that we want to create a camera app, let's see what google has to offer. Android has a page to describe building a camera app, nice!!.

The first snippet it gives is to detect the camera availability. It runs like this.


/** Check if this device has a camera */
private boolean checkCameraHardware(Context context) {
    if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
        // this device has a camera
        return true;
    } else {
        // no camera on this device
        return false;
    }
}

This is a really useful piece of code I decided to put out of my program, becoz I know my phone has a camera(lol). Anyways if you want to check out run it in your program. The next code is to get an instance of the camera. You'll obviously need it in your program.


/** A safe way to get an instance of the Camera object. */
public static Camera getCameraInstance(){
    Camera c = null;
    try {
        c = Camera.open(); // attempt to get a Camera instance
    }
    catch (Exception e){
        // Camera is not available (in use or does not exist)
    }
    return c; // returns null if camera is unavailable
}

Now here is something that you must know. Android handles camera as an OBJECT. So this code creates a camera object and calls the associated function camera.open(). This creates an exception if the camera doesn't exist or the resource isn't available (Some other program utilizing it). Now your layout will typically look like this over eclipse


We need to change this (obviously!!) to display our camera. We'll add a frame to the display to make a viewfinder out of it.


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    
     <FrameLayout
         android:id="@+id/camera_preview"
         android:layout_width="fill_parent"
         android:layout_height="fill_parent"
         android:layout_alignParentLeft="true"
         android:layout_alignParentTop="true"
         />
     
      <Button
             android:id="@+id/button_capture"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:gravity="center|left"
             android:text="capture" />

   
</RelativeLayout>

Now that you have a button that says capture and a frame to display the camera view. It must pretty much look like this.

We'll come back to refining this later. Now let us add the code to the main program. Eclipse has created initial code for me, that runs like this

package com.regnartstranger.cam;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;

public class Cam extends Activity {

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

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_cam, menu);
        return true;
    }
}


Adding up our program to get the camera resource. Now the file is


Observe that we haven't declared the variable camera that is giving us an error. So create an object to hold our camera. We'll call it camera itself(yes, because we have already started using the name).


package com.regnartstranger.cam;

import android.hardware.Camera;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;

public class Cam extends Activity {

private String TAG = "Cam";
private Camera camera;

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

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_cam, menu);
        return true;
    }
    
    public void getCameraResource(){
    try{
        camera = Camera.open();
        }catch(Exception ioe)
        {
        Log.d(TAG,ioe.getMessage());
        }
    }
}



Notice that I've also used a TAG and updated the log on error(Like a good programmer should). Also note the extra importing of the android.hardware.camera that the eclipse has done for me(Thank you!). Now to create a preview, the developer website list's it to be a class called preview class


/** A basic Camera preview class */
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
    private SurfaceHolder mHolder;
    private Camera mCamera;

    public CameraPreview(Context context, Camera camera) {
        super(context);
        mCamera = camera;

        // Install a SurfaceHolder.Callback so we get notified when the
        // underlying surface is created and destroyed.
        mHolder = getHolder();
        mHolder.addCallback(this);
        // deprecated setting, but required on Android versions prior to 3.0
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    public void surfaceCreated(SurfaceHolder holder) {
        // The Surface has been created, now tell the camera where to draw the preview.
        try {
            mCamera.setPreviewDisplay(holder);
            mCamera.startPreview();
        } catch (IOException e) {
            Log.d(TAG, "Error setting camera preview: " + e.getMessage());
        }
    }

    public void surfaceDestroyed(SurfaceHolder holder) {
        // empty. Take care of releasing the Camera preview in your activity.
    }

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        // If your preview can change or rotate, take care of those events here.
        // Make sure to stop the preview before resizing or reformatting it.

        if (mHolder.getSurface() == null){
          // preview surface does not exist
          return;
        }

        // stop preview before making changes
        try {
            mCamera.stopPreview();
        } catch (Exception e){
          // ignore: tried to stop a non-existent preview
        }

        // set preview size and make any resize, rotate or
        // reformatting changes here

        // start preview with new settings
        try {
            mCamera.setPreviewDisplay(mHolder);
            mCamera.startPreview();

        } catch (Exception e){
            Log.d(TAG, "Error starting camera preview: " + e.getMessage());
        }
    }
}


To display the picture on the screen we use SurfaceView. SurfaceView is a class in android that can be used to paint a canvas to the screen. To use it we create a new class that inherits SurfaceView and implements its call back. So the functions surfacecreated, surfacedestoryed, surfacechanged implement these call backs. We initialize the class by creating a camera object, a holder for the Surface and adding callback to that holder.
Now using the same code into our app. We get


package com.regnartstranger.cam;

import java.io.IOException;

import android.hardware.Camera;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.util.Log;
import android.view.Menu;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class Cam extends Activity {

private String TAG = "Cam";
private Camera camera;

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

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_cam, menu);
        return true;
    }
    /** A basic Camera preview class */
    public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
        private SurfaceHolder mHolder;
        private Camera mCamera;

        public CameraPreview(Context context, Camera camera) {
            super(context);
            mCamera = camera;
            mHolder = getHolder();
            mHolder.addCallback(this);
            mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        }

        public void surfaceCreated(SurfaceHolder holder) {
            try {
                mCamera.setPreviewDisplay(holder);
                mCamera.startPreview();
            } catch (IOException e) {
                Log.d(TAG, "Error setting camera preview: " + e.getMessage());
            }
        }

        public void surfaceDestroyed(SurfaceHolder holder) {
        }

        public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {

            if (mHolder.getSurface() == null){
              return;
            }

            try {
                mCamera.stopPreview();
            } catch (Exception e){
            }


            try {
                mCamera.setPreviewDisplay(mHolder);
                mCamera.startPreview();

            } catch (Exception e){
                Log.d(TAG, "Error starting camera preview: " + e.getMessage());
            }
        }
    }
    
    public void getCameraResource(){
    try{
        camera = Camera.open();
        }catch(Exception ioe)
        {
        Log.d(TAG,ioe.getMessage());
        }
   
    }
}



Now to create a preview in the screen, we need to create an object that handles it. It is called camerapreview. So adding these three lines of code sets up the camera view activity.


 mPreview = new CameraPreview(this, camera);
 FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
 preview.addView(mPreview);

The whole code looks like this now


package com.regnartstranger.cam;

import java.io.IOException;
import android.hardware.Camera;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.util.Log;
import android.view.Menu;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.FrameLayout;

public class Cam extends Activity {

private String TAG = "Cam";
private Camera camera;
public CameraPreview mPreview;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_cam);
        getCameraResource();
        mPreview = new CameraPreview(this, camera);
        FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
        preview.addView(mPreview);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_cam, menu);
        return true;
    }
    /** A basic Camera preview class */
    public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
        private SurfaceHolder mHolder;
        private Camera mCamera;

        public CameraPreview(Context context, Camera camera) {
            super(context);
            mCamera = camera;
            mHolder = getHolder();
            mHolder.addCallback(this);
            mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        }

        public void surfaceCreated(SurfaceHolder holder) {
            try {
                mCamera.setPreviewDisplay(holder);
                mCamera.startPreview();
            } catch (IOException e) {
                Log.d(TAG, "Error setting camera preview: " + e.getMessage());
            }
        }

        public void surfaceDestroyed(SurfaceHolder holder) {
        }

        public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {

            if (mHolder.getSurface() == null){
              return;
            }

            try {
                mCamera.stopPreview();
            } catch (Exception e){
            }


            try {
                mCamera.setPreviewDisplay(mHolder);
                mCamera.startPreview();

            } catch (Exception e){
                Log.d(TAG, "Error starting camera preview: " + e.getMessage());
            }
        }
    }
    
    public void getCameraResource(){
    try{
        camera = Camera.open();
        }catch(Exception ioe)
        {
        Log.d(TAG,ioe.getMessage());
        }
   
    }
}

At this point if you just add android.permission.CAMERA to the manifest file you'll be able to run the program.


The camera now looks like this. If you want to capture a photograph all you need to do is to implement a callback method to save the photograph to a file in memory. The callback is described in the developer website as

private PictureCallback mPicture = new PictureCallback() {

    @Override
    public void onPictureTaken(byte[] data, Camera camera) {

        File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
        if (pictureFile == null){
            Log.d(TAG, "Error creating media file, check storage permissions: " +
                e.getMessage());
            return;
        }

        try {
            FileOutputStream fos = new FileOutputStream(pictureFile);
            fos.write(data);
            fos.close();
        } catch (FileNotFoundException e) {
            Log.d(TAG, "File not found: " + e.getMessage());
        } catch (IOException e) {
            Log.d(TAG, "Error accessing file: " + e.getMessage());
        }
    }
};

Add this to your code.It would finally look like this


package com.regnartstranger.cam;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.os.Bundle;
import android.os.Environment;
import android.app.Activity;
import android.content.Context;
import android.util.Log;
import android.view.Menu;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.FrameLayout;

public class Cam extends Activity {

private String TAG = "Cam";
private Camera camera;
public CameraPreview mPreview;
public Button captureButton;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_cam);
        getCameraResource();
        captureButton = (Button) findViewById(R.id.button_capture);
        mPreview = new CameraPreview(this, camera);
        FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
        preview.addView(mPreview);
        captureButton.setOnClickListener(
           new View.OnClickListener() {
               public void onClick(View v) {
                   // get an image from the camera
                   camera.takePicture(null, null, mPicture);
               }
           }
        );
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_cam, menu);
        return true;
    }
    private PictureCallback mPicture = new PictureCallback() {

        public void onPictureTaken(byte[] data, Camera camera) {
        File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "MyCameraApp");
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        File mediaFile;
            mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_"+ timeStamp + ".jpg");

            if (mediaFile == null){
                Log.d(TAG, "Error creating media file, check storage permissions\n");
                return;
            }

            try {
                FileOutputStream fos = new FileOutputStream(mediaFile);
                fos.write(data);
                fos.close();
            } catch (FileNotFoundException e) {
                Log.d(TAG, "File not found: " + e.getMessage());
            } catch (IOException e) {
                Log.d(TAG, "Error accessing file: " + e.getMessage());
            }
        }
    };
    /** A basic Camera preview class */
    public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
        private SurfaceHolder mHolder;
        private Camera mCamera;

        public CameraPreview(Context context, Camera camera) {
            super(context);
            mCamera = camera;
            mHolder = getHolder();
            mHolder.addCallback(this);
            mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        }

        public void surfaceCreated(SurfaceHolder holder) {
            try {
                mCamera.setPreviewDisplay(holder);
                mCamera.startPreview();
            } catch (IOException e) {
                Log.d(TAG, "Error setting camera preview: " + e.getMessage());
            }
        }

        public void surfaceDestroyed(SurfaceHolder holder) {
        }

        public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {

            if (mHolder.getSurface() == null){
              return;
            }

            try {
                mCamera.stopPreview();
            } catch (Exception e){
            }


            try {
                mCamera.setPreviewDisplay(mHolder);
                mCamera.startPreview();

            } catch (Exception e){
                Log.d(TAG, "Error starting camera preview: " + e.getMessage());
            }
        }
    }
    
    public void getCameraResource(){
    try{
        camera = Camera.open();
        }catch(Exception ioe)
        {
        Log.d(TAG,ioe.getMessage());
        }
   
    }
}


Add the permission to write to sdcard [android.permission.WRITE_EXTERNAL_STORAGE]. Now you are good to go. Run the app once, you must be able to click pictures.

To create a more formal looking app. Add android:theme="@android:style/Theme.NoTitleBar.Fullscreen" under application in the manifest file. And android:screenOrientation="landscape" under activity. It must finally look like this.


<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.regnartstranger.cam"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="15" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.CAMERA"/>
    

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
        <activity
            android:name=".Cam"
            android:label="@string/title_activity_cam"
            android:screenOrientation="landscape" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>


This gives it a decent camera look. Run the program to get your basic Camera App

Have a nice day!!

Friday, September 21, 2012

Web Server Basics | Java Sockets | Android Sockets

I recently came across this idea of creating a web server. And surprisingly it is not as bad as it seems to be. I chose java for implementing it cause it was the easiest. A web server is a software that runs on your computer (the server), and it acts as a server that sends web pages from your computer to another when asked for. The most simplest way of knowing this is to build one. Lets quickly build a server that outputs date on your browser for an instance.



  1. import java.net.*;
  2. import java.io.*;

  3. public class Server {
  4. public static void main(String[] args)
  5. {
  6. try
  7. {
  8. //Create a socket at port 80. The port over which browser usually connects
  9. ServerSocket sock = new ServerSocket(80);
  10. //Go into a loop and wait for connections to occur
  11. while(true)
  12. {
  13. //Accept a connection
  14. Socket client = sock.accept();
  15. //set PrintWriter to the output stream of the connected client
  16. PrintWriter pout = new PrintWriter(client.getOutputStream(), true);
  17. //Print date from java.util to the client's output stream
  18. pout.println(new java.util.Date().toString());
  19. //Close the connection with the client
  20. client.close();
  21. }
  22. }
  23. catch (Exception ioe)
  24. {
  25. //In case of exceptions print it to the console.
  26. System.out.println(ioe);
  27. }
  28. }

  29. }
This is a very simple program that does nothing but print date on the screen of the browser. Compile it

javac Server.java                                                                                 (Both Windows and Linux)

And run it 

java Server                                                                                            (Both Windows and Linux)

Now open your browser and type in http://localhost/ or http://127.0.0.1/ and if everything has gone fine then voila.



Now that it is simple to create it in Java, why not android. Open up eclipse and set this layout



  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2.     xmlns:tools="http://schemas.android.com/tools"
  3.     android:layout_width="match_parent"
  4.     android:layout_height="match_parent" >

  5.     <Button
  6.         android:id="@+id/button1"
  7.         android:layout_width="wrap_content"
  8.         android:layout_height="wrap_content"
  9.         android:layout_alignParentBottom="true"
  10.         android:layout_centerHorizontal="true"
  11.         android:text="@string/runserver" />

  12.     <TextView
  13.         android:id="@+id/textView1"
  14.         android:layout_width="wrap_content"
  15.         android:layout_height="wrap_content"
  16.         android:layout_above="@+id/button1"
  17.         android:layout_alignParentLeft="true"
  18.         android:layout_alignParentRight="true"
  19.         android:layout_alignParentTop="true"/>
  20.   
  21. </RelativeLayout>





And Update strings.xml to add the "Run Server" to strings.xml, this is not necessary but a good android programming practice to include all the strings in the xml files and nothing in the program itself.


  1. <resources>

  2.     <string name="app_name">WebServer</string>
  3.     <string name="menu_settings">Settings</string>
  4.     <string name="runserver">Run Server</string><string name="title_activity_main">WebServer</string>
  5.     

  6. </resources>

And update the manifest to include android:permission:INTERNET



  1. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  2.     package="com.regnartstranger.webserver"
  3.     android:versionCode="1"
  4.     android:versionName="1.0" >

  5.     <uses-sdk
  6.         android:minSdkVersion="10"
  7.         android:targetSdkVersion="15" />
  8.     <uses-permission android:name="android.permission.INTERNET" />
  9.     
  10.     
  11.     <application
  12.         android:icon="@drawable/ic_launcher"
  13.         android:label="@string/app_name"
  14.         android:theme="@style/AppTheme" >
  15.         <activity
  16.             android:name=".WebServer"
  17.             android:label="@string/title_activity_main" >
  18.             <intent-filter>
  19.                 <action android:name="android.intent.action.MAIN" />

  20.                 <category android:name="android.intent.category.LAUNCHER" />
  21.             </intent-filter>
  22.         </activity>
  23.     </application>

  24. </manifest>


In the main WebServer.java file use this code

  1. package com.regnartstranger.webserver;

  2. import android.os.Bundle;
  3. import android.app.Activity;
  4. import android.view.Menu;
  5. import android.view.View;
  6. import android.widget.Button;
  7. import android.widget.TextView;

  8. import java.net.*;
  9. import java.io.*;

  10. public class WebServer extends Activity {

  11. @Override
  12.     public void onCreate(Bundle savedInstanceState) {
  13.         super.onCreate(savedInstanceState);
  14.         setContentView(R.layout.activity_main);
  15.         Button runserver = (Button)findViewById(R.id.button1);
  16.         runserver.setOnClickListener((android.view.View.OnClickListener) new Server());
  17.        }
  18.     public class Server implements android.view.View.OnClickListener {
  19.    
  20.     public void onClick(View clickedButton) {
  21.     TextView textMsg = (TextView)findViewById(R.id.textView1);
  22.     try{
  23.     while(true){
  24.     ServerSocket socket = new ServerSocket(1234);
  25.                 Socket client = socket.accept();
  26.         PrintWriter pout = new PrintWriter(client.getOutputStream(), true);
  27.         pout.println("Android Webserver");
  28.            client.close();
  29.            socket.close();
  30.     }
  31.     }
  32.     catch(Exception ioe)
  33.                 {
  34.                 System.err.print(ioe);
  35.         textMsg.append("Error: " + ioe.getMessage() + "\n" + "Desc: " + ioe.getLocalizedMessage() + "\n");
  36.                 }
  37.     }
  38.     }
  39.    

  40.     @Override
  41.     public boolean onCreateOptionsMenu(Menu menu) {
  42.         getMenuInflater().inflate(R.menu.activity_main, menu);
  43.         return true;
  44.     }
  45. }

Now compile and load the program into your phone. Connect your computer to the phone's internet connection. And open the browser. Now to find out which ip the phone is broadcasting open up abd shell and type netcfg. This should display up the broadcast address of the server.



As you can clearly see my computer connected to the usb internet of my phone is broadcasting at http://192.168.42.129

Similarly find out yours and then open up browser and type in the ip followed by the port 1234. In my case it is http://192.168.42.129:1234/ and we get this


The program may report that the activity encountered unexpected error. Giving you the option to either "Force close" or "Wait". This happens because the activity is struck int the while(true) loop and is not responding to create changes in activity. Select "wait" until you want the server running. The solution to avoid this is to create a background process that runs asynchronously, and finishes the job. Try doing this google Async task android.

But http isn't this simple. It is standardized to have some protocols in it that has to be adhered to. Firstly Browser must send some message so that the server will know what it wants. Let us adjust the last program to get this message.

  1. import java.net.*;
  2. import java.io.*;

  3. public class Server {
  4. public static void main(String[] args)
  5. {
  6. try
  7. {
  8. //Create a socket at port 80. The port over which browser usually connects
  9. ServerSocket sock = new ServerSocket(80);
  10. //Go into a loop and wait for connections to occur
  11. while(true)
  12. {
  13. //Accept a connection
  14. Socket client = sock.accept();
  15. //Create a buffer to read the client request
  16. BufferedReader input = new BufferedReader(new InputStreamReader(client.getInputStream()));
  17. //Print out the requested line
  18. System.out.println(input.readLine());
  19. //set PrintWriter to the output stream of the connected client
  20. PrintWriter pout = new PrintWriter(client.getOutputStream(), true);
  21. //Print date from java.util to the client's output stream
  22. pout.println(new java.util.Date().toString());
  23. //Close the connection with the client
  24. client.close();
  25. }
  26. }
  27. catch (Exception ioe)
  28. {
  29. //In case of exceptions print it to the console.
  30. System.out.println(ioe);
  31. }
  32. }

  33. }
This will now print whatever your browser is asking from your server to the screen.Once again opening http://localhost/ or http://127.0.0.1/ will give you date on the browser and this output on the console.



Now the browser says GET / HTTP/1.1 (Note: The requests may vary dependent upon the browser you use. Mine is chrome by google). Now this request means GET whatever is there in your / directory, i.e., the root directory your server is broadcasting. And HTTP/1.1 is the version and type it supports. Now though most browsers would just display your html file without any problem if transmitted like this.

  1. import java.net.*;
  2. import java.io.*;

  3. public class Server {
  4. public static void main(String[] args)
  5. {
  6. try
  7. {
  8. //Create a socket at port 80. The port over which browser usually connects
  9. ServerSocket sock = new ServerSocket(80);
  10. //Go into a loop and wait for connections to occur
  11. while(true)
  12. {
  13. //Accept a connection
  14. Socket client = sock.accept();
  15. //Create a buffer to read the client request
  16. BufferedReader input = new BufferedReader(new InputStreamReader(client.getInputStream()));
  17. //Print out the requested line
  18. System.out.println(input.readLine());
  19. //Create a output stream to send the file
  20. DataOutputStream output = new DataOutputStream(client.getOutputStream());

  21. //Open a File to send it over the link
  22. FileInputStream indexfile = new FileInputStream("C:\\users\\regnarts\\Desktop\\index.html");
  23. //Buffer for file transfer usage
  24. byte [] buffer = new byte[1024];
  25.         
  26. //loop the transfer mechanism
  27. while (true) 
  28.        {
  29.            //Read and write the file to the buffer
  30. int b = indexfile.read(buffer, 0,1024);
  31.            if (b == -1) {
  32.            break; //end of file
  33.        }
  34.          output.write(buffer,0,b);
  35.        }
  36.                 
  37.       
  38. //Close the file and the output buffer
  39.        output.close();
  40.        indexfile.close();
  41.    //Close the connection with the client
  42.        client.close();
  43. }
  44. }
  45. catch (Exception ioe)
  46. {
  47. //In case of exceptions print it to the console.
  48. System.out.println(ioe);
  49. }
  50. }

  51. }
Edit the file path from my program before you compile it. And create a index.html file (or any other name as long as you are sure that the path points to it). Now if we run the file and open http://localhost/ or http://127.0.0.1/ on browser we get 

For the html file, I copied one from the internet that was meant for a html tutorial from http://www.mcli.dist.maricopa.edu/tut/tut1.html. It reads

  1.  <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
  2.      <html>
  3.      <head>
  4.      <title>Volcano Web</title>
  5.      </head>
  6.      <!-- written for the Writing HTML Tutorial
  7.      by Lorrie Lava, February 31, 1999       -->
  8.      <body>
  9.      In this lesson you will use the Internet to research 
  10.      information on volcanoes and then write a report on 
  11.      your results.
  12.      </body>
  13.      </html>
Though this must work on most of the browsers it is not the way a server is expected to respond. The server must first output certain bytes that tells the client, status of its request. Perhaps the most famous of these is the "404 File Not Found " error. The correct output to send the index.html file would be

HTTP/1.0 200 OK\r\n Content-Type: text/html\r\n

followed by the index.html file itself. It is not compulsory to transmit index.html itself. But many webservers use it as a default file to be transmitted at the first connection. Try creating a fully working webserver along with security in either android or java. Use concurrency to create different threads to handle every request. Good Luck!!!