Java OutOfMemory Exception无法在Lollipop之前的设备上启动应用程序

时间:2015-11-03 13:33:54

标签: java android

当我尝试在Nexus 5(Android 6 M)上启动我的应用程序时,一切正常,但是当我尝试从Galaxy S4(4.4)或其他Kitkat设备或模拟器启动它时,我的应用程序显示白屏,然后崩溃或立即崩溃。

Android监视器:

11-03 14:28:48.536 12397-12397/com.iotech.discover E/AndroidRuntime: FATAL EXCEPTION: main
11-03 14:28:48.536 12397-12397/com.iotech.discover E/AndroidRuntime: Process: com.iotech.discover, PID: 12397
11-03 14:28:48.536 12397-12397/com.iotech.discover E/AndroidRuntime: java.lang.OutOfMemoryError
11-03 14:28:48.536 12397-12397/com.iotech.discover E/AndroidRuntime:     at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
11-03 14:28:48.536 12397-12397/com.iotech.discover E/AndroidRuntime:     at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:677)
11-03 14:28:48.536 12397-12397/com.iotech.discover E/AndroidRuntime:     at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:507)
11-03 14:28:48.536 12397-12397/com.iotech.discover E/AndroidRuntime:     at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:872)
11-03 14:28:48.536 12397-12397/com.iotech.discover E/AndroidRuntime:     at android.content.res.Resources.loadDrawable(Resources.java:3024)
11-03 14:28:48.536 12397-12397/com.iotech.discover E/AndroidRuntime:     at android.content.res.Resources.getDrawable(Resources.java:1586)
11-03 14:28:48.536 12397-12397/com.iotech.discover E/AndroidRuntime:     at android.view.Window.setBackgroundDrawableResource(Window.java:1035)
11-03 14:28:48.536 12397-12397/com.iotech.discover E/AndroidRuntime:     at com.iotech.discover.LoginActivity.onCreate(LoginActivity.java:50)
11-03 14:28:48.536 12397-12397/com.iotech.discover E/AndroidRuntime:     at android.app.Activity.performCreate(Activity.java:5426)
11-03 14:28:48.536 12397-12397/com.iotech.discover E/AndroidRuntime:     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
11-03 14:28:48.536 12397-12397/com.iotech.discover E/AndroidRuntime:     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2269)
11-03 14:28:48.536 12397-12397/com.iotech.discover E/AndroidRuntime:     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2363)
11-03 14:28:48.536 12397-12397/com.iotech.discover E/AndroidRuntime:     at android.app.ActivityThread.access$900(ActivityThread.java:161)
11-03 14:28:48.536 12397-12397/com.iotech.discover E/AndroidRuntime:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1265)
11-03 14:28:48.536 12397-12397/com.iotech.discover E/AndroidRuntime:     at android.os.Handler.dispatchMessage(Handler.java:102)
11-03 14:28:48.536 12397-12397/com.iotech.discover E/AndroidRuntime:     at android.os.Looper.loop(Looper.java:157)
11-03 14:28:48.536 12397-12397/com.iotech.discover E/AndroidRuntime:     at android.app.ActivityThread.main(ActivityThread.java:5356)
11-03 14:28:48.536 12397-12397/com.iotech.discover E/AndroidRuntime:     at java.lang.reflect.Method.invokeNative(Native Method)
11-03 14:28:48.536 12397-12397/com.iotech.discover E/AndroidRuntime:     at java.lang.reflect.Method.invoke(Method.java:515)
11-03 14:28:48.536 12397-12397/com.iotech.discover E/AndroidRuntime:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
11-03 14:28:48.536 12397-12397/com.iotech.discover E/AndroidRuntime:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
11-03 14:28:48.536 12397-12397/com.iotech.discover E/AndroidRuntime:     at dalvik.system.NativeStart.main(Native Method)

我认为这来自于我对位图背景的使用,但由于我有4个不同的错误,我不知道它来自哪里,而且之前有效。

编辑:我的drawables在drawable文件夹中,这是我的主要活动:

public class LoginActivity extends AppCompatActivity {
    private static final String TAG = "LoginActivity";
    private static final int REQUEST_SIGNUP = 0;

    @InjectView(R.id.input_email)
    EditText _emailText;
    @InjectView(R.id.input_password)
    EditText _passwordText;
    @InjectView(R.id.btn_login)
    Button _loginButton;
    @InjectView(R.id.link_signup)
    TextView _signupLink;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
        getWindow().setBackgroundDrawableResource(R.drawable.mlogin_paris_aerian);
        ButterKnife.inject(this);

        if (!isInternetConnected()) {
            alertDialogNoInternet();
        }

        _loginButton.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                login();
            }
        });

        _signupLink.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                // Start the Signup activity
                Intent intent = new Intent(getApplicationContext(), SignupActivity.class);
                startActivityForResult(intent, REQUEST_SIGNUP);
            }
        });
    }

    public void login() {
        Log.d(TAG, "Login");

        if (!validate()/* || !isConnected()*/) {
            onLoginFailed();
            return;
        }

        _loginButton.setEnabled(false);

        final ProgressDialog progressDialog = new ProgressDialog(LoginActivity.this,
                R.style.AppTheme_Dark_Dialog);
        progressDialog.setIndeterminate(true);
        progressDialog.setMessage(getString(R.string.login_authentication));
        progressDialog.show();

        String email = _emailText.getText().toString();
        String password = _passwordText.getText().toString();

        // TODO : onLoginSuccess si auth ok côté serveur
        Context context = getApplicationContext();
        loginAPI(context, email, password);

    public boolean isInternetConnected(){
        ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Activity.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
        if (networkInfo != null && networkInfo.isConnected())
            return true;
        else
            return false;
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == REQUEST_SIGNUP) {
            if (resultCode == RESULT_OK) {

                // TODO: Implement successful signup logic here
                // By default we just finish the Activity and log them in automatically
                this.finish();
            }
        }
    }

    @Override
    public void onBackPressed() {
        // Disable going back to the MainActivity
        moveTaskToBack(true);
    }

    public void onLoginSuccess() {
        _loginButton.setEnabled(true);
        finish();
    }

    public void onLoginFailed() {
        Toast.makeText(getBaseContext(), R.string.login_failed, Toast.LENGTH_LONG).show();

        _loginButton.setEnabled(true);
    }

    public boolean validate() {
        boolean valid = true;

        String email = _emailText.getText().toString();
        String password = _passwordText.getText().toString();
        onLoginSuccess();
        return valid;
    }

    public void alertDialogNoInternet (){
        AlertDialog.Builder builder1 = new AlertDialog.Builder(this);
        builder1.setTitle(getString(R.string.nointernet_title));
        builder1.setMessage(getString(R.string.nointernet_message));
        builder1.setCancelable(true);
        builder1.setPositiveButton(getString(R.string.ok),
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        Toast.makeText(getApplicationContext(),
                                "Merci", Toast.LENGTH_SHORT)
                                .show();
                        //dialog.cancel();
                    }
                });
        builder1.setNegativeButton(getString(R.string.cancel),
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        dialog.cancel();
                    }
                });

        AlertDialog alert11 = builder1.create();
        alert11.show();
    }

    public static void loginAPI (Context context, final String mail, final String password) {
        JSONObject obj = new JSONObject();
        try {
            obj.put("email", mail);
            obj.put("password", password);
        } catch (JSONException e) {
            e.printStackTrace();
        }

        RequestQueue queue = Volley.newRequestQueue(context);
        JsonObjectRequest jsObjRequest = new JsonObjectRequest(Request.Method.POST, "http://46.101.218.111/api/v1/auth",obj,
                new Response.Listener<JSONObject>() {
                    @Override
                    public void onResponse(JSONObject response) {
                        System.out.println(response);
                        //hideProgressDialog();
                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        //hideProgressDialog();
                        System.out.println(error);
                    }
                });
        queue.add(jsObjRequest);
    }
}

2 个答案:

答案 0 :(得分:2)

将导致崩溃的drawable放入drawable-xxhdpi或drawable-xhdpi(选择更适合您图像的文件夹)。

可能你的图像已经是高分辨率了,但因为它被放置在可绘制的图像中,所以它被视为mdpi图像,并且操作系统会对其进行缩放。

请记住,KB中图像的大小不是内存消耗的主要因素。

答案 1 :(得分:0)

基于您对其他答案的评论 - 大位图不是唯一的问题。 800x1264大小的位图占用800 * 1254 * 4字节〜略小于4MB - 它不应该只是它的sigle实例的问题。 要确保 - 只需注释掉这一行:getWindow().setBackgroundDrawableResource(R.drawable.mlogin_paris_aerian);

您可能需要熟悉hproof查看器: https://developer.android.com/tools/debugging/debugging-memory.html