应用程序被杀死时如何保存进度条的状态?

时间:2018-03-12 07:12:51

标签: android service android-progressbar

我正在使用暂停/恢复按钮构建一个简单的下载器应用程序。当我再次打开应用程序后,当我单击暂停按钮并终止应用程序时,下载进度不再显示。即使应用程序被杀,我也想保存下载进度状态。谁能帮我这个?我正在使用github上的download manager pro库构建应用程序。 这是代码: 活动类:

    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;
        }
    }
}

2 个答案:

答案 0 :(得分:0)

我不知道你想如何保存状态,但我知道一个活动有一个onStop()方法可以覆盖。 当应用程序被杀死时onStop()方法运行,所以我想你会想要在这种方法中“保存”。

至于保存的东西,我相信你会想要使用SharedPreferences类。您可以找到有关here的更多信息。

您可以找到活动的生命周期here

希望这会有所帮助

答案 1 :(得分:0)

在SharedPreferences onDestroy()上保存进度,并在创建活动时从那里检索它。

高速缓存:

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

并检索:

@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
}