Trying to circumvent NetworkOnMainThreadException on AsyncTask because of ProgressDialog - java

I have the following problem. I am using the DropBox SDK to upload a file to dropbox which works fine. When the file is being uploaded (inside an AsyncTask) a ProgressDialog is being shown with a cancel button, still fine here. What is not working fine is, when the cancel button gets pressed a NetworkOnMainThreadException is being raised. I am new to Android programming but I am suspecting it has something to do with the ProgressDialog which is in the constructor. Since it is not in the "doInBackground" part.
Tried to fix it with implementing the OnDismissListener and doing the abortion onDismiss but still no luck. I am getting the error when "mRequest.abort()" is called.
Thanks in advance for any answers!
So here is my code
public class DropBoxUpload extends AsyncTask<Void, Long, Boolean> implements OnDismissListener {
private DropboxAPI<?> mApi;
private String mPath;
private File mFile;
private long mFileLen;
private UploadRequest mRequest;
private Context mContext;
private final ProgressDialog mDialog;
private String mErrorMsg;
public DropBoxUpload(Context context, DropboxAPI<?> api, String dropboxPath, File file) {
// We set the context this way so we don't accidentally leak activities
mContext = context.getApplicationContext();
mFileLen = file.length();
mApi = api;
mPath = dropboxPath;
mFile = file;
mDialog = new ProgressDialog(context);
mDialog.setMax(100);
mDialog.setMessage("Uploading " + file.getName());
mDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mDialog.setProgress(0);
mDialog.setButton("Cancel", new OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// This will cancel the putFile operation
mDialog.dismiss();
}
});
mDialog.setCancelable(true);
mDialog.setOnDismissListener(this);
mDialog.show();
}
#Override
protected Boolean doInBackground(Void... params) {
try {
// By creating a request, we get a handle to the putFile operation,
// so we can cancel it later if we want to
FileInputStream fis = new FileInputStream(mFile);
String path = mPath + mFile.getName();
mRequest = mApi.putFileOverwriteRequest(path, fis, mFile.length(),
new ProgressListener() {
#Override
public long progressInterval() {
// Update the progress bar every half-second or so
return 500;
}
#Override
public void onProgress(long bytes, long total) {
publishProgress(bytes);
}
});
if (mRequest != null) {
mRequest.upload();
return true;
}
} catch (DropboxUnlinkedException e) {
// This session wasn't authenticated properly or user unlinked
mErrorMsg = "This app wasn't authenticated properly.";
} catch (DropboxFileSizeException e) {
// File size too big to upload via the API
mErrorMsg = "This file is too big to upload";
} catch (DropboxPartialFileException e) {
// We canceled the operation
mErrorMsg = "Upload canceled";
} catch (DropboxServerException e) {
// Server-side exception. These are examples of what could happen,
// but we don't do anything special with them here.
if (e.error == DropboxServerException._401_UNAUTHORIZED) {
// Unauthorized, so we should unlink them. You may want to
// automatically log the user out in this case.
} else if (e.error == DropboxServerException._403_FORBIDDEN) {
// Not allowed to access this
} else if (e.error == DropboxServerException._404_NOT_FOUND) {
// path not found (or if it was the thumbnail, can't be
// thumbnailed)
} else if (e.error == DropboxServerException._507_INSUFFICIENT_STORAGE) {
// user is over quota
} else {
// Something else
}
// This gets the Dropbox error, translated into the user's language
mErrorMsg = e.body.userError;
if (mErrorMsg == null) {
mErrorMsg = e.body.error;
}
} catch (DropboxIOException e) {
// Happens all the time, probably want to retry automatically.
mErrorMsg = "Network error. Try again.";
} catch (DropboxParseException e) {
// Probably due to Dropbox server restarting, should retry
mErrorMsg = "Dropbox error. Try again.";
} catch (DropboxException e) {
// Unknown error
mErrorMsg = "Unknown error. Try again.";
} catch (FileNotFoundException e) {
}
return false;
}
#Override
protected void onProgressUpdate(Long... progress) {
int percent = (int)(100.0*(double)progress[0]/mFileLen + 0.5);
mDialog.setProgress(percent);
}
#Override
protected void onPostExecute(Boolean result) {
mDialog.dismiss();
}
#Override
public void onDismiss(DialogInterface arg0) {
// TODO Auto-generated method stub
mRequest.abort();
}
}

You cannot access the mRequest object from the main UI thread as this is what is responsible for the network operation. That is why you get a NetworkOnMainThreadException when you call mRequest.abort().
You should modify your code such that you use AsyncTask.cancel on dialog dismissal and check for isCancelled periodically in your doInBackground and call mRequest.abort() when the task is cancelled.

you should call the cancel method to stop your uploading process.
ast.cancel(true);
where ast is your asynctask object

Related

How to download a file after clicking a button (Android Studio)

I recently created an activity in my app. Now I wanted the user to download a .pdf file when he/she wants to view the guidelines. I wanted to implement this on a button. Any idea how to do this properly?
Heres my code below:
public class Exhibitor_Registration_Activity extends AppCompatActivity {
Button buttonDownload;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_exhibitor_registration_);
this.setTitle("Buyer Registration");
Toolbar myToolbar = (Toolbar) findViewById(R.id.my_toolbar);
setSupportActionBar(myToolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
myToolbar.setNavigationIcon(R.drawable.ic_arrow_back_white_24dp);
final Button buttonDownload = (Button) findViewById(R.id.buttonDownload);
buttonDownload.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view) {
try {
//this is the file you want to download from the remote server
String path ="http://www.manilafame.com/website-assets/downloads/exhibitor-application-kit/local/201704/1-Summary-of-Participation-Details-April-2017_MN_002.pdfp";
//this is the name of the local file you will create
String targetFileName = null;
boolean eof = false;
URL u = new URL(path);
HttpURLConnection c = (HttpURLConnection) u.openConnection();
c.setRequestMethod("GET");
c.setDoOutput(true);
c.connect();
FileOutputStream f = new FileOutputStream(new File("c:\\junk\\"+targetFileName));
InputStream in = c.getInputStream();
byte[] buffer = new byte[1024];
int len1 = 0;
while ( (len1 = in.read(buffer)) > 0 ) {
f.write(buffer,0, len1);
}
f.close();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
}
I also got the source code from here and here.
if you want resumable, speed of download ...
follow this steps
create a class DownloadManager.java
public class DownloadManager extends AsyncTask<String,String,String>{
String downloadlink,fileDestination;
public static final int ON_INIT=100,ON_ERROR=102,ON_PROGRASS=103,ON_COMPLETED=104,STATUS_DOWNLOADED=1500,STATUS_NOT_YET=1501;
private onUpdateListener onUpdateListener;
private String downloadedPath="";
private long downloaded=0;
private File file;
private String returnData=null;
private File cacheDownloadFile;
public DownloadManager(String downloadlink,String fileDestinationPath){
this.downloadlink=downloadlink;
this.fileDestination=fileDestinationPath;
file=new File(fileDestination, Tools.getFileName(downloadlink));
cacheDownloadFile=new File(AppCostants.CHACHE_PATH+Tools.getFileName(downloadlink));
try {
if(cacheDownloadFile.isFile())
downloaded=Tools.getFileSize(cacheDownloadFile);
else
downloaded=0;
Log.d("FILE_DOWNLOAD_TAG_p",downloaded+" <- "+cacheDownloadFile.getAbsolutePath());
} catch (IOException e) {
e.printStackTrace();
}
fireOnUpdate(ON_INIT,"init ...");
}
#Override
protected String doInBackground(String... params) {
try {
File dir=new File(fileDestination);
File chacheDir=new File(AppCostants.CHACHE_PATH);
if(!chacheDir.isDirectory())
chacheDir.mkdirs();
if(!dir.isDirectory()){
dir.mkdirs();
}
if(file.exists()) {
Log.d("FILE_DOWNLOAD_TAG","File exist return complete");
return "COMPLETED";//file exist
}
if(!cacheDownloadFile.exists()){
cacheDownloadFile.createNewFile();
}
Log.d("FILE_DOWNLOAD_TAG","LINK "+downloadlink);
URL url=new URL(downloadlink);
HttpURLConnection urlConnection= (HttpURLConnection) url.openConnection();
if(downloaded>0)
urlConnection.setRequestProperty("Range","byte="+downloaded);
urlConnection.connect();
int status = urlConnection.getResponseCode();
InputStream inputStream=urlConnection.getInputStream();
int totalSize=urlConnection.getContentLength();
if(totalSize<=downloaded){
returnData= "COMPLETED";
publishProgress("File checked "+Tools.getFileName(file.getAbsolutePath()));
return returnData;
}
this.downloadedPath=cacheDownloadFile.getAbsolutePath();
byte[] buffer=new byte[1024];
int bufferLength=0;
FileOutputStream fileOutput=new FileOutputStream(cacheDownloadFile);
long d=0;
long starttime=System.currentTimeMillis();
while ((bufferLength=inputStream.read(buffer))>0){
fileOutput.write(buffer,0,bufferLength);
downloaded+=bufferLength;
d+=bufferLength;
//String l=" "+Tools.getFileName(file.getAbsolutePath())+" ( "+Tools.convertMemory(downloaded)+" / "+Tools.convertMemory(totalSize)+" )";
String l=" "+Tools.convertMemory(downloaded)+" / "+Tools.convertMemory(totalSize)+" ( "+getDownloadSpeed(starttime,d)+" )";
publishProgress(l);
if(downloaded>=totalSize){
break;
}
}
Log.d("FILE_DOWNLOAD_TAG","DWONLOADED TO "+downloadedPath+" ("+cacheDownloadFile.length()+")");
fileOutput.close();
if(Tools.fileCopy(file,cacheDownloadFile)){
Log.d("FILE_DOWNLOAD_TAG","file Copied, delete cache");
cacheDownloadFile.delete();
}
returnData="COMPLETED";
} catch (MalformedURLException e) {
returnData=null;
e.printStackTrace();
publishProgress(e.toString());
Log.d("###################",e+"");
} catch (IOException e) {
returnData=null;
e.printStackTrace();
publishProgress(e.toString());
}
return returnData;
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
fireOnUpdate(ON_PROGRASS,values[0]);
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
if(s!=null){
fireOnUpdate(ON_COMPLETED,downloadedPath);
}else{
fireOnUpdate(ON_ERROR,"Download failed");
}
}
public interface onUpdateListener{
void onUpdate(int code,String message);
}
public void setOnUpdateListener(onUpdateListener onUpdateListener){
this.onUpdateListener=onUpdateListener;
}
private void fireOnUpdate(int code,String message){
if(onUpdateListener!=null)
onUpdateListener.onUpdate(code,message);
}
private String getDownloadSpeed(long starttime,float totalDownloaded) {
long elapsedTime = System.currentTimeMillis() - starttime;
//byte :
float speed=1000f * totalDownloaded / elapsedTime;
return convert(speed);
}
private String convert(float value){
long kb=1024
,mb=kb*1024
,gb=mb*1024;
if(value<kb){
String speed=(value+"");
speed=speed.substring(0,speed.indexOf('.')+2);
return speed+" B/s";
}else if(value<mb){
value=value/kb;
String speed=(value+"");
speed=speed.substring(0,speed.indexOf('.'));
return (speed)+" KB/s";
}else if(value<gb){
value=(value/mb);
String speed=(value+"");
speed=speed.substring(0,speed.indexOf('.'));
return speed+" MB/s";
}
return "";
}
}
use this code in onClick()
DownloadManager downloadManager = new DownloadManager(url,filepath);
set event
downloadManager.setOnUpdateListener(new DownloadManager.onUpdateListener() {
#Override
public void onUpdate(int code, String message) {
if (code == DownloadManager.ON_COMPLETED) {
}
if(DownloadManager.ON_PROGRASS==code){}
}
});
start download by
downloadManager.execute();
lib setup
compile "commons-io:commons-io:+"
Tools.java
public static long getFileSize(File file) throws IOException {
FileOutputStream fileOutputStream=new FileOutputStream(file);
fileOutputStream.close();
return file.length();
}
public static boolean fileCopy(File dest,File source){
try {
FileUtils.copyFile(source,dest);
return true;
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
It is really bad idea to download file in main thread.
Use separate Thread for this
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
//your downloading here
}
});
thread.start();
it`s better, but still not so good. There are some problems with it:
1) User know nothing about downloading
So better to show additional layout which overlays screen with progress bar, probably indeterminate if you want to write less code. Then after downloading is finished you just hide your layout.
You can use runOnUiThread inside run method in thread for it.
runOnUiThread(new Runnable() {
#Override
public void run() {
//just hide some popup
//or do what you want after downloading is finished
popupLayout.serVisibility(View.GONE);
}
});
2) If user will do action which re-creates activity/fragment (like changing screen orientaion) with running thread you will get memory leak and probably activity will not know about end of download.
There are few ways to solve this problem:
You can block screen orientation at this screen, at least while downloading. Probably easiest way in your case.
You can use downloading in foreground service. Its really good
practice, but you will have to learn about services.
You can try to interrupt downloading by calling thread.interrupt()
method in onDestroy of your Activity/Fragment
You can use something like rxJava/rxAndroid (so you don not use threads at all, but you need some time for learn rxJava)
UPD
About threads
Not so bad tutorial about threads in android
You can use AsyncTask instead of Thread, but I highly recommend to use threads especially for long operations.

Downloading list of audio from URL

So I'm implementing audio Playlist app that imports audios from Parse.com, and when I retrieve them by streaming them directly from their URls, it took maybe one minute to play after clicking play button.
So I don't want to use streaming from URL methods to play my audio from server because it makes it so slow. Instead I want to download list of audios from server (Parse.com) at once and then playing them by retrieving from sdcard.
I have the class that downloads single audio from single URL .. I want to edit the code to make it downloads more than one audio at once.
here is the class I have to download audio from URL.
class DownloadMusicfromInternet extends AsyncTask<String, String, String> {
private Context mContext;
private MediaPlayer mPlayer;
public DownloadMusicfromInternet(Context context) {
mContext = context;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
// Download Music File from Internet
#Override
protected String doInBackground(String... f_url) {
int count;
try {
URL url = new URL(f_url[0]);
URLConnection conection = url.openConnection();
conection.connect();
// Get Music file length
int lenghtOfFile = conection.getContentLength();
// input stream to read file - with 8k buffer
InputStream input = new BufferedInputStream(url.openStream(), 10 * 1024);
// Output stream to write file in SD card
OutputStream output = new
Also if you could help me in how to set a name for the audios, I don't want to write static name because I'm downloading more than one audio at a time .
FileOutputStream(Environment.getExternalStorageDirectory().getPath() + "/"+"how to put unique name for each audio here ?"+".mp3");
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
publishProgress("" + (int) ((total * 100) / lenghtOfFile));
// Write data to file
output.write(data, 0, count);
}
// Flush output
output.flush();
// Close streams
output.close();
input.close();
} catch (Exception e) {
Log.e("Error: ", e.getMessage());
}
return null;
}
// While Downloading Music File
// Once Music File is downloaded
#Override
protected void onPostExecute(String file_url) {
// Play the music
playMusic();
}
// Play Music
protected void playMusic() {
// Read Mp3 file present under SD card
Uri myUri1 = Uri.parse("file:///sdcard/"+"the same unique name that was set previously ! "+".mp3");
mPlayer = new MediaPlayer();
mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
mPlayer.setDataSource(mContext.getApplicationContext(), myUri1);
mPlayer.prepare();
// Start playing the Music file
mPlayer.start();
mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
// TODO Auto-generated method stub
// Once Music is completed playing, enable the button
// btnPlayMusic.setEnabled(true);
Toast.makeText(mContext.getApplicationContext(), "Music completed playing", Toast.LENGTH_LONG).show();
}
});
} catch (IllegalArgumentException e) {
Toast.makeText(mContext.getApplicationContext(), "You might not set the URI correctly!", Toast.LENGTH_LONG).show();
} catch (SecurityException e) {
Toast.makeText(mContext.getApplicationContext(), "URI cannot be accessed, permissed needed", Toast.LENGTH_LONG).show();
} catch (IllegalStateException e) {
Toast.makeText(mContext.getApplicationContext(), "Media Player is not in correct state", Toast.LENGTH_LONG).show();
} catch (IOException e) {
Toast.makeText(mContext.getApplicationContext(), "IO Error occured", Toast.LENGTH_LONG).show();
}
}
}
and this is my adapter, and here is where my problem occurs and crashes my app. I don't know how to call ( DownloadMusicfromInternet ) more than once from the following adapter .
public class mAdapter extends ParseQueryAdapter<ParseObject> {
public mAdapter (Context context) {
super(context, new ParseQueryAdapter.QueryFactory<ParseObject>() {
public ParseQuery create() {
ParseQuery query = new ParseQuery("MusicPlaylist");
return query;
}
});
}
#Override
public View getItemView(final ParseObject object, View v, ViewGroup parent) {
if (v == null) {
v = View.inflate(getContext(), R.layout.list_music, null);
}
super.getItemView(object, v, parent);
//Audio retrieving
final ImageButton btn = (ImageButton) v.findViewById(R.id.play_btn);
final ParseFile fileObject = object.getParseFile("music");
**// here I put a loop because I want it to download a list of audios at once and I think here is the problem**
if (fileObject != null) {
for (int i = 10; i >= j; j++) {
new DownloadMusicfromInternet().execute(fileObject.getUrl());
}
fileObject.getDataInBackground(new GetDataCallback() {
#Override
public void done(byte[] bytes, com.parse.ParseException e) {
btn.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
}//end on click
}//end listener
);
}//end done
});//end get data
}//end if
return v;
}//end getItem View
}//end mAdapter
Any help would be appreciated ..

How to download multiple images and have one progressBar using AsynTask (Android)

I want my program to download many images (around 500) from the internet and store them in my external storage. Currently when I download a single image, it shows a progressBar and downloads the image properly. However when I am trying to replicate w/ two images, it gives the Toast for "Download complete" for both images being downloaded, however no progressBar for either image is shown and only the first image is properly downloaded.
Here is the code for my onCreate method for activity.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Remove Title bar
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
//force portrait orientation. (No landscape orientation).
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
setContentView(R.layout.activity_quran);
//Instantiate ProgressDialog (Used for downloading quran pages).
myProgressDialog = new ProgressDialog(QuranActivity.this);
myProgressDialog.setMessage("Downloading Quran");
myProgressDialog.setIndeterminate(true);
myProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
myProgressDialog.setCancelable(true);
//execute when the downloader must be fired.
final DownloadTask downloadTask = new DownloadTask(QuranActivity.this);
DownloadTask second = new DownloadTask(getApplicationContext());
myHTTPURL = "https://ia601608.us.archive.org/BookReader/BookReaderImages.php?zip=/10/items/05Quran15LineWhitePageWithVioletBorderWww.Momeen.blogspot.com/05%20Quran%2015%20Line%20[White%20page%20with%20Violet%20border]%20-%20www.Momeen.blogspot.com_jp2.zip&file=05%20Quran%2015%20Line%20[White%20page%20with%20Violet%20border]%20-%20www.Momeen.blogspot.com_jp2/05%20Quran%2015%20Line%20[White%20page%20with%20Violet%20border]%20-%20www.Momeen.blogspot.com_0001.jp2&scale=1&rotate=0";
myHTTPURL2 = "https://ia601608.us.archive.org/BookReader/BookReaderImages.php?zip=/10/items/05Quran15LineWhitePageWithVioletBorderWww.Momeen.blogspot.com/05%20Quran%2015%20Line%20[White%20page%20with%20Violet%20border]%20-%20www.Momeen.blogspot.com_jp2.zip&file=05%20Quran%2015%20Line%20[White%20page%20with%20Violet%20border]%20-%20www.Momeen.blogspot.com_jp2/05%20Quran%2015%20Line%20[White%20page%20with%20Violet%20border]%20-%20www.Momeen.blogspot.com_0002.jp2&scale=1&rotate=0";
//First check if the file has already been created. (Only need to download 1ce, or
//in the case where the user deleted the files, we reinstall them again).
if (isExternalStorageWritable()) {
File makeDirectory = getQuranStorageDir(QuranActivity.this, "Quran_Pages");
for (int i = 0; i < 2; i++) {
Bundle myBundle = new Bundle();
myBundle.putInt("i", i);
if (i == 0) {
downloadTask.execute(myHTTPURL);
try {
downloadTask.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
myProgressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
#Override
public void onCancel(DialogInterface dialog) {
downloadTask.cancel(true);
}
});
} else {
/*if (downloadTask.getStatus() == AsyncTask.Status.FINISHED) {
downloadTask.execute(myHTTPURL2);
} else if (downloadTask.getStatus() == AsyncTask.Status.RUNNING) {
try {
downloadTask.execute(myHTTPURL2).wait(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} */
second.execute(myHTTPURL2);
try {
second.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
// downloadTask.execute(myHTTPURL2);
}
}
}
and this is the code for my AsynTask Class.
#TargetApi(Build.VERSION_CODES.FROYO)
private class DownloadTask extends AsyncTask {
private Context context;
private PowerManager.WakeLock myWakeLock;
public DownloadTask(Context context) {
this.context = context;
}
#Override
protected String doInBackground(String... sUrl) {
InputStream input = null;
OutputStream output = null;
HttpURLConnection connection = null;
try {
URL url = new URL(sUrl[0]);
connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("GET");
connection.connect();
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
return "Server returned HTTP " + connection.getResponseCode()
+ " " + connection.getResponseMessage();
}
//Display download percentage.
int fileLength = connection.getContentLength();
//create folder to place the downloaded file in.
// File Path:E:\Android\data\com.syedabdullah.syed.quran_memorization_application
// \files\Quran Memorization Application\Quran_Pictures
//So first create a root folder Quran Memorization Application then inside that
//folder we create another folder named Quran Pictures.
/* File rootFolder = new File(getExternalFilesDir("Quran Memorization Application"),
"Quran_Pages"); */
//Here we insert inside the Quran_Pictures folder the quran_pages.
//String myFileName = "quran_01.jpg";
Bundle y = new Bundle();
int retrievePos = y.getInt("i");
String quranFilePageName = "_" + retrievePos + ".jpg";
// String fileName = "justwork.jpg";
File sup = new File(getExternalFilesDir("Quran Memorization Application"), "Quran_Pages");
File myFile = new File(sup, quranFilePageName);
myFile.createNewFile();
//downlaod the file.
input = connection.getInputStream();
output = new FileOutputStream(myFile);
byte data[] = new byte[4096];
long total = 0;
int count;
while ((count = input.read(data)) != -1) {
//allow cancel with back button.
if (isCancelled()) {
input.close();
return null;
}
total += count;
//publish the progress.
if (fileLength > 0) {
publishProgress((int) (total * 100 / fileLength));
}
output.write(data, 0, count);
}
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
intent.setData(Uri.fromFile(myFile));
QuranActivity.this.sendBroadcast(intent);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (output != null) {
output.close();
}
if (input != null) {
input.close();
}
} catch (IOException e) {
e.printStackTrace();
}
if (connection != null) {
connection.disconnect();
}
}
return null;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
//Take CPU lock to prevent CPU from going off if the user presses the power button.
//during download.
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
myWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, getClass().getName());
myWakeLock.acquire();
myProgressDialog.show();
}
#Override
protected void onProgressUpdate(Integer... progress) {
super.onProgressUpdate(progress);
//If we get here length is known, so setIndertimante to false.
myProgressDialog.setIndeterminate(false);
myProgressDialog.setMax(100);
myProgressDialog.setProgress(progress[0]);
}
#Override
protected void onPostExecute(String result) {
myWakeLock.release();
myProgressDialog.dismiss();
if (result != null) {
Toast.makeText(context, "Download error: " + result, Toast.LENGTH_LONG).show();
} else {
Toast.makeText(context, "Download Complete", Toast.LENGTH_SHORT).show();
}
}
} }
I was hoping to have a for loop that would create hundreds of downloadTasks and download all the images I need, and then I would call the get method. However in order for that to work, I first need too know why when I try for 2 images only the first one gets downloaded and why no progressbar shows up. Also if possible if I could get a hint as to how I can make my progressBar update for all the images and not be designed for just 1. Thanks in advance. (Note all URLs are currect.)
Thank you so much! figured out that my loops were suppose to go inside doInBackground. Also to anyone else having a similar issue. To download multiple files and display a decent progressBar, here is a very great tutorial: http://theopentutorials.com/tutorials/android/dialog/android-download-multiple-files-showing-progress-bar/

Failed to Exit or finish my app android (Activity) correctly

The following app upload video to Dropbox when it is start, I added finish() in the end of onCreate to exit the app when its completed the uploading, but I got "Unfortunately, DBRoulette has stopped.".
In the Eclipse LogCat:
Activity com.dropbox.android.sample.DBRoulette has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView#42a7ee38 that was originally added here
android.view.WindowLeaked: Activity com.dropbox.android.sample.DBRoulette has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView#42a7ee38 that was originally added here
I have Progress viewer which may cause the problem but I don't know how to solve it!
What I want to do is closing the app automatically when the uploading completed.
DBRoulette.java
#SuppressLint("SimpleDateFormat")
public class DBRoulette extends Activity {
private static final String TAG = "DBRoulette";
final static private String APP_KEY = "<My APP_KEY>";
final static private String APP_SECRET = "<My APP_SECRET>";
// You don't need to change these, leave them alone.
final static private String ACCOUNT_PREFS_NAME = "prefs";
final static private String ACCESS_KEY_NAME = "ACCESS_KEY";
final static private String ACCESS_SECRET_NAME = "ACCESS_SECRET";
private static final boolean USE_OAUTH1 = false;
DropboxAPI<AndroidAuthSession> mApi;
private boolean mLoggedIn;
// Android widgets
private Button mSubmit;
private RelativeLayout mDisplay;
private Button mGallery;
private ImageView mImage;
private final String PHOTO_DIR = "/Motion/";
#SuppressWarnings("unused")
final static private int NEW_PICTURE = 50;
private String mCameraFileName;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
mCameraFileName = savedInstanceState.getString("mCameraFileName");
}
// We create a new AuthSession so that we can use the Dropbox API.
AndroidAuthSession session = buildSession();
mApi = new DropboxAPI<AndroidAuthSession>(session);
// Basic Android widgets
setContentView(R.layout.main);
checkAppKeySetup();
mSubmit = (Button) findViewById(R.id.auth_button);
mSubmit.setOnClickListener(new OnClickListener() {
#SuppressWarnings("deprecation")
public void onClick(View v) {
// This logs you out if you're logged in, or vice versa
if (mLoggedIn) {
logOut();
} else {
// Start the remote authentication
if (USE_OAUTH1) {
mApi.getSession().startAuthentication(DBRoulette.this);
} else {
mApi.getSession().startOAuth2Authentication(
DBRoulette.this);
}
}
}
});
mDisplay = (RelativeLayout) findViewById(R.id.logged_in_display);
// This is where a photo is displayed
mImage = (ImageView) findViewById(R.id.image_view);
File outFile = new File("/mnt/sdcard/ipwebcam_videos/video.mov");
mCameraFileName = outFile.toString();
UploadPicture upload = new UploadPicture(DBRoulette.this, mApi, PHOTO_DIR,outFile);
upload.execute();
// Display the proper UI state if logged in or not
setLoggedIn(mApi.getSession().isLinked());
finish();
}
#Override
protected void onSaveInstanceState(Bundle outState) {
outState.putString("mCameraFileName", mCameraFileName);
super.onSaveInstanceState(outState);
}
#Override
protected void onResume() {
super.onResume();
AndroidAuthSession session = mApi.getSession();
if (session.authenticationSuccessful()) {
try {
session.finishAuthentication();
storeAuth(session);
setLoggedIn(true);
} catch (IllegalStateException e) {
showToast("Couldn't authenticate with Dropbox:"
+ e.getLocalizedMessage());
Log.i(TAG, "Error authenticating", e);
}
}
}
private void logOut() {
// Remove credentials from the session
mApi.getSession().unlink();
clearKeys();
// Change UI state to display logged out version
setLoggedIn(false);
}
#SuppressWarnings("deprecation")
public String getRealPathFromURI(Uri contentUri)
{
String[] proj = { MediaStore.Audio.Media.DATA };
Cursor cursor = managedQuery(contentUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
private void setLoggedIn(boolean loggedIn) {
mLoggedIn = loggedIn;
if (loggedIn) {
mSubmit.setText("Logout from Dropbox");
mDisplay.setVisibility(View.VISIBLE);
} else {
mSubmit.setText("Login with Dropbox");
mDisplay.setVisibility(View.GONE);
mImage.setImageDrawable(null);
}
}
private void checkAppKeySetup() {
// Check to make sure that we have a valid app key
if (APP_KEY.startsWith("CHANGE") || APP_SECRET.startsWith("CHANGE")) {
showToast("You must apply for an app key and secret from developers.dropbox.com, and add them to the DBRoulette ap before trying it.");
finish();
return;
}
// Check if the app has set up its manifest properly.
Intent testIntent = new Intent(Intent.ACTION_VIEW);
String scheme = "db-" + APP_KEY;
String uri = scheme + "://" + AuthActivity.AUTH_VERSION + "/test";
testIntent.setData(Uri.parse(uri));
PackageManager pm = getPackageManager();
if (0 == pm.queryIntentActivities(testIntent, 0).size()) {
showToast("URL scheme in your app's "
+ "manifest is not set up correctly. You should have a "
+ "com.dropbox.client2.android.AuthActivity with the "
+ "scheme: " + scheme);
finish();
}
}
private void showToast(String msg) {
Toast error = Toast.makeText(this, msg, Toast.LENGTH_LONG);
error.show();
}
/**
* Shows keeping the access keys returned from Trusted Authenticator in a
* local store, rather than storing user name & password, and
* re-authenticating each time (which is not to be done, ever).
*/
private void loadAuth(AndroidAuthSession session) {
SharedPreferences prefs = getSharedPreferences(ACCOUNT_PREFS_NAME, 0);
String key = prefs.getString(ACCESS_KEY_NAME, null);
String secret = prefs.getString(ACCESS_SECRET_NAME, null);
if (key == null || secret == null || key.length() == 0
|| secret.length() == 0)
return;
if (key.equals("oauth2:")) {
// If the key is set to "oauth2:", then we can assume the token is
// for OAuth 2.
session.setOAuth2AccessToken(secret);
} else {
// Still support using old OAuth 1 tokens.
session.setAccessTokenPair(new AccessTokenPair(key, secret));
}
}
/**
* Shows keeping the access keys returned from Trusted Authenticator in a
* local store, rather than storing user name & password, and
* re-authenticating each time (which is not to be done, ever).
*/
private void storeAuth(AndroidAuthSession session) {
// Store the OAuth 2 access token, if there is one.
String oauth2AccessToken = session.getOAuth2AccessToken();
if (oauth2AccessToken != null) {
SharedPreferences prefs = getSharedPreferences(ACCOUNT_PREFS_NAME,
0);
Editor edit = prefs.edit();
edit.putString(ACCESS_KEY_NAME, "oauth2:");
edit.putString(ACCESS_SECRET_NAME, oauth2AccessToken);
edit.commit();
return;
}
// Store the OAuth 1 access token, if there is one. This is only
// necessary if
// you're still using OAuth 1.
AccessTokenPair oauth1AccessToken = session.getAccessTokenPair();
if (oauth1AccessToken != null) {
SharedPreferences prefs = getSharedPreferences(ACCOUNT_PREFS_NAME,
0);
Editor edit = prefs.edit();
edit.putString(ACCESS_KEY_NAME, oauth1AccessToken.key);
edit.putString(ACCESS_SECRET_NAME, oauth1AccessToken.secret);
edit.commit();
return;
}
}
private void clearKeys() {
SharedPreferences prefs = getSharedPreferences(ACCOUNT_PREFS_NAME, 0);
Editor edit = prefs.edit();
edit.clear();
edit.commit();
}
private AndroidAuthSession buildSession() {
AppKeyPair appKeyPair = new AppKeyPair(APP_KEY, APP_SECRET);
AndroidAuthSession session = new AndroidAuthSession(appKeyPair);
loadAuth(session);
return session;
}
}
UploadPicture.java
public class UploadPicture extends AsyncTask<Void, Long, Boolean> {
private DropboxAPI<?> mApi;
private String mPath;
private File mFile;
private long mFileLen;
private UploadRequest mRequest;
private Context mContext;
private final ProgressDialog mDialog;
private String mErrorMsg;
private File outFiles;
public UploadPicture(Context context, DropboxAPI<?> api, String dropboxPath,
File file) {
// We set the context this way so we don't accidentally leak activities
mContext = context.getApplicationContext();
mFileLen = file.length();
mApi = api;
mPath = dropboxPath;
mFile = file;
Date dates = new Date();
DateFormat dfs = new SimpleDateFormat("yyyyMMdd-kkmmss");
String newPicFiles = dfs.format(dates) + ".mov";
String outPaths = new File(Environment
.getExternalStorageDirectory(), newPicFiles).getPath();
outFiles = new File(outPaths);
mDialog = new ProgressDialog(context);
mDialog.setMax(100);
mDialog.setMessage("Uploading " + outFiles.getName());
mDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mDialog.setProgress(0);
mDialog.setButton(ProgressDialog.BUTTON_POSITIVE, "Cancel", new OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// This will cancel the putFile operation
mRequest.abort();
}
});
mDialog.show();
}
#Override
protected Boolean doInBackground(Void... params) {
try {
// By creating a request, we get a handle to the putFile operation,
// so we can cancel it later if we want to
FileInputStream fis = new FileInputStream(mFile);
String path = mPath + outFiles.getName();
mRequest = mApi.putFileOverwriteRequest(path, fis, mFile.length(),
new ProgressListener() {
#Override
public long progressInterval() {
// Update the progress bar every half-second or so
return 500;
}
#Override
public void onProgress(long bytes, long total) {
publishProgress(bytes);
}
});
if (mRequest != null) {
mRequest.upload();
return true;
}
} catch (DropboxUnlinkedException e) {
// This session wasn't authenticated properly or user unlinked
mErrorMsg = "This app wasn't authenticated properly.";
} catch (DropboxFileSizeException e) {
// File size too big to upload via the API
mErrorMsg = "This file is too big to upload";
} catch (DropboxPartialFileException e) {
// We canceled the operation
mErrorMsg = "Upload canceled";
} catch (DropboxServerException e) {
// Server-side exception. These are examples of what could happen,
// but we don't do anything special with them here.
if (e.error == DropboxServerException._401_UNAUTHORIZED) {
// Unauthorized, so we should unlink them. You may want to
// automatically log the user out in this case.
} else if (e.error == DropboxServerException._403_FORBIDDEN) {
// Not allowed to access this
} else if (e.error == DropboxServerException._404_NOT_FOUND) {
// path not found (or if it was the thumbnail, can't be
// thumbnailed)
} else if (e.error == DropboxServerException._507_INSUFFICIENT_STORAGE) {
// user is over quota
} else {
// Something else
}
// This gets the Dropbox error, translated into the user's language
mErrorMsg = e.body.userError;
if (mErrorMsg == null) {
mErrorMsg = e.body.error;
}
} catch (DropboxIOException e) {
// Happens all the time, probably want to retry automatically.
mErrorMsg = "Network error. Try again.";
} catch (DropboxParseException e) {
// Probably due to Dropbox server restarting, should retry
mErrorMsg = "Dropbox error. Try again.";
} catch (DropboxException e) {
// Unknown error
mErrorMsg = "Unknown error. Try again.";
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return false;
}
#Override
protected void onProgressUpdate(Long... progress) {
int percent = (int)(100.0*(double)progress[0]/mFileLen + 0.5);
mDialog.setProgress(percent);
}
#Override
protected void onPostExecute(Boolean result) {
mDialog.dismiss();
if (result) {
showToast("Image successfully uploaded");
} else {
showToast(mErrorMsg);
}
}
private void showToast(String msg) {
Toast error = Toast.makeText(mContext, msg, Toast.LENGTH_LONG);
error.show();
}
}
Your problem is that you are trying to update an Activity's UI after the activity has finished.
First, you kick of an AsyncTask which posts progress updates to the UI thread. Then, before the task completes, you call finish(). Any updates to the Activity's UI after finish() is called are liable to throw exceptions, cause window leak issues, etc.
If you want to have any UI behavior as you perform your AsyncTask, you do not want to finish() the Activity until it the task is completed.
To achieve this, you could include a callback in the onPostExecute which tells the activity it is OK to finish once the AsyncTask completes.
This is how I would do it:
Change the signature of UploadPicture:
final Activity callingActivity;
public UploadPicture(final Activity callingActivity, DropboxAPI api, String dropboxPath, File file) {
Context mContext = callingActivity.getApplicationContext();
this.callingActivity = callingActivity;
Add the finish call to onPostExecute:
#Override
protected void onPostExecute(Boolean result) {
mDialog.dismiss();
if (result) {
showToast("Image successfully uploaded");
} else {
showToast(mErrorMsg);
}
callingActivity.finish(); //Finish activity only once you are done
}

Sip Error while registration

I am using native methods of sip calling and it is working fine but some time it is giving registration error IN_PROGRESS (Error Code -9 ) .I have search in Sip Error codes but dint find any error code of this kind . Here is my code for sip registration .PLease tell me if any one have idea about this error please tell me .
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.*;
import android.net.sip.*;
import java.text.ParseException;
/**
* Handles all calling, receiving calls, and UI interaction in the WalkieTalkie app.
*/
public class WalkieTalkieActivity extends Activity implements View.OnTouchListener {
public String sipAddress = null;
public static SipManager manager = null;
public static SipProfile me = null;
public SipAudioCall call = null;
public SipErrorCode sipcode;
public SipException sipexeception;
public static WalkieTalkieActivity walkiy;
public static WalkieTalkieActivity getInstance() {
if (walkiy == null) {
walkiy = new WalkieTalkieActivity();
}
return walkiy;
}
#
Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
Log.e("onCreate", "onCreate");
initializeManager(this);
}
#
Override
public void onStart() {
super.onStart();
// When we get back from the preference setting Activity, assume
// settings have changed, and re-login with new auth info.
}
#
Override
public void onDestroy() {
super.onDestroy();
if (call != null) {
call.close();
}
closeLocalProfile();
}
#
Override
protected void onResume() {
initializeManager(this);
super.onResume();
}
public void initializeManager(Context ctx) {
Log.e("inilitize", "initialize manager");
if (manager == null) {
manager = SipManager.newInstance(ctx);
}
initializeLocalProfile(ctx);
}
/**
* Logs you into your SIP provider, registering this device as the location to
* send SIP calls to for your SIP address.
*/
public void initializeLocalProfile(final Context ctx) {
Log.e("inilitize", "initialize profile");
if (manager == null) {
Log.e("inilitize", "return in profile");
updateStatus("we are unable to establish this feature on your device ", ctx);
Log.e("Wifi state", "" + SipManager.isSipWifiOnly(ctx));
return;
}
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ctx);
String username = prefs.getString("namePref", "XYZ");
String domain = prefs.getString("domainPref", "236.343.230.2");
String password = prefs.getString("passPref", "XYZ");
try {
Log.e("inilitize", "building profile ");
SipProfile.Builder builder = new SipProfile.Builder(username, domain);
builder.setPassword(password);
me = builder.build();
manager.open(me);
Log.e("alredy registered1", "" + manager.isRegistered(me.getUriString()));
try {
if (manager.isRegistered(me.getUriString())) {
Log.e("alredy registered2", "" + manager.isRegistered(me.getUriString()));
updateStatus("Ready", ctx);
return;
}
} catch (SipException e) {
// TODO Auto-generated catch block
closeLocalProfile();
e.printStackTrace();
}
manager.setRegistrationListener(me.getUriString(), new SipRegistrationListener() {
public void onRegistering(String localProfileUri) {
Log.e("Sip restration", "Registering with SIP Server..." + me.getUriString());
updateStatus("Registering with SIP Server...", ctx);
}
public void onRegistrationDone(String localProfileUri, long expiryTime) {
Log.e("Sip restration", "Ready");
updateStatus("Ready", ctx);
}
public void onRegistrationFailed(String localProfileUri, int errorCode,
String errorMessage) {
Log.e("Error Code Registration ", SipErrorCode.toString(errorCode) + " " + errorCode);
updateStatus(SipErrorCode.toString(errorCode), ctx);
}
});
} catch (ParseException pe) {
updateStatus("Connection Error.", ctx);
} catch (SipException se) {
updateStatus("Connection error.", ctx);
}
}
/**
* Closes out your local profile, freeing associated objects into memory
* and unregistering your device from the server.
*/
public void closeLocalProfile() {
if (manager == null) {
return;
}
try {
if (me != null) {
manager.unregister(me, new SipRegistrationListener() {
#
Override
public void onRegistrationFailed(String localProfileUri, int errorCode,
String errorMessage) {
// TODO Auto-generated method stub
Log.e("unregister failed", "unregister failed");
}
#
Override
public void onRegistrationDone(String localProfileUri, long expiryTime) {
// TODO Auto-generated method stub
Log.e("unregister done", "unregister done");
}
#
Override
public void onRegistering(String localProfileUri) {
// TODO Auto-generated method stub
Log.e("unregistering", "unregistering");
}
});
manager.close(me.getUriString());
}
} catch (Exception ee) {
Log.d("WalkieTalkieActivity/onDestroy", "Failed to close local profile.", ee);
}
}
/**
* Make an outgoing call.
*/
public void initiateCall(String number, final Context ctx, final View v) {
Log.d("Number", "" + number);
sipAddress = number;
Log.e("initiating call", "initiating call");
try {
SipAudioCall.Listener listener = new SipAudioCall.Listener() {#
Override
public void onCallBusy(SipAudioCall call) {
// TODO Auto-generated method stub
Log.e("buzy", "buzy");
super.onCallBusy(call);
}
#
Override
public void onCallHeld(SipAudioCall call) {
// TODO Auto-generated method stub
Log.e("held", "held");
super.onCallHeld(call);
}
#
Override
public void onCalling(SipAudioCall call) {
// TODO Auto-generated method stub
Log.e("calling", "calling");
super.onCalling(call);
}
#
Override
public void onChanged(SipAudioCall call) {
// TODO Auto-generated method stub
Log.e("changed", "changed");
super.onChanged(call);
}
#
Override
public void onError(SipAudioCall call, int errorCode,
String errorMessage) {
// TODO Auto-generated method stub
Log.e("call error", "error" + SipErrorCode.toString(errorCode) + " " + errorCode);
CallingScreen.fa.finish();
super.onError(call, errorCode, errorMessage);
}
#
Override
public void onReadyToCall(SipAudioCall call) {
// TODO Auto-generated method stub
Log.e("ready to call", "ready to call ");
super.onReadyToCall(call);
}
#
Override
public void onRinging(SipAudioCall call, SipProfile caller) {
// TODO Auto-generated method stub
Log.e("ringing", "ringing");
super.onRinging(call, caller);
}
#
Override
public void onRingingBack(SipAudioCall call) {
// TODO Auto-generated method stub
Log.e("ringing back", "ringing back");
super.onRingingBack(call);
}
// Much of the client's interaction with the SIP Stack will
// happen via listeners. Even making an outgoing call, don't
// forget to set up a listener to set things up once the call is established.
#
Override
public void onCallEstablished(SipAudioCall call) {
Log.e("call established", "call established");
call.startAudio();
updateTime(true, ctx);
}
#
Override
public void onCallEnded(SipAudioCall call) {
Log.e("call ended", "call ended");
updateTime(false, ctx);
CallingScreen.fa.finish();
}
};
Log.e("param 1 ", "" + me.getUriString());
call = manager.makeAudioCall(me.getUriString(), sipAddress + "#216.245.200.2:5060", listener, 30);
} catch (Exception e) {
e.printStackTrace();
Log.i("WalkieTalkieActivity/InitiateCall", "Error when trying to close manager.", e);
if (me != null) {
try {
closeLocalProfile();
} catch (Exception ee) {
ee.printStackTrace();
Log.i("WalkieTalkieActivity/InitiateCall",
"Error when trying to close manager.", ee);
ee.printStackTrace();
}
}
if (call != null) {
call.close();
}
}
}
public void updateStatus(final String status, final Context context) {
// Be a good citizen. Make sure UI changes fire on the UI thread.
this.runOnUiThread(new Runnable() {
public void run() {
generateNotification(context, status);
}
});
}
public void updateTime(final Boolean status, final Context context) {
// Be a good citizen. Make sure UI changes fire on the UI thread.
this.runOnUiThread(new Runnable() {
public void run() {
if (status) {
CallingScreen.fa.calling_screen_text.setVisibility(View.GONE);
CallingScreen.fa.ch.setVisibility(View.VISIBLE);
CallingScreen.fa.ch.start();
} else {
CallingScreen.fa.ch.stop();
}
}
});
}
public void updateStatus(SipAudioCall call) {
String useName = call.getPeerProfile().getDisplayName();
if (useName == null) {
useName = call.getPeerProfile().getUserName();
}
// updateStatus(useName + "#" + call.getPeerProfile().getSipDomain());
}
public boolean onTouch(View v, MotionEvent event) {
if (call == null) {
return false;
} else if (event.getAction() == MotionEvent.ACTION_DOWN && call != null && call.isMuted()) {
call.toggleMute();
} else if (event.getAction() == MotionEvent.ACTION_UP && !call.isMuted()) {
call.toggleMute();
}
return false;
}
public void speaker(Boolean state) {
if (call != null)
call.setSpeakerMode(state);
}
public void endcall() {
if (call != null) {
try {
call.endCall();
} catch (SipException se) {
Log.d("WalkieTalkieActivity/onOptionsItemSelected",
"Error ending call.", se);
}
call.close();
}
}
public static void generateNotification(Context context, String message) {
Log.e("inilitize", "generate notification");
int icon = R.drawable.ic_launcher;
long when = System.currentTimeMillis();
NotificationManager notificationManager = (NotificationManager)
context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification(icon, message, when);
String title = context.getString(R.string.app_name);
Intent notificationIntent = new Intent(context, Splash_screen.class);
// set intent so it does not start a new activity
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |
Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent intent =
PendingIntent.getActivity(context, 0, notificationIntent, 0);
notification.setLatestEventInfo(context, title, message, intent);
notificationManager.notify(0, notification);
}
}
SIP is a transaction based protocol, this means, every negotiation process is a transaction (e.g. a basic registration process would imply sending a REISTER request and receive 200 OK response). I posted a small example in this response.
IN_PROGRESS error initially indicates that you tried to start a new transaction, in your scenario you're trying to send a REGISTER request, when client is already in another related one.
A quite typical scenario is, in a fast logout/login, trying to register when unregistration process is still running (no 200 OK final response has been received).
Main problem regarding Android's SIP implementation and this error code is that it's used when as generic error when processing a SIP request fails so, previous meaning loses its significance.
Because of previous problem you would need to check logcat to get more information (you should see something like "~~~~~ SipSessionGroup:: processing ") but, best way to handle this, would be working with different listeners provided by the stack.
The stack provides two listeners that can get registration errors: SipRegistrationListener and SipSession.Listener. Both provides onRegistrationFailed callback but, later one, also provides onRegistrationTimeout, that can be quite helpful. Actually, you already used SipRegistrationListener in your code but I don't really get why you say that it should be set after open because open would try to automatically register and, if some error occurs, you won't be notified.
On the other hand, main problem with this listeners is that registration can fail because of several reason (you can check a list of different error responses here) and current implementation only notifies of error codes >= 500 (those are server and global failures) but not others like quite common 406. This is, in my opinion, an important bug in this stack.

Categories

Resources