Android HttpEntityUtils OutOfMemoryException

Android HttpEntityUtils OutOfMemoryException,android,http,out-of-memory,Android,Http,Out Of Memory,我正在做一个连接到web服务器并接收二进制数据的项目。我的问题是当我从web服务器下载数据时。如果我发送登录请求或激活某些设置,则没有问题。但当我发送下载二进制数据的请求时,它会向我抛出一个OutOfMemoryException。下面是我正在使用的代码: public byte[] activateColl(int index) { createCancelProgressDialog("","Communcating with you...","Cancel");

我正在做一个连接到web服务器并接收二进制数据的项目。我的问题是当我从web服务器下载数据时。如果我发送登录请求或激活某些设置,则没有问题。但当我发送下载二进制数据的请求时,它会向我抛出一个
OutOfMemoryException
。下面是我正在使用的代码:

public byte[] activateColl(int index) {
        createCancelProgressDialog("","Communcating with you...","Cancel");

        byte[] buffer = new byte[1024];
        try {
                httpclient = new DefaultHttpClient();
                httppost = new HttpPost("http://www.rpc.frbr.com");

                TelephonyManager tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
                String deviceId = tm.getDeviceId();
                Log.w("device_identificator","device_identificator : "+deviceId);
                String resolution = Integer.toString(getWindow().getWindowManager().getDefaultDisplay().getWidth())+ "x" +
                                             Integer.toString(getWindow().getWindowManager().getDefaultDisplay().getHeight());
                Log.w("device_resolution","device_resolution : "+resolution);
                String version = "Android " + Build.VERSION.RELEASE;
                Log.w("device_os_type","device_os_type : "+version);
                Log.w("device_identification_string","device_identification_string : "+version);
                String locale = getResources().getConfiguration().locale.toString();
                Log.w("set_locale","set_locale : "+locale);
                String clientApiVersion = null;

                PackageManager pm = this.getPackageManager();
                PackageInfo packageInfo = pm.getPackageInfo(this.getPackageName(), 0);
                clientApiVersion = packageInfo.versionName;
                Log.w("client_api_ver","client_api_ver : "+clientApiVersion);

                hash = getAuthHash();

                TelephonyManager tMgr =(TelephonyManager)this.getSystemService(Context.TELEPHONY_SERVICE);
                phoneNumber = tMgr.getLine1Number();
                Log.i("Phone","Phone Number : "+phoneNumber);

                Log.w("INDEX","INDEXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX : "+Integer.toString(index));

                String timestampSQL = "SELECT dbTimestamp FROM users";
                Cursor cursor = systemDbHelper.executeSQLQuery(timestampSQL);
                if(cursor.getCount()==0){
                    Log.i("Cursor","TimeStamp Cursor Empty!");
                } else if(cursor.getCount()>0){
                    cursor.moveToFirst();
                    timeStamp = cursor.getString(cursor.getColumnIndex("dbTimestamp"));
                }


                postParameters = new ArrayList<NameValuePair>();
                postParameters.add(new BasicNameValuePair("debug_data","1"));
                postParameters.add(new BasicNameValuePair("client_auth_hash", hash));
                postParameters.add(new BasicNameValuePair("timestamp", timeStamp));
                postParameters.add(new BasicNameValuePair("mobile_phone", phoneNumber));
                postParameters.add(new BasicNameValuePair("activate_collections",Integer.toString(index)));
                postParameters.add(new BasicNameValuePair("device_identificator", deviceId));
                postParameters.add(new BasicNameValuePair("device_resolution", resolution));

                httppost.setEntity(new UrlEncodedFormEntity(postParameters));

                HttpResponse response = httpclient.execute(httppost);
                Log.w("Response ","Status line : "+ response.getStatusLine().toString());

                buffer = EntityUtils.toByteArray(response.getEntity());

            } catch (ParseException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (NameNotFoundException e) {
                e.printStackTrace();
            }
                return buffer;
        }
有没有办法解决这个问题?我试图将缓冲区的大小增加到50*1024,但仍然没有帮助

编辑:该行出现错误:

buffer = EntityUtils.toByteArray(response.getEntity());

在Android上,你只有一个有限的堆大小,当你试图解码你的实体时,它会被耗尽。我认为您需要使用http分块将数据发送到客户端(或者出现问题,EntityUtils认为他们需要更大的数组。问题是字节数组太大而不是太小。请看以下文章:

  • 好的,试试这个

    HttpResponse response = httpclient.execute(httppost);         
     // get response entity 
     HttpEntity entity = response.getEntity();          
     // convert entity response to string  
       if (entity != null) 
        {      
         InputStream is = entity.getContent();     
         // convert stream to string    
         result = convertStreamToString(is);      
         result = result.replace("\n", "");     
    
       } 
    
    用于将InputStream转换为字符串

    public String convertStreamToString(InputStream inputStream)
    {
     BufferedReader r = new BufferedReader(new InputStreamReader(inputStream));
     StringBuilder total = new StringBuilder();
     String line;
      while ((line = r.readLine()) != null) {
        total.append(line);
      }
    return total.toString();
    }
    

    使用ApacheCommons库(org.Apache.Commons.io.IOUtils)

    或者直接写入临时文件

      HttpEntity.writeTo(OutputStream);
    
    根据用户Philipp Reichart的建议,从
    org.apache.http.util
    的包中选择Ok

    EntityUtils.toString(); 
    
    是允许使用字符串转换的
    编码格式的方法

    并且让我知道您仍然从内存错误中获得


    谢谢。

    你打算用那个字节数组做什么?服务器发送多少数据?有没有办法直接使用
    HttpEntity.getContent()
    中的
    InputStream
    或将其写入临时文件
    HttpEntity.writeTo(OutputStream)
    然后从那开始工作?它在同一行上引发了一个异常。
    convertStreamToString(is)
    在没有看到其实现的情况下是错误的(它缺少来自服务器的任何类型的编码信息,请使用),如果纯二进制数据已经太大,那么从响应创建字符串当然会失败。@Philipp Reichart-是的,我知道,这就是为什么我在这里写了三个解决方案,让他检查什么是适合他的解决方案。实际上,它在
    convertStreamToString()上给了我一个错误
    。我如何使用它,或者我应该导入一些库,因为它除了创建方法错误之外没有显示任何内容。谢谢帮助!请看我编辑的答案,convertStreamToString是一个方法,我在我的答案中进行了编辑。
    BufferedReader
    IOUtils
    解决方案仍然忽略服务器和服务器发送的编码改为使用平台默认值。这不会可靠地工作。
    HttpEntity.writeTo
    解决方案当然很好,因为它只是二进制的。真正可靠地从
    HttpEntity
    中获取
    字符串的唯一方法是
    EntityUtils.toString()
    或。
      HttpEntity.writeTo(OutputStream);
    
    EntityUtils.toString();