Android Bundle java.lang.NoClassDefFoundError
Posted
技术标签:
【中文标题】Android Bundle java.lang.NoClassDefFoundError【英文标题】: 【发布时间】:2021-12-10 11:49:43 【问题描述】:使用 android Studio 在我的个人设备和模拟器上测试我的应用可以正常工作。当我将应用程序作为捆绑包加载到 Google Play 商店(并且人们安装它)时,查询 SQLite 数据库的类返回一个空值。我没有错误需要处理,因为本地一切正常。
我更新了 Android Studio 和 Gradle,但错误仍然存在。生成捆绑包时没有给出错误。我得到的最接近的是 java.lang.NoClassDefFoundError 但如果这是我必须处理的错误,我不是 100%。
据我所知,问题在于捆绑(因为它在我测试运行时有效)。有人可以提出前进的道路吗?
Android Studio 2021.1.1 测试版 1 毕业诉 7 Windows 10 x64
谢谢
MainActivity 类:
import androidx.appcompat.app.AppCompatActivity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;import android.view.Window;
// Webview related
import android.content.res.Configuration;
import android.text.TextUtils;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
public class MainActivity extends AppCompatActivity
public BrevjarWebInterface myJSInterface;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE); //will hide the title
getSupportActionBar().hide(); // hide the title bar
setContentView(R.layout.activity_main);
// Initialise JS Interface
myJSInterface = new BrevjarWebInterface(this);
// WebView Object
WebView.setWebContentsDebuggingEnabled(true);
WebView browser = (WebView)findViewById(R.id.brevjarView);
WebSettings settings = browser.getSettings();
settings.setBuiltInZoomControls(true);
settings.setDisplayZoomControls(false);
settings.setjavascriptEnabled(true);
//Todo: resolve deprecated methods; https://android.googlesource.com/platform/frameworks/support/+/androidx-master-dev/webkit/integration-tests/testapp/src/main/java/com/example/androidx/webkit/AssetLoaderAjaxActivity.java
settings.setAllowFileAccessFromFileURLs(true);
settings.setAllowFileAccess(true);
settings.setAllowUniversalAccessFromFileURLs(true);
settings.setLoadsImagesAutomatically(true);
settings.setDomStorageEnabled(true);
settings.setAllowContentAccess(true);
settings.setJavaScriptCanOpenWindowsAutomatically(true);
//Inject WebAppInterface methods into Web page by having Interface 'Android' and load
browser.addJavascriptInterface(myJSInterface, "Android");
browser.setWebViewClient(new WebViewClient());
if (savedInstanceState != null)
browser.restoreState(savedInstanceState);
else
browser.loadUrl("file:///android_asset/index.html");
// browser.evaluateJavascript("setAndroid();", null);
/* The following three override functions: onConfigurationChanged, onSaveInstanceState onRestoreInstance
* are used to keep the integrity of the UI when screen is rotated.
*/
@Override
public void onConfigurationChanged (Configuration newConfig)
super.onConfigurationChanged(newConfig);
@Override
public void onSaveInstanceState (Bundle outState)
super.onSaveInstanceState(outState);
WebView browser = (WebView)findViewById(R.id.brevjarView);
browser.saveState(outState);
public void setMyJSInterface(BrevjarWebInterface myInterface)
myJSInterface = myInterface;
@Override
public void onBackPressed()
Context c = this.getBaseContext();
c.setTheme(R.style.Theme_IlBrevjar);
DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener()
@Override
public void onClick(DialogInterface dialog, int which)
switch (which)
case DialogInterface.BUTTON_POSITIVE:
//Yes button clicked
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(1);
break;
case DialogInterface.BUTTON_NEGATIVE:
dialog.dismiss();
break;
;
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Exit the App?");
builder.setPositiveButton("Yes", dialogClickListener);
builder.setNegativeButton("No", dialogClickListener);
builder.show();
这是 DBHelper 类:
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
public class SQLiteDBHelper extends SQLiteOpenHelper
private SQLiteDBHelper mInstance = null;
private static final int DATABASE_VERSION = 3;
private static final String DATABASE_NAME = "ordo_2021_10.sqlite";
private static final String DB_PATH_SUFFIX = "/databases/";
static Context ctx;
private SQLiteDatabase db;
/** This avoids direct instantiation and forces the creation of an object to be done
through the getInstance method. The getInstance method prevents multiple instances
to be created and thus avoids data leak
*/
public SQLiteDBHelper(Context context)
super(context, DATABASE_NAME, null, DATABASE_VERSION);
ctx = context;
public OrdoDay getOrdoDay(String date)
OrdoDay contList = new OrdoDay(); // only one value will be returned
try
db = this.getReadableDatabase();
Cursor cursor = db.rawQuery("select ld_date, lt_title, ld_litWeek, years.lt_id\n" +
"from years\n" +
"LEFT JOIN liturgicalTimes on years.lt_id = liturgicalTimes.lt_id\n" +
"where ld_date = \"" + date + "\"", null);
if (cursor != null)
while (cursor.moveToNext())
// Return Data: date (String),litTime (String), litWeek (int)
contList = new OrdoDay(cursor.getString(0), cursor.getString(1), cursor.getInt(2),cursor.getInt(3));
cursor.close();
db.close();
catch (SQLiteException e)
System.out.println(e.getMessage());
return contList;
public ArrayList <FeastDay> getFeastDay(String date, int dioc_id, int inst_id, int loc_id, int ch_id, int fullList)
String month = date.substring(5,7);
String dom = date.substring(8,10);
String dt = date;
ArrayList<FeastDay> feastList = new ArrayList<>();
try
db = this.getReadableDatabase();
Cursor cursor = db.rawQuery("SELECT *\n" +
"FROM (\n" +
"SELECT f.feast_title, f.feast_subtitle, institute.inst_code, institute.inst_title, diocese.dioc_title, locality.loc_title, church.ch_title, f.proprju_id, f.desc_short, f.desc_long, grade.grd_rank, grade.grd_title, colour.col_title, kp.kmn_code, kp.kmn_title, kp.para1, kp.para2, kp.para3, kp.para4, ld.lt_title, ld.ld_litWeek, diocese.dioc_id, institute.inst_id, locality.loc_id, church.ch_id, f.feast_id, fk.kmn_cnt FROM (\n" +
"SELECT * FROM main\n" +
"WHERE day=" + dom + " AND month=" + month + "\n" +
") m\n" +
"LEFT JOIN institute on m.inst_id = institute.inst_id\n" +
"LEFT JOIN diocese on m.dioc_id = diocese.dioc_id\n" +
"LEFT JOIN locality on m.loc_id = locality.loc_id\n" +
"LEFT JOIN church on m.ch_id = church.ch_id\n" +
"LEFT JOIN (\n" +
"SELECT * FROM feast\n" +
"LEFT JOIN proprju ON feast.proprju_id=proprju.proprju_id\n" +
") f on m.feast_id=f.feast_id\n" +
"LEFT JOIN grade on f.grd_id = grade.grd_id\n" +
"LEFT JOIN colour on f.col_id = colour.col_id\n" +
"LEFT JOIN (\n" +
"SELECT * FROM komunPars\n" +
"LEFT JOIN komun ON komunPars.kmn_id=komun.kmn_id\n" +
"LEFT JOIN (SELECT p_id, p_title as para1 FROM parameters) p1 ON komunPars.p1_id=p1.p_id\n" +
"LEFT JOIN (SELECT p_id, p_title as para2 FROM parameters) p2 ON komunPars.p2_id=p2.p_id\n" +
"LEFT JOIN (SELECT p_id, p_title as para3 FROM parameters) p3 ON komunPars.p3_id=p3.p_id\n" +
"LEFT JOIN (SELECT p_id, p_title as para4 FROM parameters) p4 ON komunPars.p4_id=p4.p_id\n" +
") kp ON f.kmnpar_id = kp.kmnpar_id\n" +
"LEFT JOIN (SELECT feast_id, count(1) kmn_cnt FROM feast_komun GROUP BY feast_komun.feast_id) fk on f.feast_id = fk.feast_id\n" +
"LEFT JOIN (\n" +
"SELECT * FROM years\n" +
"LEFT JOIN liturgicalTimes on years.lt_id = liturgicalTimes.lt_id\n" +
"WHERE ld_date = '" + dt + "'\n" +
") ld ON 1\n" +
"UNION ALL\n" +
"SELECT f.feast_title, f.feast_subtitle, institute.inst_code, institute.inst_title, diocese.dioc_title, locality.loc_title, church.ch_title, f.proprju_id, f.desc_short, f.desc_long, grade.grd_rank, grade.grd_title, colour.col_title, kp.kmn_code, kp.kmn_title, kp.para1, kp.para2, kp.para3, kp.para4, ld.lt_title, ld.ld_litWeek, diocese.dioc_id, institute.inst_id, locality.loc_id, church.ch_id, f.feast_id, fk.kmn_cnt FROM overrides\n" +
"LEFT JOIN (\n" +
"SELECT * FROM feast\n" +
"LEFT JOIN proprju ON feast.proprju_id=proprju.proprju_id\n" +
") f on overrides.feast_id=f.feast_id\n" +
"LEFT JOIN diocese on overrides.dioc_id = diocese.dioc_id\n" +
"LEFT JOIN institute on 0 = diocese.dioc_id\n" +
"LEFT JOIN locality on 0 = locality.loc_id\n" +
"LEFT JOIN church on 0 = church.ch_id\n" +
"LEFT JOIN grade on f.grd_id = grade.grd_id\n" +
"LEFT JOIN colour on f.col_id = colour.col_id\n" +
"LEFT JOIN (\n" +
"SELECT * FROM komunPars\n" +
"LEFT JOIN komun ON komunPars.kmn_id=komun.kmn_id\n" +
"LEFT JOIN (SELECT p_id, p_title as para1 FROM parameters) p1 ON komunPars.p1_id=p1.p_id\n" +
"LEFT JOIN (SELECT p_id, p_title as para2 FROM parameters) p2 ON komunPars.p2_id=p2.p_id\n" +
"LEFT JOIN (SELECT p_id, p_title as para3 FROM parameters) p3 ON komunPars.p3_id=p3.p_id\n" +
"LEFT JOIN (SELECT p_id, p_title as para4 FROM parameters) p4 ON komunPars.p4_id=p4.p_id\n" +
") kp ON f.kmnpar_id = kp.kmnpar_id\n" +
"LEFT JOIN (SELECT feast_id, count(1) kmn_cnt FROM feast_komun GROUP BY feast_komun.feast_id) fk on f.feast_id = fk.feast_id\n" +
"LEFT JOIN (\n" +
"SELECT * FROM years\n" +
"LEFT JOIN liturgicalTimes on years.lt_id = liturgicalTimes.lt_id\n" +
"WHERE ld_date = '" + dt + "'\n" +
") ld ON 1\n" +
"WHERE ovr_date = '" + dt + "'\n" +
")\n" +
"ORDER BY grd_rank DESC, case when dioc_id is NULL then 4 end, dioc_id ASC", null);
if (cursor != null)
// fList.array();
int doubleProprju = -1;
while (cursor.moveToNext())
if (fullList == 0)
// int tmpN = 0;
// tmpN = cursor.getInt(21);
// String tmp = DatabaseUtils.dumpCursorToString(cursor);
if ( ((dioc_id == 1) && (cursor.getInt(21) == 2)) || ((dioc_id == 1) && (cursor.getInt(21) == 3)) ||
((dioc_id == 3) && (cursor.getInt(21) == 2)) || ((dioc_id == 2) && (cursor.getInt(21) == 3))
)
// if feast diocese <> user diocese
continue; // omit one iteration
// tmpN = cursor.getInt(7);
if (doubleProprju == cursor.getInt(7))
// if feast has already been added (with a higher grade due to SQL sorting) do not add again
continue;
if (inst_id > 0)
// if feast institute doesn't match user institute and feast institute is not empty
// tmpN = cursor.getInt(22);
if ( (inst_id != cursor.getInt(22)) && (cursor.getInt(22) > 0))
// if feast institute does not match user institute omit, but if institute field of feast is empty keep
continue;
if (inst_id == cursor.getInt(22))
// if feast has multiple entries, choose the matching institute entry
doubleProprju = cursor.getInt(7);
else if (cursor.getInt(22) > 0)
// omit feasts of institutes if user does not have an institute
continue;
// tmpN = cursor.getInt(23);
if (loc_id > 0)
if ((cursor.getInt(23) != loc_id) && (cursor.getInt(23) > 0))
// if user locality does not match feast locality
continue;
else if (cursor.getInt(23) > 0)
// if user did not select a locality, omit feasts of localities
continue;
// tmpN = cursor.getInt(24);
if (ch_id > 0)
if ((cursor.getInt(24) != ch_id) && (cursor.getInt(24) > 0))
// if user church does not match feast church
continue;
else if (cursor.getInt(24) > 0)
// if user did not select a church, omit feasts of church
continue;
FeastDay dList = new FeastDay(cursor.getString(0), cursor.getString(1),
cursor.getString(2), cursor.getString(3), cursor.getString(4), cursor.getString(5),
cursor.getString(6),cursor.getInt(7), cursor.getString(8), cursor.getString(9),
cursor.getInt(10), cursor.getString(11), cursor.getString(12), cursor.getString(13),
cursor.getString(14), cursor.getString(15), cursor.getString(16), cursor.getString(17),
cursor.getString(18), cursor.getString(19), cursor.getInt(20),cursor.getInt(21),
cursor.getInt(22),cursor.getInt(23),cursor.getInt(24),cursor.getInt(25),
cursor.getInt(26));
feastList.add(dList);
cursor.close();
db.close();
catch (SQLiteException e)
System.out.println(e.getMessage());
return feastList;
public String getFeastOverride(OrdoDay ordoDay, String date)
String overrideList = new String();
Calendar c = Calendar.getInstance();
try
Date date1 = new SimpleDateFormat("yyyy-MM-dd").parse(date);
c.setTime(date1);
catch (java.text.ParseException e)
System.out.println(e.getMessage());
int dow = c.get(Calendar.DAY_OF_WEEK);
try
db = this.getReadableDatabase();
Cursor cursor = db.rawQuery("SELECT title FROM feast_override\n" +
"WHERE lt_id = " + ordoDay.lt_id + " AND week = " + ordoDay.ld_litWeek + " AND dow= " + dow,null);
if (cursor != null)
while (cursor.moveToNext())
overrideList = cursor.getString(0);
cursor.close();
db.close();
catch (SQLiteException e)
System.out.println(e.getMessage());
return overrideList;
public ArrayList<AltKomun> getAltKomun(int feast_id, AltKomun original)
ArrayList<AltKomun> kmnList = new ArrayList<>();
kmnList.add(original);
try
db = this.getReadableDatabase();
Cursor cursor = db.rawQuery("SELECT kp.kmn_code, kp.kmn_title, kp.para1, kp.para2, kp.para3, kp.para4 FROM (\n" +
"SELECT * FROM feast_komun\n" +
"WHERE feast_id=" + feast_id + "\n" +
") fk\n" +
"LEFT JOIN (\n" +
"SELECT * FROM komunPars\n" +
"LEFT JOIN komun ON komunPars.kmn_id=komun.kmn_id\n" +
"LEFT JOIN (SELECT p_id, p_title as para1 FROM parameters) p1 ON komunPars.p1_id=p1.p_id\n" +
"LEFT JOIN (SELECT p_id, p_title as para2 FROM parameters) p2 ON komunPars.p2_id=p2.p_id\n" +
"LEFT JOIN (SELECT p_id, p_title as para3 FROM parameters) p3 ON komunPars.p3_id=p3.p_id\n" +
"LEFT JOIN (SELECT p_id, p_title as para4 FROM parameters) p4 ON komunPars.p4_id=p4.p_id\n" +
") kp ON fk.kmnpar_id = kp.kmnpar_id",null);
if (cursor != null)
while (cursor.moveToNext())
AltKomun dList = new AltKomun(cursor.getString(0), cursor.getString(1),
cursor.getString(2), cursor.getString(3), cursor.getString(4),
cursor.getString(5));
kmnList.add(dList);
cursor.close();
db.close();
catch (SQLiteException e)
System.out.println(e.getMessage());
return kmnList;
public void CopyDataBaseFromAsset() throws IOException
InputStream myInput = ctx.getAssets().open(DATABASE_NAME);
// Path to the just created empty db
String outFileName = getDatabasePath();
// if the path doesn't exist first, create it
File f = new File(ctx.getApplicationInfo().dataDir + DB_PATH_SUFFIX);
if (!f.exists())
f.mkdir();
// Open the empty db as the output stream
OutputStream myOutput = new FileOutputStream(outFileName);
// transfer bytes from the inputfile to the outputfile
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer)) > 0)
myOutput.write(buffer, 0, length);
// Close the streams
myOutput.flush();
myOutput.close();
myInput.close();
private static String getDatabasePath()
return ctx.getApplicationInfo().dataDir + DB_PATH_SUFFIX
+ DATABASE_NAME;
public SQLiteDatabase openDataBase() throws SQLException
File dbFile = ctx.getDatabasePath(DATABASE_NAME);
if (!dbFile.exists())
try
CopyDataBaseFromAsset();
System.out.println("Copying sucess from Assets folder");
catch (IOException e)
throw new RuntimeException("Error creating source database", e);
return SQLiteDatabase.openDatabase(dbFile.getPath(), null, SQLiteDatabase.NO_LOCALIZED_COLLATORS | SQLiteDatabase.CREATE_IF_NECESSARY);
@Override
public void onCreate(SQLiteDatabase db)
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
@Override
public synchronized void close ()
if (db != null)
db.close();
super.close();
【问题讨论】:
我做的一件事是我已经开始使用 TortoiseSVN 来版本这个 Android Studio 项目。它会影响构建吗? 【参考方案1】:错误是由设置为 true 的 minifyEnabled 引起的。将其设置为 false 就可以了。看一下这个: minifyEnabled causing app to crash on release mode
【讨论】:
以上是关于Android Bundle java.lang.NoClassDefFoundError的主要内容,如果未能解决你的问题,请参考以下文章
bundle.getparcelable java.lang.classnotfoundexception怎么解决
Android异常篇 java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
Android -- java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack tra
java.lang.ClassCastException:在尝试通过Instagram共享打印屏幕时,无法将byte []强制转换为android.os.Parcelable错误
Metro server (run ‘react-native start‘) or that your bundle ‘index.android.bundle‘ is packaged corre
Metro server (run ‘react-native start‘) or that your bundle ‘index.android.bundle‘ is packaged corre