Record video from VideoView - android

Currently doing project on live Streaming, and I succeed to play live video. Now my next task is to record the video which is playing in VideoView.
I had searched, able to found capturing video but with surface(camera) but here in VideoView I am not having any surface.
any help appreciated

You can see this link. In short your server has to support downloading. If it does, you can try the following code:
private final int TIMEOUT_CONNECTION = 5000; //5sec
private final int TIMEOUT_SOCKET = 30000; //30sec
private final int BUFFER_SIZE = 1024 * 5; // 5MB
private final int TIMEOUT_CONNECTION = 5000; //5sec
private final int TIMEOUT_SOCKET = 30000; //30sec
private final int BUFFER_SIZE = 1024 * 5; // 5MB
try {
URL url = new URL("http://....");
//Open a connection to that URL.
URLConnection ucon = url.openConnection();
ucon.setReadTimeout(TIMEOUT_CONNECTION);
ucon.setConnectTimeout(TIMEOUT_SOCKET);
// Define InputStreams to read from the URLConnection.
// uses 5KB download buffer
InputStream is = ucon.getInputStream();
BufferedInputStream in = new BufferedInputStream(is, BUFFER_SIZE);
FileOutputStream out = new FileOutputStream(file);
byte[] buff = new byte[BUFFER_SIZE];
int len = 0;
while ((len = in.read(buff)) != -1)
{
out.write(buff,0,len);
}
} catch (IOException ioe) {
// Handle the error
} finally {
if(in != null) {
try {
in.close();
} catch (Exception e) {
// Nothing you can do
}
}
if(out != null) {
try {
out.flush();
out.close();
} catch (Exception e) {
// Nothing you can do
}
}
}
If the server doesn't support downloading, there is nothing you can do.

You can use platform-tools and record video using:
adb shell screenrecord --verbose /sdcard/demo.mp4
Replace Demo with whatever file name you want.
Also this will be placed on your phone, and defaults to 6 minutes I believe.
Check out the options of screen record.
To pull the file to your computer.... (the following command, or use Android Device Monitor
adb pull /sdcard/demo.mp4
I have used this to record demo's of apps, and even played youtube, and had it record that.
It does not have audio, so that may be a major problem.
But this is included in the sdk, and records any screen showing while it is recording.

Related

Download apk failed when resume download with httpUrlConnection

I meet a problem when download apk with HttpUrlConnection.
I develop a app about 30Mb, and I create a manager to check the latest version and download it.
Because of its size, I checked the downloaded file size and resume downloading if connection was cutted off or app was shutdown by system.
The problem is that a parse error happened when install downloading apk if the whole downloading process was interrupted once.
This is the error message:
Parse error: There was a problem parsing the package.
And here is my code of downloading:
private File downloadApk(File aApkFile, String aUrl, long aStartPosition, long aEndPosition) {
try {
URL url = new URL(aUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5 * 1000);
conn.setReadTimeout(5 * 1000);
conn.setRequestMethod("GET");
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Range", StringFormatter.format("bytes=%s-", aStartPosition));
conn.connect();
sendUpdateNotification(0, 100); // update notifaction info
InputStream inputStream = conn.getInputStream();
FileOutputStream fileOutputStream = new FileOutputStream(aApkFile);
int currentPercent = 0;
long currentDownloadSize = aStartPosition;
byte readBuffer[] = new byte[1024 * 10];
int byteReadSize = 0;
while (!((byteReadSize = inputStream.read(readBuffer)) <= 0)) {
fileOutputStream.write(readBuffer, 0, byteReadSize);
currentDownloadSize += byteReadSize;
int index = (int) (currentDownloadSize * 100 / aEndPosition);
if (index != currentPercent) {
currentPercent = index;
sendUpdateNotification(currentPercent, 100);
}
}
fileOutputStream.close();
inputStream.close();
conn.disconnect();
return aApkFile;
} catch (MalformedURLException aE) {
aE.printStackTrace();
Log.e("Version", aE.getMessage());
} catch (IOException aE) {
aE.printStackTrace();
Log.e("Version", aE.getMessage());
}
return null;
}
ApkFile is the downloaded file which will not be null here.
StartPosition is the apkfile's size, and get by apkFile.length().
Endposition is the whole size of apk and get by conn.getContentLength().
Is there any ideas to fix it? Thanks.
You are deleting a former partial file with:
FileOutputStream fileOutputStream = new FileOutputStream(aApkFile);
Change to appending mode:
FileOutputStream fileOutputStream = new FileOutputStream(aApkFile, true);
Check file size of original and downloaded file. Every byte counts!

Writing an audio file to websocket using IBM Watson Android sdk

I realized after going through a post in the IBM developer forums that the android sdk reads bytes from the mic recording and writes them to the websocket. I am now trying to read bytes from an audio file on memory and write them to the websocket. How should I do this? So far I have:
public class AudioCaptureThread extends Thread{
private static final String TAG = "AudioCaptureThread";
private boolean mStop = false;
private boolean mStopped = false;
private int mSamplingRate = -1;
private IAudioConsumer mIAudioConsumer = null;
// the thread receives high priority because it needs to do real time audio capture
// THREAD_PRIORITY_URGENT_AUDIO = "Standard priority of the most important audio threads"
public AudioCaptureThread(int iSamplingRate, IAudioConsumer IAudioConsumer) {
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
mSamplingRate = iSamplingRate;
mIAudioConsumer = IAudioConsumer;
}
// once the thread is started it runs nonstop until it is stopped from the outside
#Override
public void run() {
File path = Activity.getContext.getExternalFilesDir(null);
File file = new File (path, "whatstheweatherlike.wav");
int length = (int) file.length();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] b = new byte[length];
FileInputStream in = null;
try {
in = new FileInputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
try {
for (int readNum; (readNum = in.read(b)) != -1;) {
bos.write(b, 0, readNum);
}
} catch (IOException e) {
e.printStackTrace();
}
byte[] bytes = bos.toByteArray();
mIAudioConsumer.consume(bytes);
}
However, Activity.getContext is not recognized. I can convert the file to bytes in MainActivity but how do I then write it to the websocket? Am I on the right track or is this not the right way? If it is, how do I solve this problem?
Any help is appreciated!
Activity.getContext is not recognized because there's no reference to Activity, since it's just a Thread. You would have to pass in the Activity, although it would likely make more sense just to pass in the Context if you need it.
You've got the right idea that you can create a FileInputStream and use that. You might like to use our MicrophoneCaptureThread as a reference. It'd be a very similar situation, except you'd be using your FileInputStream instead of reading from the microphone. You can check it out (and an example project that uses it) here: https://github.com/watson-developer-cloud/android-sdk/blob/master/library/src/main/java/com/ibm/watson/developer_cloud/android/library/audio/MicrophoneCaptureThread.java

How to download a database and integrate into the app

I'm trying to download a database from a server and then use it in my app. My initial situation is that I've got a database in my assets folder and I am trying to download the whole database from a server when the user is clicking a button.
I think I have to use the onUpgrade method but I don't know how I can download the database and then use it or and load it into the assetfolder.
You need to brake the problem into smaller issues.
Make sure that the server side is able to provide you with a web-service with which you'll do the actual download.
It would be ideal if your server would zip your sqlite database in order for you to minimize traffic.
After you have downloaded the db on your device, you'll have to unzip it, if you have taken this approach.
When you get to the point of having the db downloaded and unzipped it's just a matter of connecting to a sqlite db and Android provides api in this regards.
Of-course, all of the above needs to be done in a multithreaded environment, you could also take into account using an Android service.
This is an example of downloading a file from a server, it should help you get an idea, it's not too generic, it works in my environment.
private void handleSelectedItemDownload(final String downloadItem) {
try {
int bufferLength;
long downloadedSize = 0;
long downloadProgressBytes = 0;
final byte[] buffer = new byte[12 * 163840];
this.url = new URL(String.format(AppConstants.SERVICE_BASE_URL + AppConstants.MEDIA_IMAGE_REQUEST_URL_PATH + downloadItem));
InputStream inputStream = this.getStream(downloadedSize);
downloadedSize = this.chunkSize;
if (downloadedSize > 0) {
this.applicationFolder = downloadItem.equals("pictures") ? Utils.getThumbNailsFolder() : Utils.getApplicationFolder();
final File mediaFolder = new File(this.applicationFolder);
mediaFolder.mkdirs();
final File file = new File(mediaFolder, String.format(File.separator + downloadItem + ".zip"));
final FileOutputStream fileOutput = new FileOutputStream(file);
this.actionStatusProgressBar.setProgress(0);
final Message downloadStartMessage = new Message();
downloadStartMessage.what = ACTION_STARTED;
this.actionMessageHandler.sendMessage(downloadStartMessage);
int progressBarMax = (int) (this.totalDownloadSize / 1024);
this.actionStatusProgressBar.setMax(progressBarMax);
while (chunkSize != 0) {
while ((bufferLength = inputStream.read(buffer)) > 0) {
fileOutput.write(buffer, 0, bufferLength);
downloadProgressBytes += bufferLength;
final Message currentProgressMessage = new Message();
currentProgressMessage.arg1 = (int) (downloadProgressBytes / 1024);
currentProgressMessage.what = ACTION_PROGRESS_VALUE;
this.actionMessageHandler.sendMessage(currentProgressMessage);
}
inputStream.close();
this.urlConnection.disconnect();
inputStream = this.getStream(downloadedSize);
downloadedSize += chunkSize;
}
fileOutput.close();
}
this.urlConnection.disconnect();
this.totalDownloadSize = 0;
} catch (MalformedURLException e) {
Log.e("DOWNLOAD_ERROR", e.getMessage() + e.toString());
this.errorEncountered = true;
this.actionType = IDataActionListener.ACTION_TYPE.ACTION_FAILED;
this.actionMessageHandler.sendEmptyMessage(ERROR_ENCOUNTERED);
} catch (IOException e) {
Log.e("DOWNLOAD_ERROR", e.getMessage() + e.toString());
this.errorEncountered = true;
this.actionType = IDataActionListener.ACTION_TYPE.ACTION_FAILED;
this.actionMessageHandler.sendEmptyMessage(ERROR_ENCOUNTERED);
} catch (Exception e) {
Log.e("DOWNLOAD_ERROR", e.getMessage() + e.toString());
this.errorEncountered = true;
this.actionType = IDataActionListener.ACTION_TYPE.ACTION_FAILED;
this.actionMessageHandler.sendEmptyMessage(ERROR_ENCOUNTERED);
}
}
private InputStream getStream(final long downloadedSize) throws IOException {
this.urlConnection = (HttpURLConnection) this.url.openConnection();
this.urlConnection.setRequestMethod("GET");
this.urlConnection.addRequestProperty("DOWNLOADED_SIZE", String.valueOf(downloadedSize));
final InputStream inputStream = this.urlConnection.getInputStream();
this.chunkSize = this.urlConnection.getContentLength();
if (!Utils.stringIsNullOrEmpty(this.urlConnection.getHeaderField("TOTAL_SIZE"))) {
if (this.totalDownloadSize == 0) {
this.totalDownloadSize = Long.parseLong(this.urlConnection.getHeaderField("TOTAL_SIZE"));
}
}
return inputStream;
}
Afterwards, when you have downloaded your db file, you can just create a SQLiteDatabase object:
final File dbFile = new File(filePath);
if (dbFile.exists()) {
this.localDatabase = SQLiteDatabase.openDatabase(filePath, null, SQLiteDatabase.OPEN_READWRITE);
this.localDatabase.setLocale(Locale.getDefault());
}
I still stick to the opinion that you should also give zipping a thought, you reduce a LOT the traffic and the time spent over network.

0-byte files not detected when downloading files on Android

I have an app for Android which downloads hundreds of files from the Internet. Some files turn out to be 0-byte after download. The app attempts to detect such cases and delete such files after download but sometimes it fails. The problem is more frequent on Android 4.x devices.
Here is the method which does the downloading. I gets the number of actually read bytes from inputStream.read(buffer).
public class Utils
{
public static class DownloadFileData
{
int nTotalSize;
int nDownloadedSize;
}
public interface ProgressCallback
{
void onProgress(long nCurrent, long nMax);
}
public static boolean downloadFile(String sFileURL, File whereToSave, DownloadFileData fileData, ProgressCallback progressCallback)
{
InputStream inputStream = null;
FileOutputStream fileOutput = null;
try
{
URL url = new URL(sFileURL);
URLConnection connection = url.openConnection();
//set up some things on the connection
connection.setDoOutput(true);
connection.connect();
fileOutput = new FileOutputStream(whereToSave);
inputStream = connection.getInputStream();
fileData.nTotalSize = connection.getContentLength();
fileData.nDownloadedSize = 0;
byte[] buffer = new byte[1024];
int bufferLength = 0; //used to store a temporary size of the buffer
// now, read through the input buffer and write the contents to the file
while ((bufferLength = inputStream.read(buffer)) > 0)
{
// if interrupted, don't download the file further and return
// also restore the interrupted flag so that the caller stopped also
if (Thread.interrupted())
{
Thread.currentThread().interrupt();
return false;
}
// add the data in the buffer to the file in the file output stream
fileOutput.write(buffer, 0, bufferLength);
// add up the size so we know how much is downloaded
fileData.nDownloadedSize += bufferLength;
if (null != progressCallback && fileData.nTotalSize > 0)
{
progressCallback.onProgress(fileData.nDownloadedSize, fileData.nTotalSize);
}
}
return true;
}
catch (FileNotFoundException e)
{
return false; // swallow a 404
}
catch (IOException e)
{
return false; // swallow a 404
}
catch (Throwable e)
{
return false;
}
finally
{
// in any case close input and output streams
if (null != inputStream)
{
try
{
inputStream.close();
inputStream = null;
}
catch (Exception e)
{
}
}
if (null != fileOutput)
{
try
{
fileOutput.close();
fileOutput = null;
}
catch (Exception e)
{
}
}
}
}
Here is the piece of code which processes the downloads. Since sometimes the number of read bytes is incorrect (it is > 0 and the real file has the size 0 bytes) I check the size of the downloaded file with outputFile.length(). But this again gives a value > 0 even though the file is really 0 byte. I tried to also just create a new file and read its size with recheckSizeFile.length(). Still the size is determined as > 0 while it's really 0 byte.
Utils.DownloadFileData fileData = new Utils.DownloadFileData();
boolean bDownloadedSuccessully = Utils.downloadFile(app.sCurrenltyDownloadedFile, outputFile, fileData, new Utils.ProgressCallback()
{
... // progress bar is updated here
});
if (bDownloadedSuccessully)
{
boolean bIsGarbage = false;
File recheckSizeFile = new File(sFullPath);
long nDownloadedFileSize = Math.min(recheckSizeFile.length(), Math.min(outputFile.length(), fileData.nDownloadedSize));
// if the file is 0bytes, it's garbage
if (0 == nDownloadedFileSize)
{
bIsGarbage = true;
}
// if this is a video and if of suspiciously small size, it's
// garbage, too
else if (Utils.isStringEndingWith(app.sCurrenltyDownloadedFile, App.VIDEO_FILE_EXTENSIONS) && nDownloadedFileSize < Constants.MIN_NON_GARBAGE_VIDEO_FILE_SIZE)
{
bIsGarbage = true;
}
if (bIsGarbage)
{
++app.nFilesGarbage;
app.updateLastMessageInDownloadLog("File is fake, deleting: " + app.sCurrenltyDownloadedFile);
// delete the garbage file
if (null != outputFile)
{
if (!outputFile.delete())
{
Log.e("MyService", "Failed to delete garbage file " + app.sCurrenltyDownloadedFile);
}
}
}
else
{
... // process the normally downloaded file
}
I am not sure but I think there is a bug in Android with reading file size. Has anyone seen a similar problem? Or am I maybe doing something wrong here?
Thanks!
EDIT: how i determine that the files are 0-byte:
all the files which get downloaded go thru the described routines. When I then later view the download folder with a file browser (Ghost Commander), some of the files (like maybe 10%) are 0-byte. They can't be played by a video player (shown as "broken file" icon).
It looks to me like your problem is that you only check for "garbage" files if the Utils.downloadFile call returns true. If the download fails in the getInputStream call or the first read, you will have created a file with zero length which will never be deleted.
You should call flush() on your FileOutputStream to ensure that all data is written to the file. This should make your issue with 0-byte files occur less often.
To check for 0 byte files using File.length() should work properly. Can you open a shell (adb shell) on the device and run ls -l to see the byte count displayed by it is 0 (maybe your file manager has some weird issues). Also please debug (or put some log statements) that sFullPath contains the correct file paths. I can't see where sFullPath gets set in your code above and why you don't just use outputFile but recreate another File object.

AsyncTask - slow download

I am using AsyncTask to download ~50 MB files from internet. Sometimes, when I download this file, progress bar gain is very slow (even when I am on Wi-Fi). And after minute, phone shows me, download complete, but the file itself has only ~100kB, no more. But when I restart device, and try to download file, download is executed briefly and quick. Has anyone faced same problem? Do I need to erase same download memory before downloading new file? I am downloading file to Environment.externalStoryDirectory().
Thx
Calling download from activity:
mProgressDialog = new ProgressDialog(ItemDetails.this);
mProgressDialog.setTitle("Downloading");
mProgressDialog.setMessage("Downloading sth...");
mProgressDialog.setIndeterminate(false);
mProgressDialog.setMax(100);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
DownloadMapTask downloadFile = new DownloadMapTask(ItemDetails.this);
downloadFile.execute(web_location_url);
mProgressDialog.show();
Download Async Task (two methods):
#Override
protected String doInBackground(String... urls) {
int count;
PATH=maps_loc+"/Android/data/test/maps/";
try {
URL url = new URL(urls[0]);
HttpURLConnection connection2 = (HttpURLConnection) url.openConnection();
connection2.setRequestMethod("GET");
connection2.setDoOutput(true);
connection2.connect();
int lenghtOfFile = connection2.getContentLength();
File apkdir = new File(PATH);
apkdir.mkdirs();
File newInstall = new File(PATH, name+".tmp");
InputStream input = new BufferedInputStream(url.openStream());
OutputStream output = new FileOutputStream(newInstall);
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1 && running==true) {
total += count;
publishProgress((int) (total * 100 / lenghtOfFile));
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public void onProgressUpdate(Integer... args) {
ItemDetails.mProgressDialog.setProgress(args[0]);
}
Some servers will close the connection if the client has slow speed and the download takes long time, which can be the case if your program is connected to the Internet through mobile data not Wi-Fi.
You should consider supporting download resume in your program to not start from scratch every time.
I do not think there is sort of download memory that you need to clear. I have an app that can easily downloads over 50MB with no problems.
Also, you might consider obtaining a lock for both Wi-Fi and processor to keep your program running until the download finishes.
Edit
In your code, try to print the value lenghtOfFile after the line int lenghtOfFile = connection2.getContentLength(); to make sure that it is the same as the actual file size you are downloading.
Below is alternative example code which supports resume that I am using in my projects. (it is just to illustrate the idea, you will need to modify the code to your needs)
HttpClient httpClient = new DefaultHttpClient();
HttpGet request = new HttpGet(new URI(fileURL)));
HttpResponse response;
InputStream is = null;
FileOutputStream fos = null;
try {
boolean continueDownloading = false;
String tmpFileName = fileName + "_tmp";
outputFile = new File(downloadFolder, tmpFileName);
if (outputFile.exists()) {
localFileLength = outputFile.length();
if (localFileLength > 0) {
continueDownloading = true;
}
if (continueDownloading) {
request.addHeader("Range", "bytes=" + localFileLength + "-");
}
response = httpClient.execute(request);
long remoteFileLength = 0;
Header contentLengthHeader = response.getFirstHeader("Content-Length");
if (contentLengthHeader != null) {
remoteFileLength = Integer.parseInt(contentLengthHeader.getValue());
}
long downloaded = 0;
if (continueDownloading) {
downloaded = localFileLength;
}
long fullFileLength = downloaded + remoteFileLength;
fos = new FileOutputStream(outputFile, true);
is = response.getEntity().getContent();
byte[] buffer = new byte[DOWNLOAD_BUFFER_SIZE];
int len = 0;
while ((len = is.read(buffer)) != -1 && isDownloading) {
fos.write(buffer, 0, len);
downloaded += len;
}
fos.flush();
boolean success = downloaded == fullFileLength;
if (success) {
outputFile.renameTo(new File(downloadFolder, fileName));
}
} catch (Throwable ex) {
ex.printStackTrace();
} finally {
// clean up resources
}
Try using downloadManager instead of downloading manually , there are many advantages to using it.
Here is an example for it : DownloadManager Example
and take a look at the documentations : DownloadManager

Categories

Resources