Search...

Saturday, December 3, 2011

How to create Custom Intents and Broadcasting with Receivers in android

Here’s an example that tries to satisfy “Warrior’s” request on sending custom intents and grabbing them with broadcast receivers. This example has two receivers and an android manifest file:
The First Receiver:

view sourceprint?
01 public class OutgoingReceiver extends BroadcastReceiver { 
02   
03     public static final String CUSTOM_INTENT = "jason.wei.custom.intent.action.TEST"; 
04   
05     @Override
06     public void onReceive(Context context, Intent intent) { 
07         System.out.println("HIT OUTGOING"); 
08         Intent i = new Intent(); 
09         i.setAction(CUSTOM_INTENT); 
10         context.sendBroadcast(i); 
11     } 
12   
13 }
The Second Receiver:

view sourceprint?
1 public class IncomingReceiver extends BroadcastReceiver { 
2   
3     @Override
4     public void onReceive(Context context, Intent intent) { 
5         if (intent.getAction().equals(OutgoingReceiver.CUSTOM_INTENT)) { 
6             System.out.println("GOT THE INTENT"); 
7         } 
8     } 
9 }
The Android Manifest:

view sourceprint?01 <?xml version="1.0" encoding="utf-8"?> 
02 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
03       package="jason.wei.apps.androidtest"
04       android:versionCode="1"
05       android:versionName="1.0"> 
06     <application android:icon="@drawable/icon" android:label="@string/app_name"> 
07         <receiver android:name=".OutgoingReceiver" android:enabled="true"> 
08             <intent-filter> 
09                 <action android:name="android.intent.action.PHONE_STATE"></action> 
10             </intent-filter> 
11         </receiver> 
12         <receiver android:name=".IncomingReceiver" android:enabled="true"> 
13             <intent-filter> 
14                 <action android:name="jason.wei.custom.intent.action.TEST"></action> 
15             </intent-filter> 
16         </receiver> 
17   
18     </application> 
19     <uses-sdk android:minSdkVersion="3" /> 
20   
21 <uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission> 
22 </manifest>

So here’s a quick explanation of what’s going on in this code snippet. So notice that we first define our custom intent as:

view sourceprint?
1 public static final String CUSTOM_INTENT = "jason.wei.custom.intent.action.TEST";
This is the intent’s action (i.e. typically this would be something like android.intent.action.ACTION_VIEW) and you can think of this as our way of “tagging” the intent and characterizing it. Notice that you can also attach data and extras to this intent as usual (see http://thinkandroid.wordpress.com/2009/12/26/passing-info-between-activities/).
Now, in our manifest, our intent filter only allows for intents with actions “jason.wei.custom.intent.action.TEST” to be received and so technically we don’t even need to do the check in the IncomingReceiver (but it never hurts).
The flow of our little example works like this – first we define the OutgoingReceiver to intercept all intents broadcasted with action READ_PHONE_STATE (i.e. phone calls, this is how we trigger the first receiver). Once the OutgoingReceiver intercepts the first broadcasted intent, it will broadcast the second custom intent using the context.sendBroadcast() method which will then be received by our second receiver IncomingReceiver.

How to download image from url and save on SD card in android.


The path to SD Card can be retrieved using
Environment.getExternalStorageDirectory();

Then compress and write to SD Card by:
outStream = new FileOutputStream(file);
bm.compress(Bitmap.CompressFormat.PNG, 100, outStream);
outStream.flush();
outStream.close();

In order to premit the App to access internet and write to SD Card, we need "android.permission.INTERNET" and "android.permission.WRITE_EXTERNAL_STORAGE".
Modify AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.exercise.AndroidWebImage"
    android:versionCode="1"
    android:versionName="1.0">
  <application android:icon="@drawable/icon" android:label="@string/app_name">
      <activity android:name=".AndroidWebImage"
                android:label="@string/app_name">
          <intent-filter>
              <action android:name="android.intent.action.MAIN" />
              <category android:name="android.intent.category.LAUNCHER" />
          </intent-filter>
      </activity>

  </application>
  <uses-sdk android:minSdkVersion="4" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</manifest>


main.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="@string/hello"
  />
<Button
  android:id="@+id/save"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:text="Save"
  />
<ImageView
  android:id="@+id/image"
  android:scaleType="center"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
/>
</LinearLayout>


AndroidWebImage.java
package com.exercise.AndroidWebImage;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

public class AndroidWebImage extends Activity {

String image_URL=
 "http://chart.apis.google.com/chart?chs=200x200&cht=qr&chl=http%3A%2F%2Fandroid-er.blogspot.com%2F";

String extStorageDirectory;

Bitmap bm;

  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.main);
   
      Button buttonSave = (Button)findViewById(R.id.save);

      ImageView bmImage = (ImageView)findViewById(R.id.image);
   BitmapFactory.Options bmOptions;
   bmOptions = new BitmapFactory.Options();
   bmOptions.inSampleSize = 1;
   bm = LoadImage(image_URL, bmOptions);
   bmImage.setImageBitmap(bm);
 
   extStorageDirectory = Environment.getExternalStorageDirectory().toString();

   buttonSave.setText("Save to " + extStorageDirectory + "/qr.PNG");
   buttonSave.setOnClickListener(buttonSaveOnClickListener);
  }

  private Bitmap LoadImage(String URL, BitmapFactory.Options options)
  {    
   Bitmap bitmap = null;
   InputStream in = null;    
      try {
          in = OpenHttpConnection(URL);
          bitmap = BitmapFactory.decodeStream(in, null, options);
          in.close();
      } catch (IOException e1) {
      }
      return bitmap;            
  }

private InputStream OpenHttpConnection(String strURL) throws IOException{
 InputStream inputStream = null;
 URL url = new URL(strURL);
 URLConnection conn = url.openConnection();

 try{
  HttpURLConnection httpConn = (HttpURLConnection)conn;
  httpConn.setRequestMethod("GET");
  httpConn.connect();

  if (httpConn.getResponseCode() == HttpURLConnection.HTTP_OK) {
   inputStream = httpConn.getInputStream();
  }
 }
 catch (Exception ex)
 {
 }
 return inputStream;
}

Button.OnClickListener buttonSaveOnClickListener
 = new Button.OnClickListener(){

  @Override
  public void onClick(View arg0) {
   // TODO Auto-generated method stub
   OutputStream outStream = null;
   File file = new File(extStorageDirectory, "er.PNG");
   try {
    outStream = new FileOutputStream(file);
    bm.compress(Bitmap.CompressFormat.PNG, 100, outStream);
    outStream.flush();
    outStream.close();
 
    Toast.makeText(AndroidWebImage.this, "Saved", Toast.LENGTH_LONG).show();
 
   } catch (FileNotFoundException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    Toast.makeText(AndroidWebImage.this, e.toString(), Toast.LENGTH_LONG).show();
   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    Toast.makeText(AndroidWebImage.this, e.toString(), Toast.LENGTH_LONG).show();
   }

  }

};

}

How to write code to record video in Android.

This section explains how to record a video on Android. For recording video, MediaRecorder class will be used. To handle the display of camcorder, SurfaceView and SurfaceHolder.Callback interface will be used.
The below section throws light on MediaRecorder, SurfaceView and SurfaceHolder.Callback interface.
  1. MediaRecorder: This class is used to record audio and video. It has different methods to configure the recorder. The methods being used in the Video Recorder are explained below:
    • setVideoSource(): This sets the video source (i.e. Camera or Default) to be used for recording. If this method is not called, the output file will not contain a video track.
    • setOutputFormat(): This sets the format of the output file produced during recording. Call this after setAudioSource()/setVideoSource() but before prepare().
    • setVideoEncoder: This sets the video encoder to be used for recording. If this method is not called, the output file will not contain a video track. Call this after setOutputFormat() and before prepare().
    • setOutputFile(): This sets the path of the output file. Call this after setOutputFormat() but before prepare().
    • setPreviewDisplay(): Sets a Surface to show a preview of recorded media (video). Calls this before prepare() to make sure that the desirable preview display is set.
    • prepare(): Prepares the recorder to begin capturing and encoding data. This method must be called after setting up the desired audio and video sources, encoders, file format, etc., but before start().
    • start(): Begins capturing and encoding data to the file specified with setOutputFile(). Call this after prepare().
    (Note: These methods should be called in the sequence explained above.)
  2. SurfaceView: This is a customized view which provides a drawing surface inside the View hierarchy. It is used for resource intensive tasks where rapid updates or high frame rates are required such as 3D graphics, creating games, or previewing the camera in real time. The main advantage of using this view is that it provides an independent thread to update the view, which gives a great user experience.
  3. SurfaceHolder: As the name suggests, this interface holds the SurfaceView object. It allows developers to control the surface size and format, edit the pixels in the surface, and monitor changes to the surface.
Now we can use the above explained APIs to develop a VideoRecording application. We will begin with developing a customized view.
  • Create the RecorderPreview class which extends the SurfaceView and Implements the SurfaceHolder.Callback interface.
    class RecorderPreview extends SurfaceView implements SurfaceHolder.Callback
        {
          //Create objects for MediaRecorder and SurfaceHolder.
          MediaRecorder recorder;
          SurfaceHolder holder;
    
          //Create constructor of Preview Class. In this, get an object of
          //surfaceHolder class by calling getHolder() method. After that add
          //callback to the surfaceHolder. The callback will inform when surface is
          //created/changed/destroyed. Also set surface not to have its own buffers.
    
          public Preview(Contect context,MediaRecorder temprecorder) {
      super(context);
              recorder=temprecorder;
      holder=getHolder();
      holder.addCallback(this);
      holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
           }
    
          // Implement the methods of SurfaceHolder.Callback interface
    
          // SurfaceCreated : This method gets called when surface is created.
          // In this, initialize all parameters of MediaRecorder object as explained
          // above.
    
          public void surfaceCreated(SurfaceHolder holder){
       try{
                recorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT);
         recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
         recorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
          recorder.setOutputFile("/sdcard/recordvideooutput.3gpp");
          recorder.setPreviewDisplay(mHolder.getSurface());
         recorder.prepare();
         } catch (Exception e) {
          String message = e.getMessage()
          }
    }
    (Note: To allow recording video, add permission into the application's manifest file. i.e. Add <uses-permission android:name="android.permission.RECORD_VIDEO"/>).
    // SurfaceDestroyed : This method gets called immediately before the
    // surface is being destroyed. Stop camera preview because surface will no
    // longer exist.
    
    public void surfaceDestroyed(SurfaceHolder holder)
    {
        if(recorder!=null)
        {
     recorder.release();
     recorder = null;
        }
    }
    
    //surfaceChanged : This method is called after the surface is created.
    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h)
    {
    }
    }
  • Implement the onCreate method of video recording application.
    //Create objects of MediaRecorder and Preview class
    private MediaRecorder recorder;
    private Preview preview;
        // In this method, create an object of MediaRecorder class. Create an object of
        // RecorderPreview class(Customized View). Add RecorderPreview class object
        // as content of UI.
    
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        recorder = new MediaRecorder();
        preview = new RecorderPreview(this,recorder);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        setContentView(preview);
    }
    
    //Create option menu which can be used for starting and stopping video recording.
    // Also implement the onOptionsItemSelected to handle the events for option menu.
    
    public boolean onCreateOptionsMenu(Menu menu)
    {
        menu.add(0, 0, 0, "StartRecording");
        menu.add(0, 1, 0, "StopRecording");
        return super.onCreateOptionsMenu(menu);
    }
    
    public boolean onOptionsItemSelected(MenuItem item)
    {
        switch (item.getItemId())
        {
            case 0:
                recorder.start();
                break;
            case 1:
        recorder.stop();
        break;
        }
        return super.onOptionsItemSelected(item);
    }
The application is now ready for testing. Video recording is available only on handsets having version of SDK 1.5 or later. It is not possible to check application on emulator, you need to install it on handset.

How to Install Android on an iPhone in Six Easy Steps

If you've got an iPhone, are a little bored with iOS, and you're interested in moonlighting with Google's Android operating system, you can dual boot Android and iOS side-by-side on your iPhone in a few relatively simple steps.
What You'll Need:
All you'll need to get started is an iOS device; Right now, the iPhone 3G has the best support, and that's what we're using in this guide.
Step One: Jailbreak Your iPhone

Full sizeYou've got a number of jailbreaking options, including PwnageTool, Redsn0w, and Blackra1n. Pick one that works on your platform, download it, and walk through the jailbreak process. (I'm not going to detail the jailbreak here since the latest jailbreaking methods often change a little, but at this point, jailbreaking an iPhone is a relatively simple process.)
Step Two: Install Bootlace in CydiaFull sizeIn order to do this, you'll need to launch Cydia from the homescreen, tap on the Manage button, select Sources, then tap Edit, then Add. The repository you'll need to add is repo.neonkoala.co.uk. Tap Add Source, let Cydia work its magic, and then tap on your newly added repository and install Bootlace.

Step Three: Run Bootlace and Patch the KernelFull sizeLeave Cydia, and launch Bootlace. If Bootlace isn't on your homescreen after you leave Cydia, restart your iPhone and it should be there. Then just launch Bootlace, and let it download and patch the kernel. When it's done, tap on Reboot and wait for your phone to reboot.

Step Four: Install OpeniBootFull sizeNow launch Bootlace again, tap the OpeniBoot button, and tap Install, then Continue. OpeniBoot will download and install.

Step Five: Install iDroidFull sizeOnce OpeniBoot is installed, tap the iDroid button, tap Install, OK, and then wait. iDroid—which is essentially the Android OS customized for your iPhone—will download and install. This will take a while, so be patient, and if your battery is low, you may want to plug in your phone before you start.

Step Six: Reboot and Play Around with AndroidFull sizeNow you've installed Android on your iPhone. Time to play around with it. Just tap on the QuickBoot button from inside Bootlace, tap the Android icon (the one of the little Android proudly holding an Apple), and confirm that you want to reboot into Android.

List of all Android Icon Resources

Just visit the below link to find all the icons available in sdk.

http://www.darshancomputing.com/android/1.5-drawables.html

Thursday, December 1, 2011

How to create Custom Listview in android


Step 1:
Add a normal listview in the main.xml layout and make sure u set the layout width as fill parent.
Main.xml

[sourcecode language="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:id="@+id/TextView01" android:layout_height="wrap_content" android:text="List of Country &amp; their denotation" android:textStyle="normal|bold" android:gravity="center_vertical|center_horizontal" android:layout_width="fill_parent"></TextView>
<ListView android:id="@+id/ListView01" android:layout_height="wrap_content"
android:layout_width="fill_parent">
</ListView>
</LinearLayout>

[/sourcecode]

Step 2 :
Add two textview(textview1&textview2) in listview.xml and add background image(bg.png) to textview1.
Listview.xml

[sourcecode language="xml"]
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content" android:gravity="left|center"
android:layout_width="wrap_content" android:paddingBottom="5px"
android:paddingTop="5px" android:paddingLeft="5px">
<TextView android:id="@+id/TextView01" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:gravity="center"
android:background="@drawable/bg" android:textColor="#FFFF00"
android:text="hi"></TextView>
<TextView android:text="@+id/TextView02" android:id="@+id/TextView02"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="10px" android:textColor="#0099CC"></TextView>
</LinearLayout>

[/sourcecode]

Step 3 :
The class EfficientAdapter should extend BaseAdapter for basic listview.
Step 4:
Create a class Holder that contains two textview.
Step 5:
Create two separate variables for country list and denotation.
Step 6:
Set the content view to main and set the set the listview adapter to EfficientAdapter class.
This will load the listcontent in the listview.

[sourcecode language="java"]

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

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;

public class customlistview extends Activity {

private static class EfficientAdapter extends BaseAdapter {
private LayoutInflater mInflater;

public EfficientAdapter(Context context) {
mInflater = LayoutInflater.from(context);

}

public int getCount() {
return country.length;
}

public Object getItem(int position) {
return position;
}

public long getItemId(int position) {
return position;
}

public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.listview, null);
holder = new ViewHolder();
holder.text = (TextView) convertView
.findViewById(R.id.TextView01);
holder.text2 = (TextView) convertView
.findViewById(R.id.TextView02);

convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}

holder.text.setText(curr[position]);
holder.text2.setText(country[position]);

return convertView;
}

static class ViewHolder {
TextView text;
TextView text2;
}
}

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ListView l1 = (ListView) findViewById(R.id.ListView01);
l1.setAdapter(new EfficientAdapter(this));
}

private static final String[] country = { "Iceland", "India", "Indonesia",
"Iran", "Iraq", "Ireland", "Israel", "Italy", "Laos", "Latvia",
"Lebanon", "Lesotho ", "Liberia", "Libya", "Lithuania",
"Luxembourg" };
private static final String[] curr = { "ISK", "INR", "IDR", "IRR", "IQD",
"EUR", "ILS", "EUR", "LAK", "LVL", "LBP", "LSL ", "LRD", "LYD",
"LTL ", "EUR"

};

}

How to create custom MediaController in honeycomb android


(1)custom_video.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout android:layout_width="match_parent"
android:layout_height="match_parent" xmlns:android="http://schemas.android.com/apk/res/android">

<com.code.EnhancedSurfaceView
android:id="@+id/video_player_surface" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_gravity="center">

</com.code.EnhancedSurfaceView>


<RelativeLayout android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout android:id="@+id/top_panel"
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:orientation="horizontal" android:background="#40808080"
android:visibility="visible" android:layout_alignParentTop="true">
<TextView android:id="@+id/video_player_caption"
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:textSize="20dip" android:textStyle="bold" android:gravity="center" />
</LinearLayout>
<ProgressBar android:id="@+id/progress1"
android:layout_height="60px" android:layout_width="60px"
android:indeterminate="true" android:visibility="visible"
android:layout_centerHorizontal="true" android:layout_centerVertical="true"
android:layout_below="@+id/IVsetup1"></ProgressBar>
<LinearLayout android:id="@+id/bottom_panel"
android:layout_height="wrap_content" android:layout_width="fill_parent"
android:background="#40808080" android:layout_alignParentBottom="true"
android:orientation="vertical" android:gravity="center_horizontal">

<LinearLayout android:id="@+id/bottom_panel1"
android:layout_height="wrap_content" android:layout_width="fill_parent"
android:layout_alignParentBottom="true" android:orientation="horizontal"
android:gravity="center_horizontal">
<ImageButton android:id="@+id/mediaRew"
android:layout_height="wrap_content" android:layout_width="wrap_content"
android:layout_centerHorizontal="true" android:background="@android:drawable/ic_media_rew" />
<ImageButton android:id="@+id/mediaPlayPause"
android:layout_height="wrap_content" android:layout_width="wrap_content"
android:layout_centerHorizontal="true" android:background="@android:drawable/ic_media_play" />

<ImageButton android:id="@+id/mediaFwd"
android:layout_height="wrap_content" android:layout_width="wrap_content"
android:layout_centerHorizontal="true" android:background="@android:drawable/ic_media_ff" />
</LinearLayout>
<LinearLayout android:id="@+id/bottom_panel2"
android:layout_height="wrap_content" android:layout_width="fill_parent"
android:layout_alignParentBottom="true" android:orientation="horizontal"
android:gravity="center_horizontal|center_vertical">
<TextView android:id="@+id/currentTime"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="" />
<SeekBar android:progress="0" android:secondaryProgress="0"
android:max="1000" android:layout_width="300dip"
android:paddingLeft="15dip" android:paddingRight="15dip"
android:id="@+id/videoProgress" android:layout_height="wrap_content"></SeekBar>

<TextView android:id="@+id/endTime" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="" />

</LinearLayout>


</LinearLayout>

</RelativeLayout>

</FrameLayout>




(2)EnhancedSurfaceView.java

package com.code;

import android.content.Context;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.SurfaceView;

public class EnhancedSurfaceView

extends SurfaceView {
TapListener listener;

public EnhancedSurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
}

public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
gestureListener.onSingleTapUp(event);
}

return (true);
}

public void addTapListener(TapListener l) {
listener = l;
}

public void removeTapListener(TapListener l) {
listener = null;
}

private GestureDetector.SimpleOnGestureListener gestureListener = new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onSingleTapUp(MotionEvent e) {

listener.onTap(e);

return (true);
}
};

public interface TapListener {
void onTap(MotionEvent event);
}
}




(3)VideoPlayerFragment.java


package com.code;

import java.io.IOException;
import java.util.Formatter;
import java.util.Locale;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

import com.code.R;

import android.app.AlertDialog;
import android.app.Fragment;
import android.content.Context;
import android.content.DialogInterface;

import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.PowerManager;
import android.os.SystemClock;

import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.ProgressBar;
import android.widget.SeekBar;
import android.widget.Toast;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;

public class VideoPlayerFragment extends Fragment implements
MediaPlayer.OnBufferingUpdateListener,
MediaPlayer.OnCompletionListener, MediaPlayer.OnPreparedListener,
MediaPlayer.OnVideoSizeChangedListener, SurfaceHolder.Callback,
MediaPlayer.OnErrorListener {

private int videoWidth;
private int videoHeight;
private MediaPlayer mediaPlayer;
private SurfaceHolder holder;
private Uri mediaUri;
private boolean isVideoSizeKnown = false;
private boolean isVideoReadyToBePlayed = false;
private PowerManager.WakeLock screenWakeLock;
private int bufferedPercent = 0;
private ScheduledFuture<?> finisherFuture;
private boolean wasPaused = false;
private View topPanel = null;
private View bottomPanel = null;
private ImageButton mediaPlayPause = null;
private ImageButton mediaRew = null;
private ImageButton mediaFwd = null;
private long lastActionTime = 0L;
EnhancedSurfaceView preview;
ProgressBar progress = null;
ProgressBar videoProgress = null;
TextView currentTime = null;
TextView endTime = null;
private static final int SHOW_PROGRESS = 2;
private boolean mDragging;

StringBuilder mFormatBuilder;
Formatter mFormatter;
private boolean DEBUG = DirectvApplication.showLogs();
//private boolean onStopCalled=false;
//private int currentPlayerDuration;


public VideoPlayerFragment() {
DEBUG = DirectvApplication.showLogs();
}

// Activity has to call this api to set required field to play video.
public void setVideoInformation(Uri uri, String videoCaption) {

updateCaption(videoCaption);
mediaUri = uri;

}

@Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
DEBUG = DirectvApplication.showLogs();

// getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
PowerManager pm = (PowerManager) getActivity().getSystemService(
Context.POWER_SERVICE);
screenWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK,
"Video Player");
screenWakeLock.acquire();
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub

return inflater.inflate(R.layout.custom_video, container, false);
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);

preview = (EnhancedSurfaceView) getView().findViewById(
R.id.video_player_surface);
preview.addTapListener(onTap);

holder = preview.getHolder();
progress = (ProgressBar) getView().findViewById(R.id.progress1);
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
topPanel = getView().findViewById(R.id.top_panel);
bottomPanel = getView().findViewById(R.id.bottom_panel);
// new code
mediaPlayPause = (ImageButton) getView().findViewById(
R.id.mediaPlayPause);
mediaPlayPause.setOnClickListener(onMedia);

mediaFwd = (ImageButton) getView().findViewById(R.id.mediaFwd);
mediaFwd.setOnClickListener(onMedia);

mediaRew = (ImageButton) getView().findViewById(R.id.mediaRew);
mediaRew.setOnClickListener(onMedia);

// New Code
videoProgress = (ProgressBar) getView()
.findViewById(R.id.videoProgress);

if (videoProgress != null) {
if (videoProgress instanceof SeekBar) {
SeekBar seeker = (SeekBar) videoProgress;
seeker.setOnSeekBarChangeListener(mSeekListener);
}
}
endTime = (TextView) getView().findViewById(R.id.endTime);
currentTime = (TextView) getView().findViewById(R.id.currentTime);

disableMediaButtons();// new code

// mediaUrl = "http://jsharkey.org/downloads/dailytest.3gp";
lastActionTime = SystemClock.elapsedRealtime();
mFormatBuilder = new StringBuilder();
mFormatter = new Formatter(mFormatBuilder, Locale.getDefault());

topPanel.setVisibility(View.GONE);
bottomPanel.setVisibility(View.GONE);

}

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

preview.postDelayed(onEverySecond, 1000);
}

@Override
public void onResume() {
super.onResume();
DEBUG = DirectvApplication.showLogs();
if (wasPaused) {
// finish();
}
preview.postDelayed(onEverySecond, 1000);
// setupTimer();
}

@Override
public void onPause() {
// releaseScreenLock();
super.onPause();
// releaseMediaPlayer();
// doCleanUp();
// if (finisherFuture != null) {
// finisherFuture.cancel(true);
// }
// wasPaused = true;
// stopTimer();
}

@Override
public void onStop() {
// TODO Auto-generated method stub
super.onStop();

//onStopCalled=true;
//Log.d("Test", "On Stop is called....");
}

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

releaseScreenLock();
releaseMediaPlayer();
doCleanUp();
if (finisherFuture != null) {
finisherFuture.cancel(true);
}
// stopTimer();
}

private void updateCaption(String caption) {
TextView captionTextView = (TextView) getView().findViewById(
R.id.video_player_caption);
captionTextView.setText(caption);
}

private void playVideo() {
doCleanUp();
progress.setVisibility(View.VISIBLE);
scheduleVideoPlaybackAborter();

try {

if(mediaPlayer!=null){
mediaPlayer.release();
}

mediaPlayer = new MediaPlayer();

// mediaPlayer.setDataSource(mediaUrl);
mediaPlayer.setDataSource(getActivity(), mediaUri);
mediaPlayer.setDisplay(holder);
mediaPlayer.setOnBufferingUpdateListener(this);
mediaPlayer.setOnCompletionListener(this);
mediaPlayer.setOnPreparedListener(this);
mediaPlayer.setOnVideoSizeChangedListener(this);
mediaPlayer.setOnErrorListener(this);
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
//Log.d("Test", " VideoPlayerActivity - done preparing");
mediaPlayer.prepareAsync();

//Log.d("Test","------------------ VideoPlayerActivity - done preparing");
} catch (IOException e) {

showErrorDialogAndFinishActivity("Network error");
}
}

private void showErrorDialogAndFinishActivity(String message) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

builder.setTitle("Exception!").setMessage(message)
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
getActivity().finish();
}
}).show();
}

private void scheduleVideoPlaybackAborter() {
if (finisherFuture != null) {
finisherFuture.cancel(true);
}

Runnable aborter = new Runnable() {
public void run() {

if (bufferedPercent == 0) {
showErrorDialogAndFinishActivity("Network Error");
}
}
};

finisherFuture = Executors.newSingleThreadScheduledExecutor().schedule(
aborter, 30, TimeUnit.SECONDS);
}

public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
if (width == 0 || height == 0) {
return;
}
isVideoSizeKnown = true;
videoWidth = width;
videoHeight = height;
if (isVideoReadyToBePlayed && isVideoSizeKnown) {
startVideoPlayback();
}
}

public void onPrepared(MediaPlayer mediaplayer) {

isVideoReadyToBePlayed = true;
progress.setVisibility(View.GONE);
if (isVideoReadyToBePlayed && isVideoSizeKnown) {
startVideoPlayback();
}
}

public void surfaceCreated(SurfaceHolder holder) {

// Log.d("Test", "Surface is created.....");

playVideo();
}

public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// No implementation
}

public void surfaceDestroyed(SurfaceHolder holder) {

// No implementation
mediaPlayer.pause();
//Log.d("Test", "Surface is destroyed.........");
}

private void releaseScreenLock() {
if (screenWakeLock.isHeld()) {
screenWakeLock.release();
}
}

private void releaseMediaPlayer() {

//Log.d("Test", "Release playerr is called...");
if (mediaPlayer != null) {
mediaPlayer.release();
mediaPlayer = null;

}
}

private void doCleanUp() {
videoWidth = 0;
videoHeight = 0;
isVideoReadyToBePlayed = false;
isVideoSizeKnown = false;
}

private void startVideoPlayback() {
holder.setFixedSize(videoWidth, videoHeight);

// if(onStopCalled){
//
// }
mediaPlayer.start();
enableMediaButtons();// new code
setPauseIcon();// new code
mHandler.sendEmptyMessage(SHOW_PROGRESS);// new code

}

public void onCompletion(MediaPlayer mp) {
setPlayIcon();

Toast.makeText(getActivity(),
"\nThis program has ended. Thanks for watching.\n",
Toast.LENGTH_SHORT).show();
getActivity().finish();
}

public void onBufferingUpdate(MediaPlayer mp, int percent) {

bufferedPercent = percent;

}

public boolean onError(MediaPlayer mp, int what, int extra) {
// TODO Auto-generated method stub

//Log.d("Test", "---------Some error---------------");
showErrorDialogAndFinishActivity("Unable to play video.");
return true;
}

private EnhancedSurfaceView.TapListener onTap = new EnhancedSurfaceView.TapListener() {
public void onTap(MotionEvent event) {

showPanels();
setProgress();

}
};

private void showPanels() {

if (progress.getVisibility() == View.GONE) {
lastActionTime = SystemClock.elapsedRealtime();
topPanel.setVisibility(View.VISIBLE);
bottomPanel.setVisibility(View.VISIBLE);
mHandler.sendEmptyMessage(SHOW_PROGRESS);
}

}

private void clearPanels() {
lastActionTime = 0;
topPanel.setVisibility(View.GONE);
bottomPanel.setVisibility(View.GONE);

}

private Runnable onEverySecond = new Runnable() {
public void run() {
if (lastActionTime > 0
&& SystemClock.elapsedRealtime() - lastActionTime > 5000) {
clearPanels();
}
preview.postDelayed(onEverySecond, 1000);

}
};

// new code
private View.OnClickListener onMedia = new View.OnClickListener() {
public void onClick(View v) {

switch (v.getId()) {

case R.id.mediaPlayPause:

if (mediaPlayer.isPlaying()) {
mediaPlayer.pause();
setPlayIcon();
setProgress();

} else {

mediaPlayer.start();
setPauseIcon();
setProgress();
mHandler.sendEmptyMessage(SHOW_PROGRESS);

}

break;

case R.id.mediaFwd:

int posFwd = mediaPlayer.getCurrentPosition();
posFwd += 5000; // milliseconds
mediaPlayer.seekTo(posFwd);
setProgress();

break;

case R.id.mediaRew:

int posRew = mediaPlayer.getCurrentPosition();
posRew -= 5000; // milliseconds
mediaPlayer.seekTo(posRew);
setProgress();

break;

}

}
};

private void setPlayIcon() {
mediaPlayPause.setBackgroundResource(android.R.drawable.ic_media_play);
}

private void setPauseIcon() {
mediaPlayPause.setBackgroundResource(android.R.drawable.ic_media_pause);
}

private void disableMediaButtons() {
mediaPlayPause.setClickable(false);
mediaFwd.setClickable(false);
mediaRew.setClickable(false);
}

private void enableMediaButtons() {
mediaPlayPause.setClickable(true);
mediaFwd.setClickable(true);
mediaRew.setClickable(true);
}

private String stringForTime(int timeMs) {
int totalSeconds = timeMs / 1000;

int seconds = totalSeconds % 60;
int minutes = (totalSeconds / 60) % 60;
int hours = totalSeconds / 3600;

mFormatBuilder.setLength(0);
if (hours > 0) {
return mFormatter.format("%d:%02d:%02d", hours, minutes, seconds)
.toString();
} else {
return mFormatter.format("%02d:%02d", minutes, seconds).toString();
}
}

private int setProgress() {

if (progress.getVisibility() == View.GONE) {
if (mediaPlayer == null || mDragging) {
return 0;
}

if (mediaPlayer == null) {
return 0;
}
//Log.d("Test","Media Player "+mediaPlayer);
int position = mediaPlayer.getCurrentPosition();
int duration = mediaPlayer.getDuration();
if (videoProgress != null) {
if (duration > 0) {
// use long to avoid overflow
long pos = 1000L * position / duration;
// pos=1000;

videoProgress.setProgress((int) pos);

}
int percent = bufferedPercent;
videoProgress.setSecondaryProgress(percent * 10);
}

if (endTime != null)
endTime.setText(stringForTime(duration));
if (currentTime != null)
currentTime.setText(stringForTime(position));

return position;

} else {
return 0;
}
}

private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
int pos;
switch (msg.what) {

case SHOW_PROGRESS:
pos = setProgress();
if (!mDragging
&& (mediaPlayer != null && mediaPlayer.isPlaying())) {
msg = obtainMessage(SHOW_PROGRESS);
sendMessageDelayed(msg, 1000 - (pos % 1000));
}
break;
}
}
};

private OnSeekBarChangeListener mSeekListener = new OnSeekBarChangeListener() {
long duration;

public void onStartTrackingTouch(SeekBar bar) {
showPanels();
setProgress();
if (mediaPlayer != null) {
duration = mediaPlayer.getDuration();
}
}



public void onProgressChanged(SeekBar bar, int progress,
boolean fromtouch) {


if (fromtouch) {
mDragging = true;

if (mediaPlayer != null) {
duration = mediaPlayer.getDuration();
long newposition = (duration * progress) / 1000L;
mediaPlayer.seekTo((int) newposition);
if (currentTime != null)
currentTime.setText(stringForTime((int) newposition));

}
}
}

public void onStopTrackingTouch(SeekBar bar) {
mDragging = false;
setProgress();
// updatePausePlay();
showPanels();
setProgress();
}
};

}