- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我目前在应用商店中有一款应用可用,但有一种错误报告我似乎无法完全弄清楚。我的应用程序使用内部 sqlite 数据库,但在某些设备上(当然不是大多数)有时会出现以下错误:
android.database.sqlite.SQLiteException: no such table: image_data (code 1): , while compiling: SELECT Min(stamp) FROM image_data WHERE category = 'Astronomy' AND stamp >= 1357426800 and coalesce(title_nl, '') = ''
我确信这个表存在并且我确信这个查询是正确的。我知道这个错误只发生在应用程序的小部件和 AlarmManager 触发的 BroadcastReceiver 中(应用程序偶尔会尝试下载新条目,因为它是当天应用程序的图片)。
我觉得和我访问数据库时所处的Context有关系。我有一个名为 AppContextHelper 的类,它扩展了 Application 并有一个静态成员,我在其中存储上下文。访问数据库时始终使用该上下文。
我的问题:在某些情况下,当获取小部件中的数据库或上述由 AlarmManager 触发的 BroadcastReceiver 时,上下文是否无效,在这种情况下,我应该使用提供的上下文来支持“应用程序”语境?如果是这样,为什么该上下文无效或更好,提供的是哪个上下文?
提前致谢!
根据要求,导致问题的代码再次仅在某些设备上,并且仅在小部件或 AlarmManager 类中。我将在 AlarmManager 类中发布导致错误的代码(即行数最少的代码)
初始化闹钟的代码:
Intent myIntent = new Intent(AppContextHelper.getContext(), ApodDownloader.class);
mPendingIntent = PendingIntent.getBroadcast(AppContextHelper.getContext(), 0, myIntent, 0);
AlarmManager alarmManager = (AlarmManager)AppContextHelper.getContext().getSystemService(Context.ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis() + 10000, AlarmManager.INTERVAL_HOUR, mPendingIntent);
AppContextHelper.java
public class AppContextHelper extends Application {
private static Context mContext;
@Override
public void onCreate() {
super.onCreate();
mContext = this;
}
public static Context getContext(){
return mContext;
}
}
(部分)ApodDownloader.java(这包含抛出异常的行)
@Override
public void onReceive(Context arg0, Intent arg1) {
(new AsyncTaskThreadPool<Integer, Void, Boolean>() {
@Override
protected Boolean doInBackground(Integer... params) {
Helpers.logMessage("Checking new entries.");
SQLiteDatabase db = FrescoDatabase.acquireReadableDatabase(AppContextHelper.getContext());
try {
>>> THIS LINE THROWS THE EXCEPTION <<<
maxStamp = Helpers.executeScalarLong(db, "SELECT Min(stamp) FROM image_data WHERE category = 'Astronomy' AND stamp >= 1357426800 and coalesce(title_nl, '') = ''");
[...]
} finally {
FrescoDatabase.releaseReadableDatabase();
}
[...] more code
}
[...] onPostExecute
}).executeOnExecutor(AsyncTaskThreadPool.THREAD_POOL_EXECUTOR, 0);
FrescoDatabase.java数据库由应用程序在启动时自动生成,此代码正在运行,也在触发异常的设备上运行。我怎么强调数据库都存在于有问题的设备上,因为除了 AlarmManager 的小部件和 BroadcastReceiver 之外,应用程序运行完美,所以请不要告诉我数据库未正确初始化:)
public class FrescoDatabase extends SQLiteOpenHelper {
public static final String[] OBSOLETE_DATABASE_FILE_NAMES = new String[] { "Fresco.v1.sqlite", "Fresco.v2.sqlite", "Fresco.v3.sqlite", "Fresco.v4.sqlite", "Fresco.v5.sqlite" };
public static final String DATABASE_FILE_NAME = "Fresco.v6.sqlite";
public static final int DATABASE_FILE_SIZE = 15302656;
private static final int DATABASE_VERSION = 7;
private static final Lock writeLock = new ReentrantLock();
private static SQLiteDatabase currentDB = null;
public static final SQLiteDatabase acquireWritableDatabase(Context c) {
writeLock.lock();
currentDB = new FrescoDatabase(c).getWritableDatabase();
return currentDB;
}
public static final void releaseWritableDatabase() {
currentDB.close();
currentDB = null;
writeLock.unlock();
}
public static final SQLiteDatabase acquireReadableDatabase(Context c) {
writeLock.lock();
currentDB = new FrescoDatabase(c).getReadableDatabase();
return currentDB;
}
public static final void releaseReadableDatabase() {
currentDB.close();
currentDB = null;
writeLock.unlock();
}
private FrescoDatabase(Context context) {
super(context, InitializeFrescoDatabaseTask.getDatabaseFileName(context), null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
// database is automatically generated, this should not be called
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
(部分)Helpers.java
public class Helpers {
[...]
public static long executeScalarLong(SQLiteDatabase db, String query) {
return executeScalarLong(db, query, new String[] { });
}
public static long executeScalarLong(SQLiteDatabase db, String query, String... parameters) {
(line 85, see stack trace down below) Cursor cursor = db.rawQuery(query, parameters);
try {
cursor.moveToNext();
long val = cursor.getLong(0);
return val;
}
catch (Exception e) {
;
}
finally {
cursor.close();
}
return -1;
}
}
异常日志(按要求):
java.lang.RuntimeException: An error occured while executing doInBackground()
at nl.tagpulse.utils.AsyncTaskThreadPool$3.done(AsyncTaskThreadPool.java:329)
at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
at java.util.concurrent.FutureTask.run(FutureTask.java:137)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
at java.lang.Thread.run(Thread.java:856)
Caused by: android.database.sqlite.SQLiteException: no such table: image_data (code 1): , while compiling: SELECT Min(stamp) FROM image_data WHERE category = 'Astronomy' AND stamp >= 1357426800 and coalesce(title_nl, '') = ''
at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:1012)
at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:623)
at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588)
at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:58)
at android.database.sqlite.SQLiteQuery.<init>(SQLiteQuery.java:37)
at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:44)
at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1314)
at android.database.sqlite.SQLiteDatabase.rawQuery(SQLiteDatabase.java:1253)
at nl.tagpulse.fresco.other.Helpers.executeScalarLong(Helpers.java:85)
at nl.tagpulse.fresco.other.Helpers.executeScalarLong(Helpers.java:82)
at nl.tagpulse.fresco.business.FrescoDatabase.retrieveNewEntries(FrescoDatabase.java:64)
at nl.tagpulse.fresco.business.ApodDownloader$1.doInBackground(ApodDownloader.java:192)
at nl.tagpulse.fresco.business.ApodDownloader$1.doInBackground(ApodDownloader.java:1)
at nl.tagpulse.utils.AsyncTaskThreadPool$2.call(AsyncTaskThreadPool.java:317)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
... 4 more
我在 Helpers.java block 中添加了第 85 行标记。
希望这对您有所帮助!
最佳答案
这是发生了什么:
ApodDownloader 是一个 BroadcastReceiver,在它的 onReceive() 中你启动了某种不允许的 AsyncTask。文档指出:
A BroadcastReceiver object is only valid for the duration of the call to onReceive(Context, Intent). Once your code returns from this function, the system considers the object to be finished and no longer active.
This has important repercussions to what you can do in an onReceive(Context, Intent) implementation: anything that requires asynchronous operation is not available, because you will need to return from the function to handle the asynchronous operation, but at that point the BroadcastReceiver is no longer active and thus the system is free to kill its process before the asynchronous operation completes.
http://developer.android.com/reference/android/content/BroadcastReceiver.html#ReceiverLifecycle
当进程被终止时,应用程序上下文不再可用。您仍然可以访问 AppContextHelper.getContext() 但这将是一个新加载的类,因为旧的类在消除进程时被杀死。换句话说,返回的上下文将为空。只有在极少数情况下才会发生这种情况,即 Android 确实终止了一个进程,这在我的经验中并不常见。
如果您的 AppContextHelper 提供的 Context 尚未初始化,那么您的 InitializeFrescoDatabaseTask.getDatabaseFileName(context) 调用将返回一个空字符串,它自然会打开错误的数据库。因为您在 FrescoDatabase 类的 onCreate() 中未执行任何操作,所以数据库未正确初始化并且找不到表。但即使您创建了表,它也可能是错误的数据库,尽管崩溃已经消失,但它不会显示任何数据。
为防止这种情况发生,您需要在运行 onReceive() 的同一个线程中完成所有工作,或者如果这花费的时间太长,则启动服务来完成繁重的工作。
在分析您的代码时我注意到的另一件事是,您在创建警报时使用应用程序上下文来创建 Intent (new Intent(AppContextHelper.getContext(), ApodDownloader.class);)。执行此操作时,您需要设置 FLAG_ACTIVITY_NEW_TASK,否则您可能会收到“android.util.AndroidRuntimeException:从 Activity 上下文外部调用 startActivity() 需要 FLAG_ACTIVITY_NEW_TASK 标志。这真的是您想要的吗?”这可能会使应用程序崩溃,也可能不会。
关于android - 极少数情况下出现 "android.database.sqlite.SQLiteException: no such table"错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15943534/
这个问题在这里已经有了答案: What is the best way to parse html in C#? [closed] (15 个答案) 关闭 3 年前。 string input =
为什么 wrapper #4 没有继承其父表容器的高度?表格嵌套在一个显示 block 包装器中,每个嵌套的div是显示表格,每个表格继承到最里面的一个。是什么原因造成的,我该如何解决? jsfidd
我正在使用带有 Bootstrap 的自定义 css 作为外边框。但顶部边框不可见,除非我将其大小设置为 2 px。 我该如何解决这个问题? HTML #name 1.one 2.two 3.thr
我正在逻辑层面上设计一个数据库,以便稍后将其传递给程序员来交付。我只是粗略地了解它们的工作原理,所以我很难简洁地表达我的问题。这是我的问题: 我有一个名为 MEANINGS 的表。 我有一个名为 WO
在 Laravel 上,我们可以使用 DB::table('table')->get(); 或使用 model::('table')->all() 进行访问;我的问题是它们之间有什么区别? 谢谢。 最
我试图从以下内容中抓取 URL从 WorldOMeter 获取 CoVid 数据,在此页面上存在一个表,id 为:main_table_countries_today其中包含我希望收集的 15x225
这是我的图表数据库:/image/CGAwh.png 我用 SEQUELIZE 制作了我的数据库模型: 型号:级别 module.exports = (sequelize, DataTypes) =>
我真的不明白为什么我的代码不能按预期工作。当我将鼠标悬停在表格的每一行上时,我想显示一个图像(来 self 之前加载的 JSON)。每个图像根据行的不同而不同,我想将它们显示在表格之外的另一个元素中。
假设我的数据库中有一张地铁 map ,其中每条线路的每个站点都是一行。如果我想知道我的线路在哪里互连: mysql> SELECT LineA.stop_id FROM LineA, LineB WH
我最近经常使用这些属性,尤其是 display: table-cell。它在现代浏览器中得到了很好的支持,并且它对某些网格有很多好处,并且可以非常轻松地对齐内容,而无需棘手的标记。但在过去的几天里,我
在 CSS 中,我可以这样做: http://s1.ipicture.ru/uploads/20120612/Uk1Z8iZ1.png http://s1.ipicture.ru/uploads/20
问题作为标题,我正在学习sparkSQL,但我无法很好地理解它们之间的区别。谢谢。 最佳答案 spark.table之间没有区别& spark.read.table功能。 内部 spark.read.
我正在尝试根据 this answer 删除表上的非空约束.但是,它似乎没有在 sqlite_sequence 中创建条目。这样做之后,即使我可以在使用测试表时让它正常工作。 有趣的是,如果我备份我的
var otable = new sap.m.Table();//here table is created //here multiple header I'm trying to create t
下面两种方法有什么区别: 内存 性能 答: select table.id from table B: select a.id from table a 谢谢(抱歉,如果我的问题重复)。 最佳答案 完
我尝试在表格后添加点,方法是使用 table::after 选择器创建一个点元素并使用 margin: 5px auto 5px auto; 将其居中。它有效,但似乎在第一个表格列之后添加了点,而不是
我正在设计一个可以标记任何内容的数据库,我可能希望能够选择带有特定标记的所有内容。 我正在为以下两个选项而苦苦挣扎,希望得到一些建议。如果有更好的方法请告诉我。 选项A 多个“多对多”连接表。 tag
"center" div 中的下表元素导致 "left" div 中的内容从顶部偏移几个像素(在我的浏览器中为 8 ).在表格之前添加一些文本可消除此偏移量。 为什么?如何在不要求在我的表格前添加“虚
我是一名优秀的程序员,十分优秀!