Android Studio:E / UncaughtException:java.lang.OutOfMemoryError

时间:2017-07-12 12:15:14

标签: java android

我一直在寻找解决问题的方法。最常见的建议是将android:hardwareAccelerated =“false”和android:largeHeap =“true”添加到清单中的应用程序标记,但是我仍然会收到以下错误:

E/UncaughtException: java.lang.OutOfMemoryError: Failed to allocate a 56272 byte allocation with 19848 free bytes and 19KB until OOM
    at java.lang.StringBuilder.toString(StringBuilder.java:408)
    at org.chromium.content_public.browser.LoadUrlParams.buildDataUri(LoadUrlParams.java:113)
    at org.chromium.content_public.browser.LoadUrlParams.createLoadDataParamsWithBaseUrl(LoadUrlParams.java:164)
    at org.chromium.android_webview.AwContents.loadDataWithBaseURL(AwContents.java:1523)
    at com.android.webview.chromium.WebViewChromium.loadDataWithBaseURL(WebViewChromium.java:609)
    at android.webkit.WebView.loadDataWithBaseURL(WebView.java:1015)
    at com.google.android.gms.internal.zzakn.loadDataWithBaseURL(Unknown Source)
    at com.google.android.gms.internal.zzakm.loadDataWithBaseURL(Unknown Source)
    at com.google.android.gms.internal.zzxy.zzgo(Unknown Source)
    at com.google.android.gms.internal.zzxq.zzgp(Unknown Source)
    at com.google.android.gms.internal.zzxw.zza(Unknown Source)
    at com.google.android.gms.ads.internal.zzl.run(Unknown Source)
    at android.os.Handler.handleCallback(Handler.java:751)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:154)
    at android.app.ActivityThread.main(ActivityThread.java:6119)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
                                                                             
                                                                             
                                                                             --------- beginning of crash
E/AndroidRuntime: FATAL EXCEPTION: main
     java.lang.OutOfMemoryError: Failed to allocate a 56272 byte allocation with 19848 free bytes and 19KB until OOM
     at java.lang.StringBuilder.toString(StringBuilder.java:408)
     at org.chromium.content_public.browser.LoadUrlParams.buildDataUri(LoadUrlParams.java:113)
     at org.chromium.content_public.browser.LoadUrlParams.createLoadDataParamsWithBaseUrl(LoadUrlParams.java:164)
     at org.chromium.android_webview.AwContents.loadDataWithBaseURL(AwContents.java:1523)
     at com.android.webview.chromium.WebViewChromium.loadDataWithBaseURL(WebViewChromium.java:609)
     at android.webkit.WebView.loadDataWithBaseURL(WebView.java:1015)
     at com.google.android.gms.internal.zzakn.loadDataWithBaseURL(Unknown Source)
     at com.google.android.gms.internal.zzakm.loadDataWithBaseURL(Unknown Source)
     at com.google.android.gms.internal.zzxy.zzgo(Unknown Source)
     at com.google.android.gms.internal.zzxq.zzgp(Unknown Source)
     at com.google.android.gms.internal.zzxw.zza(Unknown Source)
     at com.google.android.gms.ads.internal.zzl.run(Unknown Source)
     at android.os.Handler.handleCallback(Handler.java:751)
     at android.os.Handler.dispatchMessage(Handler.java:95)
     at android.os.Looper.loop(Looper.java:154)
     at android.app.ActivityThread.main(ActivityThread.java:6119)
     at java.lang.reflect.Method.invoke(Native Method)
     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)

所以我的活动可能参与其中,不幸的是我迷失了,不知道要解决什么来解决这个问题。

Gridviewadapter

import java.util.ArrayList;

import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class GridViewAdapter extends ArrayAdapter<ImageItem> {

    private Context context;
    private int layoutResourceId;
    private ArrayList<ImageItem> data = new ArrayList<ImageItem>();

    public GridViewAdapter(Context context, int layoutResourceId, ArrayList<ImageItem> data) {
        super(context, layoutResourceId, data);
        this.layoutResourceId = layoutResourceId;
        this.context = context;
        this.data = data;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View row = convertView;
        ViewHolder holder;

        if (row == null) {
            LayoutInflater inflater = ((Activity) context).getLayoutInflater();
            row = inflater.inflate(layoutResourceId, parent, false);
            holder = new ViewHolder();
            holder.imageTitle = (TextView) row.findViewById(R.id.text);
            holder.image = (ImageView) row.findViewById(R.id.image);
            row.setTag(holder);
        } else {
            holder = (ViewHolder) row.getTag();
        }


        ImageItem item = data.get(position);
        holder.imageTitle.setText(item.getTitle());
        holder.image.setImageBitmap(item.getImage());
        return row;
    }

    static class ViewHolder {
        TextView imageTitle;
        ImageView image;
    }
}

的ImageItem

import android.graphics.Bitmap;

public class ImageItem {

    private int arrayIndex;
    private Bitmap image;
    private String title;

    public ImageItem(int arrayIndex, Bitmap image, String title) {
        super();
        this.arrayIndex = arrayIndex;
        this.image = image;
        this.title = title;
    }

    public Bitmap getImage() {
        return image;
    }

    public void setImage(Bitmap image) {
        this.image = image;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public int getArrayIndex() {
        return arrayIndex;
    }

    public void setArrayIndex(int arrayIndex) {
        this.arrayIndex = arrayIndex;
    }
}

Mainactivity

import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.GridView;

import java.util.ArrayList;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.AdView;
import com.google.firebase.iid.FirebaseInstanceId;

public class MainActivity extends ActionBarActivity {

    private GridView gridView;
    private GridViewAdapter gridAdapter;
    private Toolbar toolbar;

    private static final String TAG = MainActivity.class.getSimpleName();
    private static final int STORAGE_PERMISSION_REQUEST = 2001;

    AdRequest adRequest;
    AdView mAdView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //loading ads
        loadAds();

        toolbar = (Toolbar) findViewById(R.id.app_bar);
        setSupportActionBar(toolbar);
        getSupportActionBar().setDisplayShowHomeEnabled(true);
        getSupportActionBar().setLogo(R.drawable.home_icon);
        getSupportActionBar().setDisplayUseLogoEnabled(true);

        gridView = (GridView) findViewById(R.id.gridView);
        gridAdapter = new GridViewAdapter(this, R.layout.grid_item_layout, getData());
        gridView.setAdapter(gridAdapter);

        isStoragePermissionGranted();


        gridView.setOnItemClickListener(new OnItemClickListener() {
            public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
                ImageItem item = (ImageItem) parent.getItemAtPosition(position);

                //Create intent
                Intent intent = new Intent(MainActivity.this, DetailsActivity.class);
                intent.putExtra("title", item.getTitle());
                intent.putExtra("index", item.getArrayIndex());

                //Start details activity
                startActivity(intent);
            }
        });
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.menu_main, menu);
        return true;
    }

    public boolean onOptionsItemSelected(MenuItem item) {

        int id = item.getItemId();

        if (id==R.id.navigate) {
            startActivity(new Intent(this, SettingsActivity.class));
        }
        return super.onOptionsItemSelected(item);
    }

    private void loadAds() {
        mAdView = (AdView) findViewById(R.id.adView);
        adRequest = new AdRequest.Builder().build();
        mAdView.loadAd(adRequest);
    }

    public boolean isStoragePermissionGranted() {
        if (Build.VERSION.SDK_INT >= 23) {
            if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
                    == PackageManager.PERMISSION_GRANTED) {
                Log.v(TAG, "Permission is granted");
                return true;
            } else {
                Log.v(TAG, "Permission is revoked");
                ActivityCompat.requestPermissions(
                        this,
                        new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                        1);
                return false;
            }
        } else { //permission is automatically granted on sdk<23 upon installation
            Log.v(TAG, "Permission is granted");
            return true;
        }
    }

    @Override
    public void onRequestPermissionsResult(
            int requestCode,
            String[] permissions,
            int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == STORAGE_PERMISSION_REQUEST) {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                Log.d(TAG, "Permission: " + permissions[0] + "was " + grantResults[0]);
                // resume tasks needing this permission
            } else {
                // TODO: You should not allow the user to continue!
            }
        }
    }

    /**
     * Prepare some dummy data for gridview
     */
    private ArrayList<ImageItem> getData() {
        final ArrayList<ImageItem> imageItems = new ArrayList<>();
        TypedArray imgs = getResources().obtainTypedArray(R.array.image_ids);
        for (int i = 0; i < imgs.length(); i++) {
            Log.d(TAG, "Image ID: " + String.valueOf(i));
            Bitmap bitmap = BitmapFactory.decodeResource(getResources(), imgs.getResourceId(i, -1));
            imageItems.add(new ImageItem(i, bitmap, "Image#" + i));
        }
        return imageItems;
    }
}

Detailsactivity

import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.StringTokenizer;

import com.google.android.gms.ads.AdListener;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.AdView;
import com.google.android.gms.ads.InterstitialAd;

public class DetailsActivity extends ActionBarActivity {

    Button btnShare;
    private InterstitialAd interstitialAd;
    boolean exitApp=false;
    private Toolbar toolbar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.details_activity);

        toolbar = (Toolbar) findViewById(R.id.app_bar);
        TextView titleTextView = (TextView) findViewById(R.id.title);
        setSupportActionBar(toolbar);
        getSupportActionBar().setDisplayShowHomeEnabled(true);
        getSupportActionBar().setLogo(R.drawable.home_icon);
        getSupportActionBar().setDisplayUseLogoEnabled(true);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);

        String title = getIntent().getStringExtra("title");
        int index = getIntent().getIntExtra("index", -1);

        // Worked on by Douglas

        if(title!=null){
            titleTextView.setText(title);
        }else{
            titleTextView.setText("No title");
        }

        Bitmap bitmap = getBitmap(0);
        try{
            bitmap = getBitmap(index);
        }catch (Exception e){
            Log.d("getBitmap Broke: ", e.toString());
        }

        // Till here


        ImageView imageView = (ImageView) findViewById(R.id.image);
        imageView.setImageBitmap(bitmap);

        String imgBitmapPath= MediaStore.Images.Media.insertImage(getContentResolver(), bitmap, title ,null);
        final Uri imgBitmapUri=Uri.parse(imgBitmapPath);

        btnShare=(Button)findViewById(R.id.button);
        btnShare.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                // Get the URI
                // Replace R.drawable.image with the name of the image you want to display
                //Uri uri = Uri.parse("android.resource://" + BuildConfig.APPLICATION_ID + "/" + R.drawable.image_1);

                // Now that you have the URI you can create your intent
                Intent share = new Intent(Intent.ACTION_SEND);
                share.putExtra(Intent.EXTRA_STREAM, imgBitmapUri);
                share.setType("image/*");
                share.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

                // Create a chooser to share your emoji
                try {
                    DetailsActivity.this.startActivity(Intent.createChooser(share, "Share Emoji"));
                } catch (ActivityNotFoundException e) {
                    // Whatsapp might not be installed
                }

            }
        });

        launchInter();
        loadInterstitial();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onSupportNavigateUp() {
        onBackPressed();
        return true;
    }

    public boolean onOptionsItemSelected(MenuItem item) {

        int id = item.getItemId();

        if (id==R.id.navigate) {
            startActivity(new Intent(this, SettingsActivity.class));
        }
        return super.onOptionsItemSelected(item);
    }

    /**
     * Prepare some dummy data for gridview
     */
    private Bitmap getBitmap(int index) {
        final ArrayList<ImageItem> imageItems = new ArrayList<>();
        TypedArray imgs = getResources().obtainTypedArray(R.array.image_ids);
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), imgs.getResourceId(index, -1));
        return bitmap;
    }

    private void launchInter() {
        interstitialAd = new InterstitialAd(this);
        interstitialAd.setAdUnitId("ca-app-pub-7350914179187171/1372559648");

        interstitialAd.setAdListener(new AdListener() {
            @Override
            public void onAdLoaded() {
                showAdInter();
            }

            @Override
            public void onAdFailedToLoad(int errorCode) {
                String message=String.format("onAdFailedToLoad (%s)",getErrorReason(errorCode));
            }

            @Override
            public void onAdClosed() {
                if (exitApp)
                    finish();
            }
        });
    }

    private void showAdInter() {
        if (interstitialAd.isLoaded()) {
            interstitialAd.show();
        }
        else
        {
            Log.d("","Interstitial ad was not ready to be shown");
        }
    }

    public void loadInterstitial() {
        AdRequest adRequest = new AdRequest.Builder()
                .addTestDevice(AdRequest.DEVICE_ID_EMULATOR)
                .addTestDevice("Insert_your_hashed_device_id_here")
                .build();

        interstitialAd.loadAd(adRequest);
    }

    private String getErrorReason(int errorCode) {
        String errorReason="";
        switch(errorCode) {
            case AdRequest.ERROR_CODE_INTERNAL_ERROR:
                errorReason="Internal Error";
                break;
            case AdRequest.ERROR_CODE_INVALID_REQUEST:
                errorReason="Invalid Request";
                break;
            case AdRequest.ERROR_CODE_NETWORK_ERROR:
                errorReason="Network Error";
                break;
            case AdRequest.ERROR_CODE_NO_FILL:
                errorReason="No Fill";
                break;
        }
        return errorReason;
    }
}

我真的很感激任何帮助!

1 个答案:

答案 0 :(得分:1)

我的建议是修改您的代码,以便从Bitmap类中删除ImageItem个实例,如下所示

public class ImageItem {

    private int arrayIndex;
    private int imageResource;
    private String title;

    public ImageItem(int arrayIndex, int imageResource, String title) {
        super();
        this.arrayIndex = arrayIndex;
        this.imageResource = imageResource;
        this.title = title;
    }

    public int getImageResource() {
        return imageResource;
    }

    public void setImageResource(int imageResource) {
        this.imageResource = imageResource;
    }

    // rest methods should be same

}

GridViewAdapter类中加载来自资源ID的图像,如下所示

public class GridViewAdapter extends ArrayAdapter<ImageItem> {

    // your old logic here

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        // your old logic here

        // holder.image.setImageBitmap(item.getImage());
        Picasso.with(context).load(item.getImageResource()).into(holder.image);
    }

    // your old logic here

}

修改getData

MainActivity.java方法
private ArrayList<ImageItem> getData() {
    final ArrayList<ImageItem> imageItems = new ArrayList<>();
    TypedArray imgs = getResources().obtainTypedArray(R.array.image_ids);
    for (int i = 0; i < imgs.length(); i++) {
        Log.d(TAG, "Image ID: " + String.valueOf(i));
        // no need to load image here
        // Bitmap bitmap = BitmapFactory.decodeResource(getResources(), imgs.getResourceId(i, -1));
        imageItems.add(new ImageItem(i, imgs.getResourceId(i, -1), "Image#" + i));
    }
    return imageItems;
}

最后一个在app build.gradle中添加编译依赖项,如下所示

dependencies {
    ...
    compile 'com.squareup.picasso:picasso:2.5.0'
    ...
}

并完成。