简体   繁体   English

应用被杀死后,如何保存进度条的状态?

[英]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. 我正在使用来自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. 我不知道您要如何保存状态,但我知道活动具有可以覆盖的onStop()方法。 The onStop() method runs when the app is killed so I would imagine you would want to do your "saving" in this method. 当应用被杀死时, onStop()方法将运行,因此我想您会希望在此方法中进行“保存”。

As for saving something I believe you would want to use the SharedPreferences class. 至于保存某些内容,我相信您将要使用SharedPreferences类。 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. 将进度保存在SharedPreferences onDestroy()上,并在创建活动时从那里检索进度。

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
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Flutter 应用恢复; 当活动被系统杀死时如何保存应用程序状态? - Flutter app restoration; how to save the app state when the activity is killed by the system? 即使应用程序被杀死,如何保存数据 - How to save data even when the app is killed 当应用程序进程被杀死时,如何停止android恢复状态? - How to stop android from restoring state when the app process is killed? 应用程序进程被杀死时如何保存演示者实例 - How to save presenter instance when app process is being killed 在Android上的libgdx中,如果应用程序被杀,如何保存游戏状态? - In libgdx on Android, how do I save game state in case app is killed? 何时保存应用状态 - When to save the state of an app 启动时如何保存应用定向状态 - How to save app orientation State when launched 当应用程序处于后台和终止状态时如何移动不同活动的通知导航 - How to move notification navigation for different activity when app is background and killed state 当 android 应用程序处于终止状态时,如何从推送通知(使用 FCM)中获取“数据有效负载”? - How can I get “data payload” from push notification (using FCM) when android app is in killed state? 终止应用程序后,如何在Viewpager中保存片段的状态 - How to save the state of the fragments in Viewpager after the application is killed
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM