首页 > 解决方案 > APK 发布问题,一些属性检测为空

问题描述

现在,我使用 android studio 和原生 java 制作的应用程序已经完成。我会将其更改为 APK 以上传到 Play 商店。

如果 SharedPreference 中不存在 jwt,则应用程序以启动画面开始,然后将其定向到登录页面。

下面是作为闪屏 UI 的 MainActivity.java。

public class MainActivity extends AppCompatActivity {
    int loadingTime = 2000;
    final Context context = this;

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

        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {


                File folder = new File(Environment.getExternalStorageDirectory() +
                        File.separator + "Client Warehouse Dzil");
                boolean success = true;

                if (!folder.exists()) {
                    success = folder.mkdirs();
                }

                SharedPreferences preferences = getSharedPreferences("session",Context.MODE_PRIVATE);
                final String token = preferences.getString("token", null);

                if (token != null) { // check, if jwt is Exist take to home
                    Intent home = new Intent(MainActivity.this, HomeActivity.class);
                    startActivity(home);
                } else { // other, display login page
                    Intent login = new Intent(getApplicationContext(), LoginActivity.class);
                    startActivity(login);
                }


                finish();
            }
        }, loadingTime);

    }
}

问题是当我从此应用程序生成 APK 时。debug版本没有问题,但是release版本有问题。即使是我将上传到 Play 商店的这个版本。这是登录活动

package com.tsurumaru.dzil.clientwarehouse.activity.login;

import com.tsurumaru.dzil.clientwarehouse.R;
import com.tsurumaru.dzil.clientwarehouse.activity.home.HomeActivity;
import com.tsurumaru.dzil.clientwarehouse.model.LoginRestModel;
import com.tsurumaru.dzil.clientwarehouse.remote.LoginRestService;
import com.tsurumaru.dzil.clientwarehouse.remote.RestApiUtils;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

/**
 * A login screen that offers login via email/password.
 */
public class LoginActivity extends AppCompatActivity {
    EditText edtUsername;
    EditText edtPassword;
    Button btnLogin;
    ProgressBar progressBar;
    LoginRestService loginRestService;


    @Override
    protected void onStart() {
        super.onStart();
        if (Build.VERSION.SDK_INT >= 23) {
            requestPermissions(new String[]{
                    Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE
            }, 2);
        }
    }

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

        edtUsername = findViewById(R.id.edtUsername);
        edtPassword = findViewById(R.id.edtPassword);
        btnLogin = findViewById(R.id.btnLogin);
        progressBar = findViewById(R.id.progressBar);

        loginRestService = RestApiUtils.getLoginRestService();

        btnLogin.setOnClickListener(view -> {
            String username = edtUsername.getText().toString();
            String password = edtPassword.getText().toString();

            //validate the form
            if (validateLogin(username, password)) {
                doLogin(username, password);
                progressBar.setVisibility(View.VISIBLE);
            }
        });
    }

    private boolean validateLogin(String username, String password) {
        if (username == null || username.trim().length() == 0) {
            Toast.makeText(this, "Username is required", Toast.LENGTH_SHORT).show();
            return false;
        }

        if (password == null || password.trim().length() == 0) {
            Toast.makeText(this, "Password is required", Toast.LENGTH_SHORT).show();
            return false;
        }

        return true;
    }

    private void doLogin(String username, String password) {
        Call<LoginRestModel> call = loginRestService.auth(username, password);
        call.enqueue(new Callback<LoginRestModel>() {
            @Override
            public void onResponse(Call<LoginRestModel> call, Response<LoginRestModel> response) {

                if (response.isSuccessful()) {
                    LoginRestModel resObj = response.body();
                    if (resObj.getStatus().equals("success")) {

                        /* Save to sharedPreferences*/
                        saveSession(resObj.getId(), resObj.getUsername(), resObj.getToken());

                        // Redirect to Home Page
                        Intent intent = new Intent(LoginActivity.this, HomeActivity.class);
                        startActivity(intent);

                    } else {

                        Toast.makeText(LoginActivity.this, "The username and password is incorrect", Toast.LENGTH_SHORT).show();
                    }
                } else {

                    Toast.makeText(LoginActivity.this, "Error, please try again", Toast.LENGTH_SHORT).show();
                }
                progressBar.setVisibility(View.INVISIBLE);
            }

            @Override
            public void onFailure(Call<LoginRestModel> call, Throwable t) {
                Toast.makeText(LoginActivity.this, t.getMessage(), Toast.LENGTH_SHORT).show();
                call.cancel();

            }
        });
    }

    public void saveSession(int id, String username, String token) {
        SharedPreferences sharedPreferences = getSharedPreferences("session", Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sharedPreferences.edit();
        editor.putInt("id", id);
        editor.putString("username", username);
        editor.putString("token", token);
        editor.apply();
    }
}

在 APK 调试中,上述 Retrofit 调用中的 doLogin 函数成功运行。在 APK Release 中,应用突然关闭并重新启动。我在 Logcat 中看到:

Process: com.tsurumaru.dzil.clientwarehouse, PID: 31649
    java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.String.equals(java.lang.Object)' on a null object reference
        at c.h.a.a.a.c.b.a(:4)
        at g.i.run()
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:160)
        at android.app.ActivityThread.main(ActivityThread.java:5541)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:964)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:759)
06-17 19:15:45.444 960-1190/? E/InputDispatcher: channel 
        '248fd78b com.tsurumaru.dzil.clientwarehouse/com.tsurumaru.dzil.clientwarehouse.activity.login.LoginActivity (server)'
        ~ Channel is unrecoverably broken and will be disposed!

在 chaaacba 中说 null ???这是什么,任何帮助它如此感激。

标签: javaandroid

解决方案


发布模式会缩小和缩小您的项目。因此,您必须实施proguard或设置缩小和缩小false

buildTypes {
        release {
            minifyEnabled false
            shrinkResources false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

而且 at c.h.a.a.a.c.b.a它被混淆了。由于proguard弱,它是不必要的混淆。


推荐阅读