-1

Before posting this questions i have searched a lot in stack overflow but couldn't find the solution..some of them are ..

How to Upload Large Video FIle on server?

video upload in Android

Upload large file in Android without outofmemory error

Upload files by post to server OutOfMemory

Upload file in Android with outofmemory error etc.....

I am uploading a video File which is inside file Manager /mfs_candidate_intro/65850.mp4

Now MainActivity.java

package com.servicedemo;

import java.io.File;

import android.support.v7.app.ActionBarActivity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;


public class MainActivity extends ActionBarActivity {


    private String fpath;
    private String myfile;
    private static final String UPLOAD_URL = "http://www.ourgoalplan.com/CandidateIntroUploader.ashx";
    private int candidateID =65850; 

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

    }


   public void startMethod(View v) {

       fpath=setVideoOutPutFile();
       Intent i=new Intent(MainActivity.this,Uploadservice.class);
        i.putExtra("filepath", fpath);
        i.putExtra("uploadurl", UPLOAD_URL);
        i.putExtra("candidateID", candidateID);
        startService(i);
}



   private String setVideoOutPutFile()
    {
        File mediaStorageDir = new File(Environment.getExternalStorageDirectory(), "/mfs_candidate_intro");

        if (!mediaStorageDir.exists())
        {
            if (!mediaStorageDir.mkdirs())
            {
                Log.d("VideoLogger", "failed to create directory");
            }
        }

        String path = Environment.getExternalStorageDirectory().getAbsolutePath();
        Log.e("external storagedirectory path= =", path);
        myfile = path + "/mfs_candidate_intro/" + candidateID + ".mp4";
        Log.e("external final file = =", myfile);
        return myfile;
    }



}

Uploadservice.java contains

package com.servicedemo;

import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import org.apache.commons.io.FileUtils;

import android.app.IntentService;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;

public class Uploadservice extends IntentService{

    private String uploadURL;
    private int candidateID;
    private String FilePath;

    public Uploadservice() {      
        super("My service");

    }

    @Override
    public IBinder onBind(Intent intent) {
    return null;
    }



    @Override
    protected void onHandleIntent(Intent intent) {   //After completion of onstartcommand system will deliver all intent object to onHandleItent method.          

        uploadURL=intent.getExtras().getString("uploadurl");
        candidateID=intent.getExtras().getInt("candidateID");
        FilePath =intent.getExtras().getString("filepath");
        Log.d("Inside onhandleIntent", FilePath);
        try {
            uploadVideo(uploadURL,candidateID,FilePath);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }


    }


    public byte[] filecovert(String path)
    {
        return null;

    }

    public void uploadVideo(String iUploadUrl, int iCandidateId, String iFilePath) throws IOException
    {
        /**
         * converts the file in the specified path to byte Array
         */
        byte[] videobytes = convertFileToBytes(iFilePath);


        // Number of chunks in Bytes..
        final long chunkSize = 100000;
        // creates a new file in the specified path..
        File videoFile = new File(iFilePath);



        if (videobytes != null && videobytes.length > 0)
        {


            String requestUri = iUploadUrl + "?CandidateID=" + iCandidateId + "&fileName=" + videoFile.getName();

            // get the number of chunks
            long numOfChunks = (videobytes.length / chunkSize);
            byte[] byteArray = new byte[(int) chunkSize];

            /**
             * Get the remaining Bytes. /Check if there is some bytes remaining after calculation of numOfChunks
             */
            long remaingbytes = videobytes.length % chunkSize;
            if (remaingbytes > 0)
            {
                // Increase number of chunks by one if some bytes are left ...
                numOfChunks = numOfChunks + 1;
            }
            long copyBytesLength = chunkSize;

            for (int chunkNo = 1; chunkNo <= numOfChunks; chunkNo++)
            {
                String requestURL = requestUri + "&TotalChunks=" + numOfChunks + "&ChunkCounter=" + chunkNo;
                copyBytesLength = ((chunkNo * chunkSize) > videobytes.length) ? remaingbytes : chunkSize;
                byteArray = new byte[(int) copyBytesLength];
                System.arraycopy(videobytes, (int) ((chunkNo - 1) * chunkSize), byteArray, 0, (int) copyBytesLength);

                // send request to Handler
                if (requestHandler(numOfChunks, byteArray, chunkNo, requestURL))
                {
                    Log.e("SplashScreen", "Request Handler Returns False " + iCandidateId);
                    break;
                }
            }
        }
    }

    /**
     * This method provides the file data as byte array
     * 
     * @param iFilePath
     *            the path to the file
     * @return the corresponding byte array representation
     * @throws IOException
     */
    private byte[] convertFileToBytes(String iFilePath) throws IOException
    {
        return FileUtils.readFileToByteArray(new File(iFilePath));
    }

    /**
     * This method handles the division of byte array data into small chunks
     * 
     * @param iNumOfChunks
     *            number of chunks available after dividing data as separate 1 MB units
     * @param iByteArray
     *            the byte array representation of video data.
     * @param iChunkNum
     *            current chunk number
     * @param iRequestURL
     *            complete upload url
     * @return true/false based upon the success result.
     */
    private boolean requestHandler(long iNumOfChunks, byte[] iByteArray, int iChunkNum, String iRequestURL)
    {
        try
        {
            boolean valid = true;
            HttpURLConnection conn = null;
            DataOutputStream dos = null;
            DataInputStream inStream = null;
            URL url = new URL(iRequestURL);
            conn = (HttpURLConnection) url.openConnection();
            conn.setDoInput(true);
            conn.setDoOutput(true);
            conn.setUseCaches(false);
            conn.setRequestMethod("POST");
            conn.setRequestProperty("Connection", "Keep-Alive");
            conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            dos = new DataOutputStream(conn.getOutputStream());
            // Writes iByteArray.length from IByteArray starting at offset 0 to the dos output stream.
            dos.write(iByteArray, 0, iByteArray.length);
            dos.flush();
            dos.close();
            // get the response code returned by the HTTP server...
            int responseCode = conn.getResponseCode();
            Log.e("SplashScreen", "Response code is " + responseCode);
            /**
             * If response code is OK ,Check if the iChunkNum == iNumOfChunks If it is equal ,it means Writting to th
             */
            if (responseCode == HttpURLConnection.HTTP_OK)
            {
                if (iChunkNum == iNumOfChunks)
                {
                    inStream = new DataInputStream(conn.getInputStream());
                    String str;
                    StringBuffer buf = new StringBuffer();
                    while ((str = inStream.readLine()) != null)
                    {
                        buf.append(str);
                    }
                    str = buf.toString();
                    Log.e("SplashScreen", "Server Response" + str);
                    inStream.close();
                }
                else
                {
                    valid = false;
                }
            }
            return valid;
        }
        catch (IOException e)
        {
            e.printStackTrace();
            return false;
        }

    }

 @Override
public void onDestroy() {
    Log.d("destroyed", "Intent destroyed");
    Toast.makeText(getApplicationContext(), "helloooooooooooo", Toast.LENGTH_LONG).show();
    super.onDestroy();
}

}

Manifest.xml contains ..

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.servicedemo"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="21" />

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.INTERNET"/>


    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

         <service
             android:name=".Myservice"
             android:exported="false"
        />

         <service
             android:name=".Uploadservice"
             android:exported="false"
        />

    </application>



</manifest>

My Problem is when file size is big it's showing

12-02 18:36:35.944: E/dalvikvm-heap(21228): Out of memory on a 90981622-byte allocation.
12-02 18:36:35.944: I/dalvikvm(21228): "IntentService[My service]" prio=5 tid=11 RUNNABLE
12-02 18:36:35.944: I/dalvikvm(21228):   | group="main" sCount=0 dsCount=0 obj=0x41bb0780 self=0x5832c038
12-02 18:36:35.944: I/dalvikvm(21228):   | sysTid=21405 nice=0 sched=0/0 cgrp=apps handle=1479722576
12-02 18:36:35.944: I/dalvikvm(21228):   | schedstat=( 23006625 25262207 18 ) utm=2 stm=0 core=2
12-02 18:36:35.944: I/dalvikvm(21228):   at org.apache.commons.io.IOUtils.toByteArray(IOUtils.java:~512)
12-02 18:36:35.944: I/dalvikvm(21228):   at org.apache.commons.io.IOUtils.toByteArray(IOUtils.java:488)
12-02 18:36:35.944: I/dalvikvm(21228):   at org.apache.commons.io.FileUtils.readFileToByteArray(FileUtils.java:1764)
12-02 18:36:35.944: I/dalvikvm(21228):   at com.servicedemo.Uploadservice.convertFileToBytes(Uploadservice.java:126)
12-02 18:36:35.944: I/dalvikvm(21228):   at com.servicedemo.Uploadservice.uploadVideo(Uploadservice.java:68)
12-02 18:36:35.944: I/dalvikvm(21228):   at com.servicedemo.Uploadservice.onHandleIntent(Uploadservice.java:47)
12-02 18:36:35.944: I/dalvikvm(21228):   at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:65)
12-02 18:36:35.944: I/dalvikvm(21228):   at android.os.Handler.dispatchMessage(Handler.java:99)
12-02 18:36:35.944: I/dalvikvm(21228):   at android.os.Looper.loop(Looper.java:137)
12-02 18:36:35.944: I/dalvikvm(21228):   at android.os.HandlerThread.run(HandlerThread.java:60)
12-02 18:36:35.949: W/dalvikvm(21228): threadid=11: thread exiting with uncaught exception (group=0x40e962a0)
12-02 18:36:35.954: E/AndroidRuntime(21228): FATAL EXCEPTION: IntentService[My service]
12-02 18:36:35.954: E/AndroidRuntime(21228): java.lang.OutOfMemoryError
12-02 18:36:35.954: E/AndroidRuntime(21228):    at org.apache.commons.io.IOUtils.toByteArray(IOUtils.java:512)
12-02 18:36:35.954: E/AndroidRuntime(21228):    at org.apache.commons.io.IOUtils.toByteArray(IOUtils.java:488)
12-02 18:36:35.954: E/AndroidRuntime(21228):    at org.apache.commons.io.FileUtils.readFileToByteArray(FileUtils.java:1764)
12-02 18:36:35.954: E/AndroidRuntime(21228):    at com.servicedemo.Uploadservice.convertFileToBytes(Uploadservice.java:126)
12-02 18:36:35.954: E/AndroidRuntime(21228):    at com.servicedemo.Uploadservice.uploadVideo(Uploadservice.java:68)
12-02 18:36:35.954: E/AndroidRuntime(21228):    at com.servicedemo.Uploadservice.onHandleIntent(Uploadservice.java:47)
12-02 18:36:35.954: E/AndroidRuntime(21228):    at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:65)
12-02 18:36:35.954: E/AndroidRuntime(21228):    at android.os.Handler.dispatchMessage(Handler.java:99)
12-02 18:36:35.954: E/AndroidRuntime(21228):    at android.os.Looper.loop(Looper.java:137)
12-02 18:36:35.954: E/AndroidRuntime(21228):    at android.os.HandlerThread.run(HandlerThread.java:60)

The problem is inside

private byte[] convertFileToBytes(String iFilePath) throws IOException
    {
        return FileUtils.readFileToByteArray(new File(iFilePath));
    } 

it is defined in the Uploadservice.java

Also,Is it neccessary to use

String requestURL = requestUri + "&TotalChunks=" + numOfChunks + "&ChunkCounter=" + chunkNo;

or we can remove it???

Community
  • 1
  • 1
Rajeev Kumar
  • 59
  • 1
  • 12

1 Answers1

0

It's because you're reading the whole video into memory before uploading! This might be OK for an image file, but you can't assume that you have enough RAM to store a video while you upload it.

You need to open the file as an InputStream, and upload as you read from the stream.

You could also use a MappedByteBuffer. I'd go with a stream, but it does look as though a MappedByteBuffer would be closer to the code you already have.

chiastic-security
  • 20,430
  • 4
  • 39
  • 67
  • i am new to android so i don't know how can i open the file as stream i am using only FileUtils.readFileToByteArray(new File(iFilePath)); ....can you tell me how to open it as stream and then convert it as Byte Array ..as i am returning only byte array from the function ..thnx in advance.. :) – Rajeev Kumar Dec 02 '14 at 13:26
  • 1
    @RajeevKumar look up `FileInputStream`. But the whole point is **to avoid** converting it to a byte array. You need a small buffer, and as you read from the stream into the buffer, you upload from there (inside a loop, until the stream is finished). – chiastic-security Dec 02 '14 at 13:28
  • please correct me if i am wrong .. At first i am converting the video file into byte array then ,dividing it into no. of chunks and for each chunk,i am setting url and then calling a function(requestHandler)which opens connection and upload the chunk ....My Question is how will i divide video into number of chunks if i use stream ????Also ,URL using &TotalChunks and &ChunkCounter to open connection ..so can't avoid dividing video into number of chunks.. ....Please provide a link if you have so.. – Rajeev Kumar Dec 02 '14 at 13:43