简体   繁体   中英

How to save state of a progressbar when app is killed?

I am building a simple downloader app, with a pause/resume button. When I click on pause button and kill the app the download progress isn't shown anymore, after I open the app again. I want to save the download progress state even if the app is killed. Can anyone help me with this? I'm building the app using download manager pro library from github. here's the code: Activity Class:

    public class MainActivity extends AppCompatActivity {

    String[] permissions = {
            Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.WRITE_EXTERNAL_STORAGE
    };
    public static final int REQUEST_ID_MULTIPLE_PERMISSIONS = 100;
    EditText edt_url;
    Button btn_download;
    TextView fileNametv, ProgressbarTv;
    private MyDownloadService mService;
   ProgressBar progressBar;
    String filename, url;
    /* UrlFileNameListener listener;*/
    Integer progress;
    MyReceiver receiver;
    public static MainActivity instance;
   /* RecyclerView recyclerView;
    List<Model> downloadList;
    LinearLayoutManager manager;
    DownloadAdapter adapter;
    //    ImageView pausebtn;
    int position;*/
    File myDirectory;
    Boolean mBound = false;
    Button pause_btn;
    int tasktoken;
   /* Model model;
    Parcelable mListState;
    private final String KEY_RECYCLER_STATE = "recycler_state";
    private final String KEY_LIST_STATE = "list_state";*/

   private ServiceConnection mServiceConnection = new ServiceConnection() {
       @Override
       public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
           mBound = true;
           MyDownloadService.LocalBinder localBinder = (MyDownloadService.LocalBinder) iBinder;
           mService = localBinder.getService();
       }

       @Override
       public void onServiceDisconnected(ComponentName componentName) {
            mBound = false;
       }
   };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

      /*  if(savedInstanceState!=null){
            mListState = savedInstanceState.getParcelable(KEY_RECYCLER_STATE);
            downloadList =savedInstanceState.getParcelableArrayList(KEY_LIST_STATE);
        } */
        setContentView(R.layout.activity_main);
        edt_url = findViewById(R.id.edt_url);
        btn_download = findViewById(R.id.btn_download);
        pause_btn = findViewById(R.id.pause_resume);
        /*recyclerView = findViewById(R.id.recycler_view);
        downloadList = new ArrayList<>();
        manager = new LinearLayoutManager(this);
        adapter = new DownloadAdapter(downloadList, this);
        recyclerView.setLayoutManager(manager);
        DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(),
                manager.getOrientation());
        recyclerView.addItemDecoration(dividerItemDecoration);
        recyclerView.setAdapter(adapter);*/
        fileNametv = findViewById(R.id.download_file_name);
        ProgressbarTv = findViewById(R.id.progress_tv);
        progressBar = findViewById(R.id.download_progress);
       // pausebtn = findViewById(R.id.pause_resume);
        instance = this;

       /* if (progress!= null && filename != null) {
            savedInstanceState.putInt("progress", progress);
            savedInstanceState.putString("filename",filename);
        //    savedInstanceState.putString("filename", model.getFileName());
          //  savedInstanceState.putParcelable("list",mListState);
        }*/


        receiver = new MyReceiver();

        btn_download.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                getDownloadProcess();
            }
        });

        pause_btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mService.pauseDownload(tasktoken);
            }
        });
        LocalBroadcastManager.getInstance(this)
                .registerReceiver(receiver,
                        new IntentFilter("download"));

        if (checkAndRequestPermissions()) {
            myDirectory = new File(Environment.getExternalStorageDirectory() + "/" + "RITSDownloads2");
            if (!myDirectory.exists()) {
                myDirectory.mkdir();
            }
        }
    }

    @Override
    protected void onStart() {
        super.onStart();
        Intent intent = new Intent(this,MyDownloadService.class);

        bindService(intent,mServiceConnection,Context.BIND_AUTO_CREATE);

    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt("progress", progress);
        outState.putString("filename",filename);

     /*   mListState = manager.onSaveInstanceState();
        outState.putParcelable(KEY_RECYCLER_STATE,mListState);
        outState.putParcelableArrayList(KEY_LIST_STATE, (ArrayList<? extends Parcelable>) adapter.getDownloadList());*/
    }

    @Override
    protected void onPause() {
        super.onPause();
        //mListState = manager.onSaveInstanceState();

    }

    @Override
    protected void onResume() {
        super.onResume();
      //  manager.onRestoreInstanceState(mListState);

    }

    @Override
    public void onBackPressed() {
        progress = progressBar.getProgress();
        super.onBackPressed();
    }
    /*  @Override
    public void onRestoreInstanceState(Bundle savedInstanceState, PersistableBundle persistentState) {
        super.onRestoreInstanceState(savedInstanceState, persistentState);
         manager.onRestoreInstanceState(mListState);
        savedInstanceState.getParcelable(KEY_RECYCLER_STATE);
        savedInstanceState.getParcelableArrayList(KEY_LIST_STATE);

    }
*/

    private void getDownloadProcess() {
        url = edt_url.getText().toString();
        filename = URLUtil.guessFileName(url, null, null);
        //listener.setUrl(url,filename);
        edt_url.setText("");
      /*  model = new Model();
        model.setFileName(filename);
        downloadList.add(model);
        adapter.notifyDataSetChanged();*/
        fileNametv.setText(filename);
        Intent intent = new Intent(MainActivity.this, MyDownloadService.class);
        intent.putExtra("filename", filename);
        intent.putExtra("url", url);
        intent.setAction(DownloadActions.ACTION.Download_ACTION);
        startService(intent);



    }


    public class MyReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            progress = intent.getIntExtra("progress", 1);

            ReportStructure reportStructure = MyDownloadService.downloadManagerPro.singleDownloadStatus(intent.getIntExtra("tasktoken",1));
            tasktoken = intent.getIntExtra("tasktoken",1);
//            model.setProgress(progress);
           /*int position = downloadList.indexOf(model);
            DownloadAdapter.DownloadHolder holder = getDownloadHolder(position);
            holder.progressBar.setProgress(progress);*/
           progressBar.setProgress(progress);

        }

    }

   /* public DownloadAdapter.DownloadHolder getDownloadHolder(int position) {
        return (DownloadAdapter.DownloadHolder) recyclerView.findViewHolderForLayoutPosition(position);
    }
*/


    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        savedInstanceState.getInt("progress");
        savedInstanceState.getString("filename");



      /*  Log.d("savedInstancestate",savedInstanceState.toString());
        //savedInstanceState.getInt("position");
        if(savedInstanceState!=null){
            List<Model> downloadList = savedInstanceState.getParcelableArrayList(KEY_LIST_STATE);
            adapter = new DownloadAdapter(downloadList,this);

        }
*/

    }





    private boolean checkAndRequestPermissions() {
        if (ContextCompat.checkSelfPermission(this, permissions[0]) != PackageManager.PERMISSION_GRANTED
                && ContextCompat.checkSelfPermission(this, permissions[1]) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, permissions, REQUEST_ID_MULTIPLE_PERMISSIONS);
            return false;
        } else {
            return true;
        }
    }


    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           @NonNull String permissions[], @NonNull int[] grantResults) {

        String TAG = "LOG_PERMISSION";
        Log.d(TAG, "Permission callback called-------");
        switch (requestCode) {
            case REQUEST_ID_MULTIPLE_PERMISSIONS: {

                Map<String, Integer> perms = new HashMap<>();
                // Initialize the map with both permissions
                perms.put(this.permissions[0], PackageManager.PERMISSION_GRANTED);
                perms.put(this.permissions[1], PackageManager.PERMISSION_GRANTED);
                // Fill with actual results from user
                if (grantResults.length > 0) {
                    for (int i = 0; i < permissions.length; i++)
                        perms.put(permissions[i], grantResults[i]);
                    // Check for both permissions

                    if (perms.get(this.permissions[0]) == PackageManager.PERMISSION_GRANTED
                            && perms.get(this.permissions[1]) == PackageManager.PERMISSION_GRANTED
                            ) {
                        Log.d(TAG, "Phone state and storage permissions granted");
                        // process the normal flow
                        //else any one or both the permissions are not granted
                        //TODO Do your stuff here after permissions granted
                    } else {
                        Log.d(TAG, "Some permissions are not granted ask again ");
                        //permissions is denied (this is the first time, when "never ask again" is not checked) so ask again explaining the usage of permissions
//                      //shouldShowRequestPermissionRationale will return true
                        //show the dialog or snackbar saying its necessary and try again otherwise proceed with setup.
                        if (ActivityCompat.shouldShowRequestPermissionRationale(this, this.permissions[0]) ||
                                ActivityCompat.shouldShowRequestPermissionRationale(this, this.permissions[1])) {
                            showDialogOK("Phone state and storage permissions required for this app",
                                    new DialogInterface.OnClickListener() {
                                        @Override
                                        public void onClick(DialogInterface dialog, int which) {
                                            switch (which) {
                                                case DialogInterface.BUTTON_POSITIVE:
                                                    checkAndRequestPermissions();
                                                    break;
                                                case DialogInterface.BUTTON_NEGATIVE:
                                                    // proceed with logic by disabling the related features or quit the app.
                                                    break;
                                            }
                                        }
                                    });
                        }
                        //permissions is denied (and never ask again is  checked)
                        //shouldShowRequestPermissionRationale will return false
                        else {
                            Toast.makeText(this, "Go to settings and enable permissions", Toast.LENGTH_LONG)
                                    .show();
                            //proceed with logic by disabling the related features or quit the app.
                        }
                    }
                }
            }
        }

    }

    private void showDialogOK(String message, DialogInterface.OnClickListener okListener) {
        new AlertDialog.Builder(this)
                .setMessage(message)
                .setPositiveButton("OK", okListener)
                .setNegativeButton("Cancel", okListener)
                .create()
                .show();
    }
}

Service Class:
public class MyDownloadService extends Service implements DownloadManagerListener {
    private static final String LOG_TAG = "tag";
   public static DownloadManagerPro downloadManagerPro;
    File myDirectory;
    int taskToken;
    String name;
    Intent notificationIntent;
    Notification notification;
    PendingIntent pendingIntent;
    private IBinder binder = new LocalBinder();


    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return binder;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        if (intent.getAction().equals(DownloadActions.ACTION.Download_ACTION)) {
            Log.d(LOG_TAG, "Received Start Foreground Intent");
        }
        name = intent.getStringExtra("filename");
        final String url = intent.getStringExtra("url");
        Log.d(LOG_TAG, name);
        Log.d(LOG_TAG, url);
        downloadManagerPro = new DownloadManagerPro(this.getApplicationContext());
        downloadManagerPro.init("RITSDownloads2/", 16, this);
        myDirectory = new File(Environment.getExternalStorageDirectory() + "/" + "RITSDownloads2");
        if (!myDirectory.exists()) {
            myDirectory.mkdir();
        }
        taskToken = downloadManagerPro.addTask(name, url, 16, true, true);
        Log.d(LOG_TAG, String.valueOf(taskToken));
        try {
            downloadManagerPro.startDownload(taskToken);
            notificationIntent = new Intent(this, MainActivity.class);
            notificationIntent.setAction(DownloadActions.ACTION.Download_ACTION);
            pendingIntent = PendingIntent.getActivity(this, 0,
                    notificationIntent, 0);


            notification = new NotificationCompat.Builder(this)
                    .setContentTitle("Downloading")
                    .setTicker("Rits Download")
                    .setContentText(name)
                    .setSmallIcon(android.R.drawable.stat_sys_download)
                    .setContentIntent(pendingIntent)
                    .setOngoing(true)
                    .build();
            startForeground(DownloadActions.NOTIFICATION_ID.FOREGROUND_SERVICE,
                    notification);
            // stopForeground(true);
            // stopSelf();


        } catch (IOException e) {
            e.printStackTrace();
        }
        return START_STICKY;


    }

    @Override
    public void OnDownloadStarted(long taskId) {
        Log.d(LOG_TAG, "DownloadStarted");

    }

    @Override
    public void OnDownloadPaused(long taskId) {

    }

    @Override
    public void onDownloadProcess(long taskId, double percent, long downloadedLength) {

        final int progress = (int) percent;
        final int taskToken = (int) taskId;
//        int position = positions.get(taskToken);



        notification = new NotificationCompat.Builder(this)
                .setContentTitle("Downloading")
                .setTicker("Rits Download")
                .setContentText(name)
                .setSmallIcon(android.R.drawable.stat_sys_download)
                .setContentIntent(pendingIntent)
                .setOngoing(true)
                .setColor(ContextCompat.getColor(this, R.color.colorPrimary))
                .setProgress(100, progress, false)
                .build();
        startForeground(DownloadActions.NOTIFICATION_ID.FOREGROUND_SERVICE,
                notification);
        Intent intent = new Intent(this, MainActivity.class);
        intent.putExtra("progress", progress);
        intent.setAction("download");
        intent.putExtra("tasktoken",taskToken);

        ReportStructure structure = downloadManagerPro.singleDownloadStatus(taskToken);
        String name =structure.name;
        intent.putExtra("name",name);

        LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);
    }

    @Override
    public void OnDownloadFinished(long taskId) {

    }

    @Override
    public void OnDownloadRebuildStart(long taskId) {

    }

    @Override
    public void OnDownloadRebuildFinished(long taskId) {

    }

    public void pauseDownload(int taskToken){
        ReportStructure reportStructure = downloadManagerPro.singleDownloadStatus(taskToken);
        if(reportStructure.state == TaskStates.DOWNLOADING){
            downloadManagerPro.pauseDownload(taskToken);
        } else if(reportStructure.state == TaskStates.PAUSED){
            try {
                downloadManagerPro.startDownload(taskToken);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void OnDownloadCompleted(long taskId) {
        Log.d(LOG_TAG, "Download Complete");
             /*   MainActivity.instance.pausebtn.post(new Runnable() {
                    @Override
                    public void run() {
                        MainActivity.instance.pausebtn.setImageDrawable(getResources().getDrawable(R.drawable.ic_action_done));
                    }
                });*/
        notification = new NotificationCompat.Builder(this)
                .setContentTitle("Download Complete")
                .setTicker("Rits Download")
                .setContentText(name)
                .setSmallIcon(R.drawable.ic_action_done)
                .setContentIntent(pendingIntent)
                .setOngoing(true)
                .setColor(ContextCompat.getColor(this, R.color.colorPrimary))
                .build();
        startForeground(DownloadActions.NOTIFICATION_ID.FOREGROUND_SERVICE,
                notification);



    }

    @Override
    public void connectionLost(long taskId) {

    }

    @Override
    public void onTaskRemoved(Intent rootIntent) {
       /* Intent restartService = new Intent(getApplicationContext(),this.getClass());
        restartService.setPackage(getPackageName());
        PendingIntent restartPendingIntent =PendingIntent.getService(getApplicationContext(), 1,restartService, PendingIntent.FLAG_ONE_SHOT);
        AlarmManager myAlarmService = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
        myAlarmService.set(
                AlarmManager.ELAPSED_REALTIME,
                SystemClock.elapsedRealtime() + 1000,
                restartPendingIntent);*/
    }

    public class LocalBinder extends Binder{

        public MyDownloadService getService(){
            return MyDownloadService.this;
        }
    }
}

I don't know how you want to save the state but I do know that an activity has a onStop() method that you can override. The onStop() method runs when the app is killed so I would imagine you would want to do your "saving" in this method.

As for saving something I believe you would want to use the SharedPreferences class. You can find more information about that here .

You can find the lifecycle of an activity here

hope this helps

Save the progress on SharedPreferences onDestroy() and retrieve it from there when activity is created.

Cache:

@Override
protected void onDestroy() {
    super.onDestroy();
    SharedPreferences sharedPreferences = getSharedPreferences("space_name", MODE_PRIVATE);
    SharedPreferences.Editor editor = sharedPreferences.edit();
    editor.putInt("progress", progress).apply();
}

And retrieve:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    SharedPreferences sharedPreferences = getSharedPreferences("space_name", MODE_PRIVATE);
    progress = sharedPreferences.getInt("progress", 0); // 0 default value in case is empty
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM