I have been searching for a solution to my problem. The most common recommendations are to add android:hardwareAccelerated="false" and android:largeHeap="true" to the application tag in the manifest, however I still get the following error:
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)
So here are my activities that might have part in this, unfortunately I am lost and don't know what to adjust to resolve this problem.
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;
}
}
I would really appreciate any help with this!
getDatamethod which is storing each bitmap in memory and app crashes because of out of memoryImageItemclass object instead useURIof image path and then load this image in adapter using any image loader library such asPicasso