为啥 publishProgress 方法在服务中不起作用?

Posted

技术标签:

【中文标题】为啥 publishProgress 方法在服务中不起作用?【英文标题】:Why Is publishProgress method not working in Service?为什么 publishProgress 方法在服务中不起作用? 【发布时间】:2014-12-08 10:31:04 【问题描述】:

我是 android 开发的菜鸟,我正在尝试在服务中执行 AsyncTask。当我注释掉 publishProgress 方法时,Asynctask 工作正常,但是当我尝试调用 publishProgress 时,我的应用程序在 doInBackground 方法中停止。它不会崩溃,它只是退出,当我使用调试器运行应用程序时,会弹出一条 Eclipse 错误消息,指出“更新进度”遇到错误。相同的代码在 Activity 中对我来说可以正常工作,但在 Service 中却不行。非常感谢任何解决此问题的帮助。

我的代码:

我在哪里实例化进度条

@Override
public void onCreate() 
super.onCreate();

//https://gist.github.com/bjoernQ/6975256 <--Tutorial URL


layout_inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);

WindowManager.LayoutParams params = new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, PixelFormat.TRANSLUCENT);
params.gravity = Gravity.LEFT | Gravity.CENTER_VERTICAL;
params.x = 0;
params.y = 0;
topLeftView = layout_inflater.inflate(R.layout.layout_service, null);
wm.addView(topLeftView, params); 

btn_retry = (Button) topLeftView.findViewById(R.id.btn_retry);
btn_cancel = (Button) topLeftView.findViewById(R.id.btn_cancel);
progress_bar = (VerticalProgressBar) topLeftView.findViewById(R.id.progressbar);
upload_image = (ImageView) topLeftView.findViewById(R.id.imageView1);

btn_retry.setOnTouchListener(this);
btn_retry.setOnClickListener(this);

btn_cancel.setOnTouchListener(this);
btn_cancel.setOnClickListener(this);

progress_bar.setOnTouchListener(this);
upload_image.setOnTouchListener(this);

topLeftView.setOnTouchListener(this); 

  

  class saveMedia extends AsyncTask<Void, Integer, String> 

    // @Override
    protected void onPreExecute() 


        progress_bar.setProgress(0);
        progress_bar.setMax(100);
    

    @Override
    protected String doInBackground(Void... params) 



             HttpURLConnection connection = null;
             DataOutputStream outputStream = null;
             DataInputStream inputStream = null;

             String urlServer = "";
             if(is_club) //For Clubs
                 urlServer = "http://example.com/App/ppfunctions.php?action=upload&club_id=" + club_id + "&club_name=" + club_name + "&user_id=" + user_id + "&user_name=" + user_name + "&club_city=" + club_city + "&comment=" + comments + "&price=" + price + "&line=" + line + "&capacity=" + capacity ;
             else //For Parties
                 urlServer = "http://example.com/App/ppfunctions.php?action=upload_party&club_id=" + party_id + "&club_name=" + party_name + "&user_id=" + user_id + "&user_name=" + user_name + "&comment=" + comments + "&price=" + price + "&line=" + line + "&capacity=" + capacity ;
             
             String lineEnd = "\r\n";
             String twoHyphens = "--";
             String boundary =  "*****";

             int bytesRead, bytesAvailable, bufferSize;
             byte[] buffer;
             int maxBufferSize = 15*1024*1024; 

             try                

                 URL url = new URL(urlServer);
                 connection = (HttpURLConnection) url.openConnection();

                 // Allow Inputs & Outputs
                 connection.setDoInput(true);
                 connection.setDoOutput(true);
                 connection.setUseCaches(false);

                 // Enable POST method
                 connection.setRequestMethod("POST");

                 connection.setRequestProperty("Connection", "Keep-Alive");
                 connection.setRequestProperty("Content-Type", "multipart/form-data;boundary="+boundary);

                 outputStream = new DataOutputStream( connection.getOutputStream() );
                 outputStream.writeBytes(twoHyphens + boundary + lineEnd);
                 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd-HH:mm:ss");
                 Date date = new Date();
                 SharedPreferences preferences = getSharedPreferences("PPPref", MODE_WORLD_READABLE);
                 String filename = "";
                 if(is_photo)
                     filename = String.valueOf(System.currentTimeMillis()) + ".jpg";
                 else
                     filename = String.valueOf(System.currentTimeMillis()) + ".mp4";
                                        
                 outputStream.writeBytes("Content-Disposition: form-data; name=\"uploadedfile\";filename=\"" + filename +"\"" + lineEnd);
                 outputStream.writeBytes(lineEnd);

                 bytesAvailable = fileInputStream.available();
                 bufferSize = Math.min(bytesAvailable, maxBufferSize);
                 buffer = new byte[bufferSize];


                 int sentBytes=0;

                 // Read file
                 bytesRead = fileInputStream.read(buffer, 0, bufferSize);

                 while (bytesRead > 0)
                     outputStream.write(buffer, 0, bufferSize);
                     bytesAvailable = fileInputStream.available();
                     bufferSize = Math.min(bytesAvailable, maxBufferSize);
                     bytesRead = fileInputStream.read(buffer, 0, bufferSize);

                     sentBytes += bufferSize;
                     publishProgress((int)(sentBytes * 100 / bytesAvailable)); //<--Dies here.

                 

                 outputStream.writeBytes(lineEnd);
                 outputStream.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);

                 // Responses from the server (code and message)
                 int serverResponseCode = connection.getResponseCode();
                 String serverResponseMessage = connection.getResponseMessage();

                 StringBuilder response = null;
                 DataInputStream dis = null;
                 String con  = null;
                 try 
                     dis = new DataInputStream(connection.getInputStream());
                     response = new StringBuilder();

                     String line2;
                     con = dis.readLine();
                     while ((line2 = dis.readLine()) != null) 
                         response.append(line2);

                     
                 catch(Exception e)

                 

                 Log.e("s", con );

                 fileInputStream.close();
                 outputStream.flush();
                 outputStream.close();

                 //Kill Service
                 stopSelf();
                 //onDestroy();

             catch (Exception ex)
                 ex.printStackTrace();
              

            return null;


    

    @Override
    protected void onProgressUpdate(Integer... progress) 

        super.onProgressUpdate(progress);
        // Update the ProgressBar
        progress_bar.setProgress(progress[0]);



    

    @Override
    protected void onPostExecute(String result) 
        /*dialog.dismiss();

        Intent intent = new Intent (Share_Media_Activity.this, PhotoVideo_Activity.class);
        startActivity(intent); */
    


【问题讨论】:

所以这个AsyncTask 在你的服务中? 是的,我的异步正在服务中运行。 这个ProgressBar来自哪里? 我是通过Service的onCreate方法中的窗口管理器创建的。它在用户界面中显示为叠加层。 @CommonsWare 请检查我的编辑 【参考方案1】:

我以前遇到过这个问题。在您的 while 循环中检查您的 bytesAvailable = fileInputStream.available();正在返回正在返回零。如果是这样,它可能会导致算术异常。

【讨论】:

以上是关于为啥 publishProgress 方法在服务中不起作用?的主要内容,如果未能解决你的问题,请参考以下文章

方法 publishProgress 必须从工作线程调用,目前推断线程为主线程

在 GZIP 解压过程中设置 ProgressBar maxValue 和 publishProgress 值

在异步任务中发布进度

为啥每次调用 Spring MVC 服务中的简单方法都比静态方法慢?

为啥在我的 Web 服务中调用此方法时出现错误“无法将类型 'void' 隐式转换为 'string'?

为啥即使在 Spring 服务类的第二个方法中传播 = Propagation.REQUIRES_NEW 时事务也会回滚?