I've tried and done everything that I read on internet and here on stackoverflow to solve my problem, but no success till now. What I'm trying to do is basically click on a button and show a ProgressDialog while the MediaPlayer is buffering a stream from internet. I got many types of erros with context stuff (NullPointerException) and thread problems too. Here are some details about the code:
the button is a toggle button with background image sat based on events (on, off, not connected show different image buttons);
The function prepareStream() is the one that should be ran in a thread and dismiss the ProgressDialog after load the stream. it's calling an http stream of BBC radio;
I guess that the problem is about the context... I've put some Log.d TAGs on the code to check where was happening the problem and O figured out that was on mediaPlayer.start() method.
He goes the little boy:
package com.android.iFocus;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.media.MediaPlayer;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.ToggleButton;
import com.insightoverflow.iFocus.R;
public class iFocusActivity extends Activity implements OnClickListener {
//Declare Controls
public int count = 0;
public int x = 1;
public MediaPlayer mediaPlayer = null;
ToggleButton toggleRain = null;
Button buttonAbout = null;
Button buttonMethod = null;
Button buttonLink = null;
public ProgressDialog progressDialog;
public static final String TAG = "getFocused";
public boolean isOnline() {
//Check if internet is connected
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null;
}
public void prepareStream(final Context context){
if(isOnline()){
// init player
new Thread()
{
public void run()
{
try {
sleep(1500);
//progressDialog.show();
mediaPlayer = MediaPlayer.create(context, Uri.parse("http://vprbbc.streamguys.net:80/vprbbc24.mp3"), null);
x=2;
} catch (Exception e){
x=3;
}
//dismiss the progressdialog
progressDialog.dismiss();
}
}.start();
} else {
x=3;
}
}
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
// load layout
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// load controls
toggleRain = (ToggleButton)findViewById(R.id.toggleRain);
buttonAbout = (Button)findViewById(R.id.buttonAbout);
buttonMethod = (Button)findViewById(R.id.buttonMethod);
buttonLink = (Button)findViewById(R.id.buttonLink);
//Define Listeners (click event handler)
toggleRain.setOnClickListener(this);
buttonAbout.setOnClickListener(this);
buttonMethod.setOnClickListener(this);
buttonLink.setOnClickListener(this);
// init state for player
count = 0;
//Context APP
//Context appContext = this.getApplicationContext();
if (!isOnline()){
toggleRain.setBackgroundDrawable(getResources().getDrawable(R.drawable.notconnectedbutton));
x=3;
}
}
public void onClick(View v) {
if( toggleRain.getId() == ((Button)v).getId() ){
//meanwhile device is offline, do this
do {
toggleRain.setBackgroundDrawable(getResources().getDrawable(R.drawable.notconnectedbutton));
try{
Thread.currentThread();
//do what you want to do before sleeping
Thread.sleep(1000);//sleep for 1000 ms
//do what you want to do after sleeptig
} catch(Exception ie){}
continue;
}while (!isOnline());
//If device is online, go for this
if (((CompoundButton) toggleRain).isChecked()) {
toggleRain.setBackgroundDrawable(getResources().getDrawable(R.drawable.stopbutton));
} else {
toggleRain.setBackgroundDrawable(getResources().getDrawable(R.drawable.playbutton));
}
//----> HERE GOES WHERE I THINK IS THE PROBLEM <-----
//---------------------------------------------------
if (isOnline()){
//If music is not playing, start music
if(count==0){
Log.d(TAG, "START PROGRESS DIALOG");
progressDialog = ProgressDialog.show(v.getContext(), "Load", "Loading");
//progressDialog = ProgressDialog.show(, "Load", "Loading...", true, false);
Log.d(TAG, "END PROGRESS DIALOG");
Log.d(TAG, "START PREPARE STREAM");
Context context = v.getContext();
prepareStream(context);
Log.d(TAG, "END PREPARE STREAM");
Log.d(TAG, "START MEDIA PLAYER START");
//LOG CAT START AND END ALL OF THE OTHER LOG TAGS, EXCEPT THIS mediaplayer.start()
mediaPlayer.start();
Log.d(TAG, "END MEDIAPLAYER START");
count = 1;
} else {
mediaPlayer.pause();
count = 0;
}
}
} else if( buttonAbout.getId() == ((Button)v).getId() ){
Intent i = new Intent(iFocusActivity.this, AboutActivity.class);
startActivity(i);
}
else if ( buttonMethod.getId() == ((Button)v).getId() ){
Intent o = new Intent(iFocusActivity.this, MethodActivity.class);
startActivity(o);
}
else if ( buttonLink.getId() == ((Button)v).getId() ){
Uri uri = Uri.parse( "http://getFocused.in" );
startActivity( new Intent( Intent.ACTION_VIEW, uri ) );
}
}
#Override
protected void onDestroy() {
super.onDestroy();
if(mediaPlayer != null) {
mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = null;
}
}
}
So logcat tell me on the time mediaPlayer.start() is called the NullPointerException
You must run your ProgressDialog.show() in the runOnUiThread() method(Not in the main UI thread). See the Android docs here
Create a progress dialog object and then, write this code.
runOnUiThread(new Runnable(){
#Override
public void run() {
dialog.show();
}
});
Also the calls prepareStream() and mediaplayer.start() should go into a separate thread and not the main UI thread.
Sort out the thread related issues and you should be done.
Related
Before shouting that this is a duplicate question, please note that i have gone trough the following articles / questions :
One;
Two;
Three;
Four;
Five;
Six;
Seven;
Search Query
Ok. Now, since, hopefully we established that I'm not so lazy, just dumb, I can ask for your help : how to check if data connection is on and if not prompt the user to turn on data services or exit app android ?!
Please take in consideration that I'm new to Java/XML/Android, and I will require thorough explanations if possible, because everything I've tried so far doesn't work (since incomplete code, obsolete code, poor improvisation and programming skills (mine, of course)).
I will settle for the code too, but if accompanied with (some) explanations is for the better, since it is an opportunity for me to understand and learn.
This is the only thing sort of "working" util now (sort of because, it ends allways saying "Error setting mobile data state" even if I have enabled data before running the app ) :
public class WelcomeActivity extends AppCompatActivity {
ImageView imageView;
public void setMobileDataState(boolean mobileDataEnabled)
{
try
{
TelephonyManager telephonyService = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
Method setMobileDataEnabledMethod = telephonyService.getClass().getDeclaredMethod("setDataEnabled", boolean.class);
if (null != setMobileDataEnabledMethod)
{
setMobileDataEnabledMethod.invoke(telephonyService, mobileDataEnabled);
}
}
catch (Exception ex)
{
//Log.e(TAG, "Error setting mobile data state", ex);
Context context = getApplicationContext();
Toast.makeText(context, "Error setting mobile data state", Toast.LENGTH_LONG).show();
}
}
public boolean getMobileDataState()
{
try
{
TelephonyManager telephonyService = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
Method getMobileDataEnabledMethod = telephonyService.getClass().getDeclaredMethod("getDataEnabled");
if (null != getMobileDataEnabledMethod)
{
boolean mobileDataEnabled = (Boolean) getMobileDataEnabledMethod.invoke(telephonyService);
return mobileDataEnabled;
}
}
catch (Exception ex)
{
// Log.e(TAG, "Error getting mobile data state", ex);
Context context = getApplicationContext();
Toast.makeText(context, "Error getting mobile data state", Toast.LENGTH_LONG).show();
}
return false;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_welcome);
imageView = (ImageView) findViewById(R.id.coverSpin);
Animation animation = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.welcome_animation);
imageView.setAnimation(animation);
getMobileDataState();
setMobileDataState(true);
........................................
This is the first Activity from my app, it is a "welcome" animation activity, where I would like to check if data is on, then app runs normally further, if not, give the user the possibility to enable data, if, when (from settings) the user returns with data disabled then the app does not continue and exits ...
Thank you for your time and understanding (for my no-skills and problem).
Any help is appreciated !!!
I would like to say THANK YOU to : vidulaJ and Jagadesha NH . Combining the two solutions from them I succeded in acomplishing the task. I posted the solution that I used, just in case anyone else needs it. vidulaJ and Jagadesha NH thank you, again !
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.provider.Settings;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.Toast;
import java.lang.reflect.Method;
public class WelcomeActivity extends AppCompatActivity {
private ImageView imageView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_welcome);
imageView = (ImageView) findViewById(R.id.coverSpin);
Animation animation = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.welcome_animation);
imageView.setAnimation(animation);
if(isMobileDataEnabled()){
//Mobile data is enabled and do whatever you want here
Toast.makeText(this, getString(R.string.sDataOKEnable), Toast.LENGTH_SHORT).show();
}
else{
//Mobile data is disabled here
new AlertDialog.Builder(this).setTitle(getString(R.string.sDataReqMes))
.setMessage(getString(R.string.sDataReqEnable)).setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// if user clicks ok then it will open network settings
startActivity(new Intent(Settings.ACTION_WIRELESS_SETTINGS));
}
}).setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
}).show();
}}
private boolean isMobileDataEnabled(){
boolean mobileDataEnabled = false;
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
try {
Class cmClass = Class.forName(cm.getClass().getName());
Method method = cmClass.getDeclaredMethod("getMobileDataEnabled");
method.setAccessible(true);
mobileDataEnabled = (Boolean)method.invoke(cm);
} catch (Exception e) {
e.printStackTrace();
}
return mobileDataEnabled;
}
}
I could still use some help in openning the data enable/disable activity/menu directly and not the general settings activity ...
Try this.
import android.content.Context;
import android.net.ConnectivityManager;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import java.lang.reflect.Method;
public class WelcomeActivity extends AppCompatActivity{
private ImageView imageView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_welcome);
imageView = (ImageView) findViewById(R.id.coverSpin);
Animation animation = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.welcome_animation);
imageView.setAnimation(animation);
if(isMobileDataEnabled()){
//Mobile data is enabled and do whatever you want here
}
else{
//Mobile data is disabled here
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("Error");
builder.setMessage("No mobile data connection detected.");
builder.setCancelable(false);
builder.setPositiveButton("Exit", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
finish();
}
});
AlertDialog alert = builder.create();
alert.show();
}
}
private boolean isMobileDataEnabled(){
boolean mobileDataEnabled = false;
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
try {
Class cmClass = Class.forName(cm.getClass().getName());
Method method = cmClass.getDeclaredMethod("getMobileDataEnabled");
method.setAccessible(true);
mobileDataEnabled = (Boolean)method.invoke(cm);
} catch (Exception e) {
e.printStackTrace();
}
return mobileDataEnabled;
}
}
Try this simple program, if the data is not on it will alert user to open settings
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.provider.Settings;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (!isDataAvailable()) { //check if data is enabled or not
new AlertDialog.Builder(this).setTitle("Unable to connect")
.setMessage("Enable data?").setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// if user clicks ok then it will open network settings
startActivity(new Intent(Settings.ACTION_WIRELESS_SETTINGS));
}
}).setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
}).show();
} else {
Toast.makeText(this, "DATA IS ON", Toast.LENGTH_SHORT).show();
}
}
private boolean isDataAvailable() {
// returns true or false based on whether data is enabled or not
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
return networkInfo != null && networkInfo.isConnected();
}
}
Please try this
public boolean isNetworkAvailable(Context context) {
ConnectivityManager ConnectMgr = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
if (ConnectMgr == null)
return false;
NetworkInfo NetInfo = ConnectMgr.getActiveNetworkInfo();
if (NetInfo == null)
return false;
if (!NetInfo.isConnected()) {
//Show pop up
}
}
Don't forget to add these permission in manifest.
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
I have some pretty standard code to run an MP3, but it takes like 2 seconds to play it. This app is very simple. This app should play a 1-2 second sound. Also, is there a way to buffer the mp3 at app's load into the RAM or something so it can play very quickly(w/o delay)? Please help!
import android.content.Context;
import android.media.MediaPlayer;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
public class MainActivity1 extends ActionBarActivity {
MediaPlayer mediaPlayer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_activity1);
}
public void playSound(View v)throws Exception{
mediaPlayer = MediaPlayer.create(this, R.raw.john_cena);
mediaPlayer.setLooping(false);
mediaPlayer.start();
Thread.sleep(1500);
//mediaPlayer.stop();
mediaPlayer.reset();
mediaPlayer.release();
Log.d("1234FIND", "STOP RELEASE RESET");
}
}
If you want to avoid the slight delay as the media file is loaded, you should prepare your media player instance ahead of time. There's a delay while your media file is loaded and prepared for playback. You have a few options:
Continue to use MediaPlayer.create(), but do so sooner, before you're ready to call playSound(). In the simple example you provided, try calling MediaPlayer.create() in the onCreate() method.
You could also use the prepareAsync() and setOnPreparedListener() methods to prepare the media file in the background and set a notification when it is ready. This is more complicated but provides you with more control and a better user experience. If you need to load a large file, this is the best way to make it work. Small audio files probably aren't as big of a deal.
If you're going to play the same media file over and over again, you don't need to release the MediaPlayer right away. If you don't reset or release, the media will still be in memory and can play again immediately. But be sure to call release() when you're definitely done, and in the lifecycle events such as onPause() or onStop().
See the documentation for details.
To get it to play for a few seconds and then stop, use Android's CountDownTimer:
// Will call onFinish() after 2 seconds. Second parameter is
// for onTick() which we don't need and can ignore.
new CountDownTimer(2000, 2000) {
public void onTick(long millisUntilFinished) {
// Do nothing...
}
public void onFinish() {
mediaPlayer.stop();
// Decide here if you need to prepare a new clip
// or release the media player
}
}.start();
Here is a complete example:
package com.example.matthew.somediaplayer;
import android.content.res.AssetFileDescriptor;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import java.io.IOException;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "TEST";
private MediaPlayer mediaPlayer;
private boolean isMediaPlayerPrepared = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.button);
button.setEnabled(false);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mediaPlayer.isPlaying() == false) {
playSound();
}
}
});
}
#Override
public void onResume(){
super.onResume();
Log.d(TAG, "In onResume()");
createAndPrepareMediaPlayer();
}
#Override
public void onStop() {
super.onStop();
Log.d(TAG, "In onStop()");
mediaPlayer.release();
isMediaPlayerPrepared = false;
}
#Override
public void onPause(){
Log.d(TAG, "In onPause()");
super.onPause();
}
public void createAndPrepareMediaPlayer() {
Log.d(TAG, "In createAndPrepareMediaPlayer()");
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
if(isMediaPlayerPrepared == false) {
try {
AssetFileDescriptor afd = getResources().openRawResourceFd(R.raw.test);
mediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
Log.d(TAG, "Media player is prepared.");
isMediaPlayerPrepared = true;
Button button = (Button) findViewById(R.id.button);
button.setEnabled(true);
}
});
Log.d(TAG, "Beginning to prepare media player.");
mediaPlayer.prepareAsync();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void playSound() {
Log.d(TAG, "In playSound()");
if( isMediaPlayerPrepared ) {
// Will call onFinish() after 2 seconds. Second parameter is
// for onTick() which we don't need and can ignore.
new CountDownTimer(2000, 2000) {
public void onTick(long millisUntilFinished) {
// Do nothing...
}
public void onFinish() {
Log.d(TAG, "In onFinish()");
// We can't call a method like pause on an unprepared MediaPlayer instance.
if( isMediaPlayerPrepared ) {
mediaPlayer.pause();
} else {
Log.d(TAG, "Media player isn't prepared, and isn't allowed to pause.");
}
}
}.start();
mediaPlayer.setLooping(false);
mediaPlayer.seekTo(0); // set to beginning of track (if not already)
mediaPlayer.start();
Log.d(TAG, "Starting to play a sound.");
}
}
}
I am running a Text To Speech code, but now my new requirement is to provide "Pause" facility. I read number of SO questions and found I have to write data into a file and have to use media player class to play the file. Below is my code.
public void speak(String text)
{
HashMap<String,String> map = new HashMap<String,String>();
map.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, text);
tts.synthesizeToFile(text, map,"ttsFile.wav");
//tts.speak(text, TextToSpeech.QUEUE_FLUSH, null);
}
Here I have 2 questions.
I do not want to open media player to play the file, file should be played inside the app with the media player controls (just like how you can set videoView.setMediaController(); to VideoView). How can I do this? any example please?
Is there any "Cache" place to save the above file so it will be deleted once the app is closed?
You can do something like this:
Create a video player in your application :
VideoPlayerActivity.java:
package com.camera.manual;
import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.Window;
import android.view.WindowManager;
import android.widget.MediaController;
import android.widget.Toast;
import android.widget.VideoView;
public class VideoPlayerActivity extends Activity {
private boolean mResumed = false;
private boolean mFocused = false;
private boolean mControlResumed = false;
private VideoView videoView = null;
private int stopPosition = 0;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTheme(R.style.Theme_TransparentVideo);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
setContentView(R.layout.video_view);
videoView =(VideoView)findViewById(R.id.myvideoview);
MediaController mediaController= new MediaController(this);
mediaController.setAnchorView(videoView);
Uri uri=Uri.parse("android.resource://"+getPackageName()+"/"+R.raw.slow);
videoView.setMediaController(mediaController);
videoView.setVideoURI(uri);
videoView.requestFocus();
videoView.start();
}
#Override
public void onPause() {
super.onPause();
mResumed = false;
if (mControlResumed) {
if (null != videoView)
videoView.pause();
stopPosition = videoView.getCurrentPosition();
mControlResumed = false;
}
}
#Override
public void onResume() {
super.onResume();
mResumed = true;
if (mFocused && mResumed && !mControlResumed) {
if(null != videoView) {
//videoView.resume();
videoView.seekTo(stopPosition);
videoView.start();
}
mControlResumed = true;
}
}
#Override
public void onWindowFocusChanged(boolean hasFocus) {
mFocused = hasFocus;
if (mFocused && mResumed && !mControlResumed) {
if (null != videoView) {
//videoView.resume();
videoView.seekTo(stopPosition);
videoView.start();
}
mControlResumed = true;
}
}
}
You can call it like this:
Intent intent = new Intent();
intent.setClass(mContext, VideoPlayerActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
mContext.startActivity(intent);
Hi I have created download process activity and it's run on button click. This activity opens on listitem click. But Now I want to run the download process on lisitem click, instread of button click.
ZipDownloader.java
import java.io.File;
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.view.WindowManager;
import android.widget.Toast;
import com.kabelash.sg.util.DecompressZip;
import com.kabelash.sg.util.DownloadFile;
import com.kabelash.sg.util.ExternalStorage;
import com.kabelash.sg.R;
public class ZipDownloader extends Activity {
protected ProgressDialog mProgressDialog;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate( savedInstanceState );
setContentView( R.layout.zipdownload );
// Keep the screen (and device) active as long as this app is frontmost.
// This is to avoid going to sleep during the download.
getWindow().addFlags( WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON );
}
/**
* Invoked when user presses "Start download" button.
*/
public void startDownload( View v ) {
String url = "http://sample.co.uk/sample.zip";
new DownloadTask().execute( url );
}
/**
* Background task to download and unpack .zip file in background.
*/
private class DownloadTask extends AsyncTask<String,Void,Exception> {
#Override
protected void onPreExecute() {
showProgress();
}
#Override
protected Exception doInBackground(String... params) {
String url = (String) params[0];
try {
downloadAllAssets(url);
} catch ( Exception e ) { return e; }
return null;
}
}
//Progress window
protected void showProgress( ) {
mProgressDialog = new ProgressDialog(this);
mProgressDialog.setTitle( R.string.progress_title );
mProgressDialog.setMessage( getString(R.string.progress_detail) );
mProgressDialog.setIndeterminate( true );
mProgressDialog.setCancelable( false );
mProgressDialog.show();
}
protected void dismissProgress() {
// You can't be too careful.
if (mProgressDialog != null && mProgressDialog.isShowing() && mProgressDialog.getWindow() != null) {
try {
mProgressDialog.dismiss();
} catch ( IllegalArgumentException ignore ) { ; }
}
mProgressDialog = null;
}
}
on MainActivity.java
#Override
public boolean onOptionsItemSelected(MenuItem item) {
super.onOptionsItemSelected(item);
switch(item.getItemId()){
case R.id.update:
Intent intent = new Intent(this, ZipDownloader.class);
startActivity(intent);
break;
}
return true;
}
Please don't ignore this question. Thanks in advance and sorry for my English.
Have you tried bringing your AsyncTask code into the activity you want your listitem clicked, then just
switch(item.getItemId()){
case R.id.update:
String url = "http://sample.co.uk/sample.zip";
new DownloadTask().execute( url );
break;
}
return true;
call the background task onclick?
ProgressDialog quits updating when orientation of screen changes. I have put into place a fix that salvages the asynctask and sets the activity of the asynctask to the new activity after it is destroyed and rebuilt. The percentage complete on the progressdialog stays at the percentage it was at before the orientation change.
What am I missing?
package net.daleroy.fungifieldguide.activities;
import java.io.BufferedInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import android.app.Activity;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.view.View.OnClickListener;
import android.widget.Toast;
import net.daleroy.fungifieldguide.R;
import net.daleroy.fungifieldguide.fungifieldguideapplication;
public class FungiFieldGuide extends Activity {
//static final int PROGRESS_DIALOG = 0;
//ProgressThread progressThread;
private final static String LOG_TAG = FungiFieldGuide.class.getSimpleName();
fungifieldguideapplication appState;
private DownloadFile mTask;
public boolean mShownDialog;
ProgressDialog progressDialog;
private final static int DIALOG_ID = 1;
#Override
protected void onPrepareDialog(int id, Dialog dialog) {
super.onPrepareDialog(id, dialog);
if ( id == DIALOG_ID ) {
mShownDialog = true;
}
}
private void onTaskCompleted() {
Log.i(LOG_TAG, "Activity " + this + " has been notified the task is complete.");
//Check added because dismissDialog throws an exception if the current
//activity hasn't shown it. This Happens if task finishes early enough
//before an orientation change that the dialog is already gone when
//the previous activity bundles up the dialogs to reshow.
if ( mShownDialog ) {
dismissDialog(DIALOG_ID);
Toast.makeText(this, "Finished..", Toast.LENGTH_LONG).show();
}
}
#Override
protected Dialog onCreateDialog(int id) {
switch(id) {
case DIALOG_ID:
progressDialog = new ProgressDialog(this);
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setMessage("Loading Database (only first run)...");
return progressDialog;
default:
return super.onCreateDialog(id);
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.main);
appState = ((fungifieldguideapplication)this.getApplication());
Object retained = getLastNonConfigurationInstance();
if ( retained instanceof DownloadFile ) {
Log.i(LOG_TAG, "Reclaiming previous background task.");
mTask = (DownloadFile) retained;
mTask.setActivity(this);
//showDialog(DIALOG_ID);
}
else {
if(!appState.service.createDataBase())
{
Log.i(LOG_TAG, "Creating new background task.");
//showDialog(DIALOG_ID);
mTask = new DownloadFile(this);
mTask.execute("http://www.codemarshall.com/Home/Download");
}
}
//showDialog(PROGRESS_DIALOG);
View btn_Catalog = findViewById(R.id.btn_Catalog);
btn_Catalog.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
Intent i = new Intent(getBaseContext(), Cat_Genus.class);//new Intent(this, Total.class);
startActivity(i);
}
});
View btn_Search = findViewById(R.id.btn_Search);
btn_Search.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
Intent i = new Intent(getBaseContext(), Search.class);//new Intent(this, Total.class);
startActivity(i);
}
});
}
#Override
public Object onRetainNonConfigurationInstance() {
mTask.setActivity(null);
return mTask;
}
#Override
public void onDestroy()
{
super.onDestroy();
//progressDialog.dismiss();
//progressDialog = null;
appState.service.ClearSearchParameters();
}
private class DownloadFile extends AsyncTask<String, Integer, Boolean>{
private FungiFieldGuide activity;
private boolean completed;
private String Error = null;
private String Content;
private DownloadFile(FungiFieldGuide activity) {
this.activity = activity;
}
#Override
protected void onPreExecute()
{
showDialog(DIALOG_ID);
}
#Override
protected Boolean doInBackground(String... urlarg) {
int count;
try {
URL url = new URL(urlarg[0]);
URLConnection conexion = url.openConnection();
conexion.setDoInput(true);
conexion.setUseCaches(false);
// this will be useful so that you can show a tipical 0-100% progress bar
int lenghtOfFile = conexion.getContentLength();
// downlod the file
InputStream input = new BufferedInputStream(conexion.getInputStream());
OutputStream output = new FileOutputStream("/data/data/net.daleroy.fungifieldguide/databases/Mushrooms.db");
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
// publishing the progress....
publishProgress((int)total*100/lenghtOfFile);
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
} catch (Exception e) {
Log.i(LOG_TAG, e.getMessage());
}
return null;
}
#Override
public void onProgressUpdate(Integer... args){
progressDialog.setProgress(args[0]);
}
#Override
protected void onPostExecute(Boolean result)
{
completed = true;
notifyActivityTaskCompleted();
}
private void notifyActivityTaskCompleted() {
if ( null != activity ) {
activity.onTaskCompleted();
}
}
private void setActivity(FungiFieldGuide activity) {
this.activity = activity;
if ( completed ) {
notifyActivityTaskCompleted();
}
}
}
}
This is not a real solution but to prevent this I just disabled orientation changes during the life of the AsyncTask with adding first:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
and when the job is done:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
Hope this helps.