I have a video downloader android application It's allow people to download videos from twitter and Something has changed in 2 months Downloaded videos are not playable on Android version <= 6.0 Error is : "Can't Play This Video" Some of these videos playable but most of it is not. same format mp4.
I didn't make any changes in my code. I tried download files manually from browser and still error is occurs.
// Progress Dialog
private ProgressDialog pDialog;
public static final int progress_bar_type = 0;
// File url to download
private static String file_url = "https://video.twimg.com/ext_tw_video/1122253815884001280/pu/vid/1280x720/xTTWb4wnRMvFzpXk.mp4";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new DownloadFileFromURL().execute(file_url);
}
/**
* Showing Dialog
* */
#Override
protected Dialog onCreateDialog(int id) {
switch (id) {
case progress_bar_type: // we set this to 0
pDialog = new ProgressDialog(this);
pDialog.setMessage("Downloading file. Please wait...");
pDialog.setIndeterminate(false);
pDialog.setMax(100);
pDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pDialog.setCancelable(true);
pDialog.show();
return pDialog;
default:
return null;
}
}
/**
* Background Async Task to download file
* */
class DownloadFileFromURL extends AsyncTask<String, String, String> {
/**
* Before starting background thread Show Progress Bar Dialog
* */
#Override
protected void onPreExecute() {
super.onPreExecute();
showDialog(progress_bar_type);
}
/**
* Downloading file in background thread
* */
#Override
protected String doInBackground(String... f_url) {
int count;
try {
URL url = new URL(f_url[0]);
URLConnection conection = url.openConnection();
conection.connect();
// this will be useful so that you can show a tipical 0-100%
// progress bar
int lenghtOfFile = conection.getContentLength();
// download the file
InputStream input = new BufferedInputStream(url.openStream(),
8192);
// Output stream
OutputStream output = new FileOutputStream(Environment
.getExternalStorageDirectory().toString()
+ "/2011.mp4");
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
// publishing the progress....
// After this onProgressUpdate will be called
publishProgress("" + (int) ((total * 100) / lenghtOfFile));
// writing data to file
output.write(data, 0, count);
}
// flushing output
output.flush();
// closing streams
output.close();
input.close();
} catch (Exception e) {
Log.e("Error: ", e.getMessage());
}
return null;
}
/**
* Updating progress bar
* */
protected void onProgressUpdate(String... progress) {
// setting progress percentage
pDialog.setProgress(Integer.parseInt(progress[0]));
}
/**
* After completing background task Dismiss the progress dialog
* **/
#Override
protected void onPostExecute(String file_url) {
// dismiss the dialog after the file was downloaded
dismissDialog(progress_bar_type);
}
}
I want to make these videos playable as others. Some of the mp4 videos plable and most of its is not. I don't know the reason is codec or not but I want to make these playable too.
This videos is example of situation.
https://video.twimg.com/ext_tw_video/1122253815884001280/pu/vid/1280x720/xTTWb4wnRMvFzpXk.mp4
Your example video uses H.264 profile of High #Level 3. Not supported in Android version <= 6.
H.264 is the "image" format of the video (where audio is MP3/AAC).
Lowest-to-high Profie order is: Baseline --> Main --> High.
See docs: https://developer.android.com/guide/topics/media/media-formats#video-codecs
MediaInfo analysis:
Video
ID : 1
Format : AVC
Format/Info : Advanced Video Codec
Format profile : High#L3.1
Normally you fix by offering alternate encodings of the video file from your site. Since you're not in charge of Twitter server, you'll have to check if Twitter itself is keeping any Low/Standard-Def versions of uploaded videos, for older devices that can't handle High-Def. If found, then just offer users a multiple choice of "quality" links.
Alternatively try to see if FFmpeg can play the format. Try VLC Player app (is FFmpeg powered) on a problematic device. If it plays okay, then try importing Android-FFmpeg into your app code, where you use it to decode/play the downloaded videos in your app.
Related
Since google Drive can not download a file of more than 25 MB, as it requests the authorization of the user from an HTML page, I thought that it was necessary for these files to display the page "virus warning" in a webView in my App. So I created this small sample in Android studio to test. It is quite simple a MainActivity and an activity.xml containing a simple WebView:
public class MainActivity extends AppCompatActivity {
private static final int WRITE_SDCARD_REQUEST_CODE = 12;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// permission to write file on internal storage ....
if (ContextCompat.checkSelfPermission(MainActivity.this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
WRITE_SDCARD_REQUEST_CODE);
} else {
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
WRITE_SDCARD_REQUEST_CODE);
}
}
else {
// launch my webPage and webClient withe the given url of my file
WebView myWebView = (WebView) findViewById(R.id.webview);
myWebView.loadUrl("https://drive.google.com/uc?export=download&id=0B4fwFC8FCSQGGTZfbHYwczBXVjg");
myWebView.setWebViewClient(new MyWebViewClient());
}
}
private class MyWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// return after valid with "Download anyway " button
Log.i("URL",url);//<-- url result: https://drive.google.com/uc?export=download&confirm=LoXi&id=0B4fwFC8FCSQGGTZfbHYwczBXVjg
//with "confirm=LoXi" Added to the original link
// so i try to download this new confirmed url given by Google Drive warning page
// But the link is not valid for download!!!!! Why????
DownloadFileFromURL dFURL = new DownloadFileFromURL();
dFURL.execute(url);
// I obtain a wrong file .... 36 Ko...not good!
return true;
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == WRITE_SDCARD_REQUEST_CODE)
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
WebView myWebView = (WebView) findViewById(R.id.webview);
// original link of file Google drive that i want to download
myWebView.loadUrl("https://drive.google.com/uc?export=download&id=0B4fwFC8FCSQXbTZfbHYwczBXVjg");
myWebView.setWebViewClient(new MyWebViewClient());
}
}
class DownloadFileFromURL extends AsyncTask<String, String, String> {
/**
* Before starting background thread Show Progress Bar Dialog
* */
#Override
protected void onPreExecute() {
super.onPreExecute();
}
/**
* Downloading file in background thread
* */
#Override
protected String doInBackground(String... f_url) {
int count;
try {
URL url = new URL(f_url[0]);
URLConnection conection = url.openConnection();
conection.connect();
// this will be useful so that you can show a tipical 0-100%
// progress bar
int lenghtOfFile = conection.getContentLength();
// download the file
InputStream input = new BufferedInputStream(url.openStream(),
8192);
// Output stream
OutputStream output = new FileOutputStream(Environment
.getExternalStorageDirectory().toString()
+ "/video.mp4");
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
// publishing the progress....
// After this onProgressUpdate will be called
publishProgress("" + (int) ((total * 100) / lenghtOfFile));
// writing data to file
output.write(data, 0, count);
}
// flushing output
output.flush();
// closing streams
output.close();
input.close();
} catch (Exception e) {
Log.e("Error: ", e.getMessage());
}
return null;
}
/**
* Updating progress bar
* */
protected void onProgressUpdate(String... progress) {
// setting progress percentage
//pDialog.setProgress(Integer.parseInt(progress[0]));
}
/**
* After completing background task Dismiss the progress dialog
* **/
#Override
protected void onPostExecute(String file_url) {
// dismiss the dialog after the file was downloaded
//dismissDialog(progress_bar_type);
}
}
}
From the download link of my file of more than 25 MB (here 90 Mo) I display well the page "Virus Warning" of drive. After clicking on the download button "download anyway" I am able to get a modified link back in my WebClient. But this link does not seem valid. If I try to copy / paste it in chrome I return to the same page of the "virus Warning" !!! Why??
When I right click on the "download anyway" button to copy the link, this link is the same form that I get by my WebClient but the part "confirm=XXXX" not, and it works and gives me access to the download!
Could you give me your opinions and suggestions?
Thank you.
I finally solved the problem by managing the cookies in my WebViewClient and using DownloadManager:``
private class MyWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// prevent other actions on page
if (url.contains("export=download&confirm")){
DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
Uri source = Uri.parse(url);
DownloadManager.Request request = new DownloadManager.Request(source);
String cookie = CookieManager.getInstance().getCookie(url);
request.addRequestHeader("Cookie", cookie);
request.addRequestHeader("User-Agent", view.getSettings().getUserAgentString());
request.addRequestHeader("Accept", "text/html, application/xhtml+xml, *" + "/" + "*");
request.addRequestHeader("Accept-Language", "en-US,en;q=0.7,he;q=0.3");
request.addRequestHeader("Referer", url);
request.setDestinationInExternalPublicDir("/","video.mp4");
manager.enqueue(request);
}else {
// a keyEvent back listener should be implemented
myWebView.loadUrl(url);
}
return true;
}
#Override
public void onPageFinished(WebView view, String url){
}
}
I hope it will help.
I'd like to create app which allows to download a picture using URL address and next, shows it on my screen.
Unfortunately, in LogCat is showed this error:
BitmapFactory: Unable to decode stream: java.io.FileNotFoundException: sdcard/photoalbum/download_image.jpg: open failed: ENOENT (No such file or directory)
Download's progress, which is showing on screen, works really fast. Image has 12 KB.
But I see that this picture is not downloading on my phone (sdcard).
This is caused that I couldn't decode this stream?
I would be grateful if somebody know how to resolve/fix this problem?
Here is a code:
ImageView imageView;
String image_url = "http://montco.happeningmag.com/wp-content/uploads/2015/04/run-150x150.jpg";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.button);
imageView = (ImageView) findViewById(R.id.image_view);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
DownloadTask downloadTask = new DownloadTask();
downloadTask.execute(image_url);
}
});
}
// how to create an assign task do download this image
class DownloadTask extends AsyncTask<String,Integer,String> // second type is Integer because this is from 'int progress', third is String because this is the return ("Download Complete...")
{
// progress bar to display this download
ProgressDialog progressDialog;
#Override
protected void onPreExecute() {
progressDialog = new ProgressDialog(MainActivity.this);
progressDialog.setTitle("Download in Progress...");
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setMax(100);
progressDialog.setProgress(0);
progressDialog.show();
}
#Override
protected String doInBackground(String... params) {
// how is the maximum size of this file, we need some variable:
int file_length = 0;
String path = params[0]; // we get this URL , 0(zero) index of this argument
// how image_url on this variable call "path"
try {
URL url = new URL(path);
URLConnection urlConnection = url.openConnection();
urlConnection.connect();
file_length = urlConnection.getContentLength();
// we need a folder to storage this download image
File new_folder = new File("sdcard/photoalbum");
if(!new_folder.exists())
{
new_folder.mkdir(); // we create new folder if 'photoalbum' doesnt exist in sdcard
}
// how to put some file inside this folder
File input_file = new File(new_folder,"downloaded_image.jpg");
// how to create input STREAM to read information data from url
InputStream inputStream = new BufferedInputStream(url.openStream(),8192); // we need input stream with some buffer. 8192(8 KB) (input stream
// now I want to read informations in one kb so I need byte variable
byte[] data = new byte[1024]; // it will read info to 1 KB
// before read information we need some variable
int total = 0;
int count = 0;
// we need output stream object to write a data
OutputStream outputStream = new FileOutputStream(input_file); // because outputStream is available in input_file
// we need write information to outputStream
while((count = inputStream.read())!=-1) //loop executes until the value became (-1)
{
// how to update value from a variable total
total += count;
outputStream.write(data,0,count); // data is available on the Byte variable data; offset; count
// how to display a progress bar: we need to call publish progress method and specify special value for this progress
int progress = (int) total*100/file_length;
publishProgress(progress);
}
// how to close Stream
inputStream.close();
outputStream.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// after finished our job we need to return some result
return "Download Complete...";
}
#Override
protected void onProgressUpdate(Integer... values) {
progressDialog.setProgress(values[0]); // this will update the progress bar
}
#Override
protected void onPostExecute(String result) {
// after finishing job, we need to hide a progress bar
progressDialog.hide();
// how to display some result
Toast.makeText(getApplicationContext(),result,Toast.LENGTH_LONG).show();
// how to put image into imageView
String path = "sdcard/photoalbum/download_image.jpg";
// how to set this image in imageView
imageView.setImageDrawable(Drawable.createFromPath(path));
}
}
File new_folder = new File("sdcard/photoalbum");
if(!new_folder.exists()){
new_folder.mkdir(); // we create new folder if 'photoalbum' doesnt exist in sdcard
}
Try to modify the upper code as follow:
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())
|| !Environment.isExternalStorageRemovable()) {
File new_folder = new File(Environment.getExternalStorageDirectory().toString() + File.separator + "photoalbum");
if(!new_folder.exists()){
new_folder.mkdirs(); // we create new folder if 'photoalbum' doesnt exist in sdcard
}
}
I am trying to stream a live feed in rtsp as such:
String uri = "rtsp://54.213.167.253:5544/63a1203d-4e12-438e-86ec-f447fa90cfd7";
Uri uri_add = Uri.withAppendedPath(MediaStore.Video.Media.INTERNAL_CONTENT_URI, "1");
videoView.setVideoURI(uri_add.parse(uri));
mediaController = new MediaController(_context);
videoView.setMediaController(mediaController);
videoView.requestFocus();
videoView.start();
This works on an HTC, Sony, and LG device that I have tested with, however does not work on the Galaxy S6 or any Samsung device. I have researched the encoding compatibilities and h.264 is what my stream is encoded, which should work on all the devices I have. I am running Android v. 5.0.2 and 5.1.1 on these devices and there is no correlation between software to the issue. That is to say, the GalaxyS6 running 5.0.2 is not playing video while a HTC running 5.0.2 is playing video. I am completely lost as to what could be the cause of the "Can't Play Video" message that I get.
I have read all the articles and posts people have about streaming live video and attempted to implement them in my code, however I run in to the same issue each time. I am pretty sure there is nothing wrong with the code, else it would not work at all on any device. Anyone have any ideas what could be causing this and why?
This problem seems to be common on a few Samsung devices. Did you check what Logcat shows?
I had the same problem with a Galaxy Tab 4, I ended up using Vitamio's library for video streaming. It's not been supported for some time now, but pretty easy to use and for basic customization
Use this class. This is running on Samsung devices also.
private ProgressDialog progressDialog;
VideoView videoView;
private myAsync sync;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video);
String videourl = "rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov";
videoView = (VideoView) findViewById(R.id.video_view);
progressDialog = ProgressDialog.show(CustomizeProgressDialogActivity.this, "",
"Buffering video...", true);
progressDialog.setCancelable(false);
// progressDialog.dismiss();
MediaController mediaController = new MediaController(CustomizeProgressDialogActivity.this);
mediaController.setAnchorView(videoView);
Uri video = Uri.parse(videourl);// insert video url
videoView.setMediaController(mediaController);
videoView.setVideoURI(video);
videoView.requestFocus();
sync = new myAsync();
sync.execute();
// PlayVideo();
}
private class myAsync extends AsyncTask<Void, Integer, Void> {
int duration = 0;
int current = 0;
#Override
protected Void doInBackground(Void... params) {
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
public void onPrepared(MediaPlayer mp) {
progressDialog.dismiss();
videoView.start();
duration = videoView.getDuration();
}
});
do {
current = videoView.getCurrentPosition();
System.out.println("duration - " + duration + " current- "
+ current);
if (sync.isCancelled())
break;
}
while (current != duration || current == 0);
return null;
}
}
I am using this code to load data from online database to my android application .
I am wondering what can i add to make this code better ?
Sometimes the progress dialog keeps spinning and never gets the data, the application is stuck then, any ideas on how i can prevent that ?
class LoadAllSections extends AsyncTask<String, String, String>
{
// make a progress dialog appear with the selected specifics
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(MainActivity.this);
pDialog.setMessage("Loading all sections, please wait");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
// in the background run this code to retrieve data from the server
protected String doInBackground(String... args)
{
List<NameValuePair> params = new ArrayList<NameValuePair>();
JSONObject json = jParser.makeHttpRequest(url_Sections,"POST", params);
try
{
int success = json.getInt(TAG_SUCCESS);
sections = json.getJSONArray(TAG_SECTIONS);
if (success == 1)
{
for (int i = 0; i < sections.length(); i++)
{
JSONObject c = sections.getJSONObject(i);
section_id = c.getString(TAG_SECTION_ID);
section_name = c.getString(TAG_SECTION_NAME);
section_desc = c.getString(TAG_SECTION_DESC);
section_image = c.getString(TAG_SECTION_IMAGE);
section_valid = c.getString(TAG_SECTION_VALID);
HashMap <String,String> sectionmap = new HashMap<String,String>();
sectionmap.put(TAG_SECTION_ID, section_id);
sectionmap.put(TAG_SECTION_NAME, section_name);
sectionmap.put(TAG_SECTION_DESC, section_desc);
sectionmap.put(TAG_SECTION_IMAGE, section_image);
sectionmap.put(TAG_SECTION_VALID, section_valid);
sectionlist.add(sectionmap);
}
}
else
{
finish();
}
}
catch (JSONException e)
{
e.printStackTrace();
}
return null;
}
// disable the progress dialog and load data to the gridview
protected void onPostExecute(String file_url)
{
pDialog.dismiss();
adapter=new SectionAdapter(MainActivity.this,sectionlist);
SectionsGridView.setAdapter(adapter);
}
}
I wanted to add a comment, but I am not allowed to.
Don't have enough reputation :-(
Pass url_section as argument to doInBackground instead of making it global.
I would place the httpRequest insde a try catch block.
Did you set the timeout, if the httpRequest is not answering? I would set that to
60 seconds. I think by default this is set to 600 seconds.
Why do you pass the file_url to onPostExecute instead of passing the
sectionList?
Take a look at AsyncTask. If you don't want to pass anything between the methods, you can also use Void. So in your case AsyncTask would also do it.
First, i already know how to download, i can show the progress bar, but i cannot switch activity, by default of the download code, when download reach 100% ,it will dismiss the dialogue and remain on that page/layout, i want it to download, and then move to next activity not staying where it is.. So i added a runnable code to change activity after 2seconds of complete download, but it just move to next activity after 2seconds even when download does not excecute.. Help me check the code, and tell me what to do. Thanks
public class ClockWorkMod extends Activity {
// button to show progress dialog
Button btnShowProgress;
// Progress Dialog
private ProgressDialog pDialog;
ImageView my_image;
// Progress dialog type (0 - for Horizontal progress bar)
public static final int progress_bar_type = 0;
// File url to download
private static String file_url = "http://api.loadedgeek.com/myupgrade/clockworkmod.img";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.clockworkmod);
// show progress bar button
btnShowProgress = (Button) findViewById(R.id.btnProgressBar);
// Image view to show image after downloading
/**
* Show Progress bar click event
* */
btnShowProgress.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// starting new Async Task
new DownloadFileFromURL().execute(file_url);
}
});
}
/**
* Showing Dialog
* */
#Override
protected Dialog onCreateDialog(int id) {
switch (id) {
case progress_bar_type: // we set this to 0
pDialog = new ProgressDialog(this);
pDialog.setMessage("Installing ClockWorkMod. Please Wait...");
pDialog.setIndeterminate(false);
pDialog.setMax(100);
pDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pDialog.setCancelable(true);
pDialog.show();
return pDialog;
default:
return null;
}
}
/**
* Background Async Task to download file
* */
class DownloadFileFromURL extends AsyncTask<String, String, String> {
/**
* Before starting background thread
* Show Progress Bar Dialog
* */
#Override
protected void onPreExecute() {
super.onPreExecute();
showDialog(progress_bar_type);
}
/**
* Downloading file in background thread
* */
#Override
protected String doInBackground(String... f_url) {
int count;
try {
URL url = new URL(f_url[0]);
URLConnection conection = url.openConnection();
conection.connect();
// this will be useful so that you can show a tipical 0-100% progress bar
int lenghtOfFile = conection.getContentLength();
// download the file
InputStream input = new BufferedInputStream(url.openStream(), 8192);
// Output stream
OutputStream output = new FileOutputStream("/sdcard/MyUpgrade/clockworkmod.img");
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
// publishing the progress....
// After this onProgressUpdate will be called
publishProgress(""+(int)((total*100)/lenghtOfFile));
// writing data to file
output.write(data, 0, count);
}
// flushing output
output.flush();
// closing streams
output.close();
input.close();
} catch (Exception e) {
Log.e("Error: ", e.getMessage());
}
return null;
}
/**
* Updating progress bar
* */
protected void onProgressUpdate(String... progress) {
// setting progress percentage
pDialog.setProgress(Integer.parseInt(progress[0]));
}
/**
* After completing background task
* Dismiss the progress dialog
* **/
#Override
protected void onPostExecute(String file_url) {
// dismiss the dialog after the file was downloaded
dismissDialog(progress_bar_type);
new Handler().
postDelayed(new Runnable() {
#Override
public void run() {
Intent i= new Intent(ClockWorkMod.this, ClockWorkModFlash.class);
startActivity(i);
}
}, 2000);
}
}
{
} }
create intent to which activity you want to go and start that after download is completed like
suppose you want to go to com.ex.act onceit completes then do
Intent i=new Intent("com.ex.act");
startActivity(i);