0

So in my app, I want to implement an auto-upgrade feature so that my app's users can upgrade the app easily. In order to do that I decided to use my syncAdapter (already usable for updating local SQLite from a remote mySQL Server). So in my syncAdapter I am making the call for my AsyncTask class that does the app-upgrade, like this:

public SyncAdapter(Context context, boolean autoInitialize) {
    super(context, autoInitialize);
    this.context = mContext;
}

@Override
  public void onPerformSync(Account account, Bundle extras, String authority,ContentProviderClient provider, SyncResult syncResult) {
Context mcontext = mContext;
new AsyncGetVersiune(mcontext).execute("3", "1");
...
}

Then my AsyncGetVersiune class does this (if the upgrade is necessary):

public class AsyncGetVersiune extends AsyncTask<String, Integer, Double> {
  private Context mContext;

  public AsyncGetVersiune (Context context){
    super();
    mContext = context;
  }

IntentFilter filter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
mContext.registerReceiver(downloadReceiver, filter);
final String calex = calea;

AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
builder.setMessage("There is a newer version available. Upgrade now?")
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
    //if the user agrees to upgrade
    public void onClick(DialogInterface dialog, int id) {
        //start downloading the file using the download manager
        downloadManager = (DownloadManager) mContext.getSystemService(mContext.DOWNLOAD_SERVICE);
        Uri Download_Uri = Uri.parse(calex);
        DownloadManager.Request request = new DownloadManager.Request(Download_Uri);
        request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);
        request.setAllowedOverRoaming(false);
        request.setTitle("Download new version");
        request.setDestinationInExternalFilesDir(mContext, Environment.DIRECTORY_DOWNLOADS, "Newversion.apk");
        downloadReference = downloadManager.enqueue(request);
        }
     })
.setNegativeButton("Not now", new DialogInterface.OnClickListener() {
    public void onClick(DialogInterface dialog, int id) {
                    // User cancelled the dialog
    }
 });
builder.create().show();

But I get an error regarding the DialogBuilder. Apparently it does not like my Context...

*"Error parsing data android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application"*

What can I do? I would like to have the Dialog inplace... So syncAdapter checks for new version using an AsyncTask class. If the AsyncTask finds new version, then in onPostExecute I want to display the dialog and from there... start download and install of the new version

But since I am starting the upgrade process from an syncAdapter... I cant have an Activity entangled here...

So what should I do?

user1137313
  • 2,390
  • 9
  • 44
  • 91

3 Answers3

0

You should call AlertDialog on UI methods only, e.g. on onPostExecute()

Andrey Kopeyko
  • 1,556
  • 15
  • 14
  • Even if I give up the AlertDialog and just start the download.... I still need to call "request.setDestinationInExternalFilesDir(mContext, Environment.DIRECTORY_DOWNLOADS, "Newversion.apk");" that uses my Context. So still receive this error even without the AlertDialog. – user1137313 Dec 07 '14 at 23:09
  • So what is the solution? Give up using this approach? How comes every app out there can do it but I can't? – user1137313 Dec 07 '14 at 23:10
  • Please describe your needs more clearly - you first fire up AlertDialog and after start AsyncTask? or vice versa? In fist situation you should not place AlertDialog inside AsyncTask. This seems to be your mistake. You should fire up a dialog, process it's result, and if needed - start AsyncTask as usual. – Andrey Kopeyko Dec 07 '14 at 23:27
0

BadTokenException occurs when your context is no Longer valid. Try passing getApplicationContext() instead of getContext() or mActivity.this

Can you paste the code from where SyncAdapter is instantiating.

Waqar Khan
  • 468
  • 4
  • 18
0

Simply your passing wrong context variable. So need to change here from

new AsyncGetVersiune(mcontext).execute("3", "1");

to

new AsyncGetVersiune(context).execute("3", "1");

Comment this line

Context mcontext = mContext;

which created instance of it again in adapter class.

Piyush
  • 18,895
  • 5
  • 32
  • 63