当用户返回到activty

时间:2016-05-10 08:00:12

标签: android service upload

我目前正在开发一个将文件上传到我的服务器的应用。我的应用程序旨在启动,使用直到任务完成,最后通过按下按钮启动文件上传,应用程序已被使用。所以这是一种非常线性的方法:开始,使用到最后,文件上传,完成。

现在我想将文件发送到我的服务器,如果由于某种原因决定不使用它直到最后。所以当调用onStop()时。

经过一些研究后,我决定选择一个使用startService()在onStop()中调用的未绑定服务。在该服务中,执行while循环直到上传成功(serverResponseCode == 200)并在每次尝试失败后休眠。

当用户再次开始使用已停止的应用程序时,因此调用onResume()我想取消文件传输,因为用户将在最后通过单击其他活动中的上传按钮来上传文件。 因此,当我尝试在onResume()中停止服务时,我收到服务停止的Toast,但我在logcat中看到它仍然在运行:尝试连接到服务器并休眠。

到目前为止我尝试过:

1)尝试了对答案的建议:

automatically start up a service when the application is closed

stop service in android

2)即使onStartCommand返回START_NOT_STICKY,也会发生。

这是我的代码:

服务代码:

import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Process;
import android.support.annotation.Nullable;
import android.util.Log;
import android.widget.Toast;

import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

public class UploadService extends Service {
    private Looper mServiceLooper;
    private ServiceHandler mServiceHandler;
    private static final String TAG = "UploadService";

    int serverResponseCode = 0;

    String upLoadServerUri = null;
    String uploadFilePath;
    String uploadFileName;

    // Handler that receives messages from the thread
    private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {

           //... have some Server connection parameters here

            while (serverResponseCode != 200) {

                // ... trying to upload a file to my server

                if (serverResponseCode != 200) {
                    try {
                        Log.d(TAG, "Thread slepps");
                        Thread.sleep(10000);

                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }

            stopSelf(msg.arg1);
        }
    }


    private class DisplayToast implements Runnable {
        String mText;

        public DisplayToast(String text) {
            mText = text;
        }

        public void run() {
            Toast.makeText(UploadService.this, mText, Toast.LENGTH_SHORT).show();
        }
    }


    @Override
    public void onCreate() {
        // Start up the thread running the service.  Note that we create a
        // separate thread because the service normally runs in the process's
        // main thread, which we don't want to block.  We also make it
        // background priority so CPU-intensive work will not disrupt our UI.
        HandlerThread thread = new HandlerThread("ServiceStartArguments", Process.THREAD_PRIORITY_BACKGROUND);
        thread.start();

        // Get the HandlerThread's Looper and use it for our Handler
        mServiceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }


    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
        // For each start request, send a message to start a job and deliver the
        // start ID so we know which request we're stopping when we finish the job
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        mServiceHandler.sendMessage(msg);

        // If we get killed, after returning from here, restart
        return START_STICKY;
    }


    @Override
    public void onDestroy() {
        Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();

    }

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

}

调用启动和停止服务的活动:

import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.LayerDrawable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.PopupMenu;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import android.widget.RatingBar;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.SearchView;
import android.widget.SearchView.OnQueryTextListener;
import java.text.SimpleDateFormat;
import java.util.Date;

public class AppSelectionActivity extends AppCompatActivity implements View.OnClickListener, OnQueryTextListener {

    private final static String TAG = "AppSelectionActivity";
    private boolean leftOnIntent = false;  // is set to true when starting one of my other activity with an intent, so that service will not be started
    private Intent serviceIntent;

    @Override
    protected void onStop() {
        Log.d(TAG,"onStop: app is stopped");
        if (!leftOnIntent) {
            serviceIntent = new Intent(AppSelectionActivity.this, UploadService.class);
            startService(serviceIntent);
            Log.d(TAG, "onStop: Intent is started");
        }
        super.onStop();
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.d(TAG,"onResume: app is resumed");
        stopService(new Intent(AppSelectionActivity.this, UploadService.class));
        leftOnIntent = false;
    }

    @Override
    protected void onDestroy() {
        Log.d(TAG,"onDestroy: got called");
        super.onDestroy();
    }
}

有关如何正确停止服务和文件上传的任何建议吗?

1 个答案:

答案 0 :(得分:0)

您的Handler需要一些标记,您可以将其设置为停止上传循环(while (serverResponseCode != 200))。所以让我们介绍一下

public boolean keepRunning;

按如下方式修改循环:

keepRunning = true;
while (serverResponseCode != 200 && keepRunning)
{
      // ... trying to upload a file to my server
      if (serverResponseCode != 200) {
          try {
              Log.d(TAG, "Thread slepps");
              Thread.sleep(10000);

          } catch (InterruptedException e) {
              e.printStackTrace();
          }
      }
}

如果您想停止Service,现在可以通过startService()行动致电Intent来实现这一目标......

Intent intent = new Intent(this, UploadService.class);
intent.setAction("your.package.name.STOP_UPLOAD");
startService(intent);

...然后您在onStartCommand()评估。

String intentAction = (intent != null) ? intent.getAction() : "";
if ( "your.package.name.STOP_UPLOAD".equals(intentAction) )
{
    mServiceHandler.keepRunning = false;
    stopSelf();
}
else
{
    Message msg = mServiceHandler.obtainMessage();
    msg.arg1 = startId;
    mServiceHandler.sendMessage(msg);
}
return START_STICKY;

如果代码中的某些其他方法被执行,这里涉及的一些方法由运行时调用:

  • Service.onStartCommand()startService()
  • 触发
  • Handler.handleMessage()sendMessage();
  • 触发

在您的情况下,调用handleMessage()后,运行时会调用mServiceHandler.sendMessage(msg);。这将启动上传,当用户返回Activity时触发可能仍然很忙,因此触发onResume()。因此,在此方法中,您调用startService()以中止上传。

这会触发onStartCommand()。评估Intent操作后,boolean将设置为false。 Handler可能仍在执行while循环。如果是这种情况,循环将立即停止,因为条件不再成立。