Android Video download using Service class

Android Video download using Service.class


HI
Today we see how to downloading video using android service class

In my last blog I show how to downloading video using AsyncTask
Some time an asynctask take much time to downloading video so if you are showing some progressdialog for downloading it may freez your UI
you can't do any other task upto downloading the video

Using service class the downloading take may goes to background and you may operate other task of an application

So lets start the coding

Lets create a layout for the MainActivity

<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"
   android:paddingBottom="@dimen/activity_vertical_margin"
   android:paddingLeft="@dimen/activity_horizontal_margin"
   android:paddingRight="@dimen/activity_horizontal_margin"
   android:paddingTop="@dimen/activity_vertical_margin"
   tools:context="com.videoservice.activity.MainActivity" >

     <LinearLayout
        android:id="@+id/linearLayout1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:orientation="horizontal" >

       <Button
         android:id="@+id/btn_download"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_weight="1"
         android:text="Download" />

       <Button
       android:id="@+id/btn_Play"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_weight="1"
       android:text="Play Video" />
 </LinearLayout>

    <VideoView
      android:id="@+id/videoView1"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_below="@+id/linearLayout1"
      android:layout_marginTop="18dp" />

</RelativeLayout>


Here I take a two button first for downloading and second for playing video from device.
So here is one videoview1 which will play video inside it.

Lets start to write a service class

A service is a component that runs in the background to perform long-running operations without needing to interact with the user and it works even if application is destroyed.

Here I creae a Class which extends with service class name as DownloadVideo_Service

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import com.videoservice.Utils.AppConstants;
import com.videoservice.Utils.VideoInterface;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;

public class DownloadVideo_Service extends Service {
   String str_filename, urlPaths;
   boolean isFileExists;
   Context currObj;
   public final static String Download_response = "response";
  
  @Override
    public IBinder onBind(Intent intent) {
      // TODO Auto-generated method stub
      return null;
    }
  @Override
    public void onCreate() {
        // TODO Auto-generated method stub
        super.onCreate();
        System.out.println("come here 000 ");
           currObj = this;
         System.out.println("come here 000*** ");
   }

   @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
       // TODO Auto-generated method stub
       /// return super.onStartCommand(intent, flags, startId);
      str_filename = intent.getStringExtra("filename");
      urlPaths = intent.getStringExtra("urlPaths");
      isFileExists = AppConstants.fileExistance(currObj, str_filename);
      Thread tt_download = new Thread(new DownloadThread(currObj, startId,        str_filename, urlPaths));
      tt_download.start();
      return START_STICKY;
   }
    @Override
     public void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
        System.out.println("Service Destroyed...");
      }
    final class DownloadThread implements Runnable {
     int service_id;
     String str_filenames, urlPaths;
     Context currObj;
     VideoInterface objVideoResponse;

     public DownloadThread(Context currObj, int service_id, String str_filenames,       String urlPaths) {
      // TODO Auto-generated constructor stub
      this.service_id = service_id;
      this.str_filenames = str_filenames;
      this.urlPaths = urlPaths;
      this.currObj = currObj;
      System.out.println("come here 111 ");
   }
   @Override
    public void run() {
      // TODO Auto-generated method stub
       synchronized (this) {
         try {
           System.out.println("0000 ");
           // wait(10000);
        if (isFileExists == false) {
          DownloadVideo(currObj, urlPaths, str_filename);
          Intent IT_response = new Intent();
          IT_response.setAction(Download_response);
          IT_response.putExtra("video_response", urlPaths+","+ str_filename);
          sendBroadcast(IT_response);
        } else {
         // already exists
       }
       System.out.println("1111 ");
     } catch (Exception e) {
        // TODO: handle exception
    }
     stopSelf(this.service_id);
   }
}

   private void DownloadVideo(Context currObj, String urlPaths2, String          str_filename) {
           // TODO Auto-generated method stub
      try {
         System.err.println("urlPaths for Video:==> " + urlPaths);
         URL wallpaperURL = new URL(urlPaths);
         URLConnection connection = wallpaperURL.openConnection();
         InputStream inputStream = new BufferedInputStream(wallpaperURL.openStream(), 10240);
        File cacheDir = AppConstants.getDataFolder(currObj);
        File cacheFile = new File(cacheDir, str_filename);
        FileOutputStream outputStream = new FileOutputStream(cacheFile);
        byte buffer[] = new byte[1024];
        int dataSize;
        int loadedSize = 0;
        while ((dataSize = inputStream.read(buffer)) != -1) {
           loadedSize += dataSize;
         // publishProgress(loadedSize);
         outputStream.write(buffer, 0, dataSize);
        }
        outputStream.close();
      } catch (Exception e) {
        e.printStackTrace();
   }
  }
 }
}

In side the onStartCommand I write a thread class which will synchronized the process as per the process call

The stopself function of service is for stop the service onces its task is completed
That the user not need to stop it.

Here we write a BroadcastReceiver class which will recive the response from the service as the video is donloaded or not

The Video_receiver class is responsible for handling the BroadcastReceiver data and pass the data over the main activity

 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 public class Video_receiver extends BroadcastReceiver{
  @Override
  public void onReceive(Context arg0, Intent arg1) {
   // TODO Auto-generated method stub
   String str_data = arg1.getStringExtra("video_response");
   System.out.println("str_data *** "+str_data);
   MainActivity.GetResult(arg1);
  }
}


Lets start code for the main activity class

import com.videoservice.Utils.AppConstants;
import com.videoservice.service.DownloadVideo_Service;
import com.videoservice.service.Video_receiver;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.VideoView;

public class MainActivity extends Activity implements OnClickListener {
   Video_receiver objreceiver;
   static VideoView videoView1;
   Button btn_Play, btn_download;
   String str_videoName = "newHotel.mov";
   static Context currObj;

 @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);
       currObj = this;
       initialized();
}
   private void initialized() {
       // TODO Auto-generated method stub
       btn_Play = (Button) findViewById(R.id.btn_Play);
       btn_download = (Button) findViewById(R.id.btn_download);
       btn_Play.setOnClickListener(this);
       btn_download.setOnClickListener(this);
       videoView1 = (VideoView) findViewById(R.id.videoView1);
   }
  @Override
     public boolean onCreateOptionsMenu(Menu menu) {
       // Inflate the menu; this adds items to the action bar if it is present.
       getMenuInflater().inflate(R.menu.main, menu);
       return true;
}
@Override
  public boolean onOptionsItemSelected(MenuItem item) {
      // Handle action bar item clicks here. The action bar will
      // automatically handle clicks on the Home/Up button, so long
      // as you specify a parent activity in AndroidManifest.xml.
     int id = item.getItemId();
     if (id == R.id.action_settings) {
          return true;
     }
      return super.onOptionsItemSelected(item);
}

@Override
public void onClick(View v) {
    // TODO Auto-generated method stub
     switch (v.getId()) {
       case R.id.btn_download:
        boolean isFileExists = AppConstants.fileExistance(this, str_videoName);
        if (isFileExists == false) {
          objreceiver = new Video_receiver();
          IntentFilter intentfilter = new IntentFilter();
          intentfilter.addAction(DownloadVideo_Service.Download_response);
          registerReceiver(objreceiver, intentfilter);
          Intent IT_downloadService = new Intent(this, DownloadVideo_Service.class);
          IT_downloadService.putExtra("filename", str_videoName);
          IT_downloadService.putExtra("urlPaths", AppConstants.str_hotelVideo);
          startService(IT_downloadService);
     } else {
          System.out.println("File already downloaded");
    }
   break;
   case R.id.btn_Play:
        PlayVideo(str_videoName);
   break;
   default:
   break;
  }
}

  public static void GetResult(Intent intent) {
   // TODO Auto-generated method stub
   Bundle bundle = intent.getExtras();
   if (bundle != null) {
       String str_file = bundle.getString("video_response");
       System.out.println("bundle value " + str_file);
       String str_data[] = str_file.split(",");
       String filename = str_data[1];
         PlayVideo(filename);
      } else {
        System.out.println("bundle is null");
    }
}

private static void PlayVideo(String str_file) {
   // TODO Auto-generated method stub
   boolean filePresent = AppConstants.fileExistance(currObj, str_file);
    if (filePresent == true) {
      String videoFilename = AppConstants.getFilePath(currObj, str_file);
      System.err.println("File Patha " + videoFilename);
      videoView1.setVideoPath(videoFilename);
      videoView1.requestFocus();
      if (!videoView1.isPlaying()) {
         videoView1.start();
      }
    }
  }
}

Here I start the service onClickListener for the videodownd button code
First I check the existance of a file if file is not exists then I call the download service.class which will start downloading on background.

Dont forgot to register your service inside the manifeast file inside the application tag

<service
android:name="com.videoservice.service.DownloadVideo_Service"
android:exported="false" />


Write a Class AppConstants which will containe the Url which will for the videoFile and other custom function for checking file is exists on the device and other

  import java.io.File;
  import android.content.Context;
  public class AppConstants {

  public static String str_hotelVideo =       "http://www.youwebsite.com/ws/app_videos/shutterstock_v12322691.mov";
  public static boolean fileExistance(Context mcontext,String fname) {
       //File file = new File(mcontext.getFilesDir() + File.separator + "Video/" + fname);
     File cacheDir = getDataFolder(mcontext);
     File cacheFile = new File(cacheDir, fname);
      return cacheFile.exists();
 }
   public static File getDataFolder(Context context) {
       File dataDir = null;
       /* Write file to external storage
        * if      (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
        dataDir = new File(Environment.getExternalStorageDirectory(), "Video");
        if(!dataDir.isDirectory()) {
        dataDir.mkdirs();
    }
}*/
//Write to internal storage on app path
     if(context.getApplicationInfo().dataDir!=null){
       dataDir = new File(context.getCacheDir(),"App_Viedo");
       if(!dataDir.isDirectory()) {
        dataDir.mkdirs();
   }
}
   if(!dataDir.isDirectory()) {
        dataDir = context.getFilesDir();
    }
       return dataDir;
   }
public static String getFilePath(Context mcontext, String fname) {
    // File file = new File(mcontext.getFilesDir() + File.separator +
    // "Video/" + fname);
    File cacheDir = getDataFolder(mcontext);
    File cacheFile = new File(cacheDir, fname);
     return cacheFile.getAbsolutePath();
   }
}


See the following out put below






Comments

  1. Hi Mahesh,

    Thanks for your help my problem is resolved with your code best of luck buddy god bless you...!

    ReplyDelete

Post a Comment

Popular posts from this blog

Crypto JS Encryption & Decryption in Android

ListView Over GoogleMapView

Android Interview Material