I have implemented SyncAdapter to perform sync of items in application. This adapter is invoked correctly by Android when sync is requested either programmatically or automatically.
When I try to cancel the sync operation manually by deselecting the check box under Accounts and sync setting >{myappccount} > Data and Synchronisation > {app item} , my sync adapters onSyncCanceled is also get called correctly.
But when I my app try to read some internal setting through content provider query , it receives "java.lang.SecurityException: Permission Denial". Although same query works well during normal execution of application or during sync .
Below is stack trace.
java.lang.SecurityException: Permission Denial: reading com.my.applications.sync.content.MySettingProvider uri content://com.my.applications.sync.provider.mysetting/currentstateid from pid=0, uid=1000 requires null
at android.content.ContentProvider$Transport.enforceReadPermission(ContentProvider.java:307)
at android.content.ContentProvider$Transport.query(ContentProvider.java:186)
at android.content.ContentResolver.query(ContentResolver.java:262)
at com.my.applications.sync.service.MysyncService.getCurrentServiceUri(MysyncService.java:442)
at com.my.applications.sync.service.MysyncService.cancelSync(MysyncService.java:1723)
at com.my.applications.sync.syncadapter.OtherSyncAdapter.onSyncCanceled(OtherSyncAdapter.java:51)
at android.content.AbstractThreadedSyncAdapter$ISyncAdapterImpl.cancelSync(AbstractThreadedSyncAdapter.java:121)
at android.content.ISyncAdapter$Stub.onTransact(ISyncAdapter.java:78)
at android.os.Binder.execTransact(Binder.java:320)
at dalvik.system.NativeStart.run(Native Method)
Do I need to add any permission for my internal content provider?
It looks from your stack trace that you've declared a readPermission on your ContentProvider. When onSyncCanceled(..) is called on your app it's an RPC call from the sync manager (typically) - and the Sync manager is not likely to hold the readPermission.
Try the following in #onCancelSync(..) to run your cancel code without the callers pid/uid involved:
long caller = android.os.Binder.clearCallingIdentity();
try {
// Do your stuff here
} finally {
android.os.Binder.restoreCallingIdentity(caller);
}
Br,
Jens
Related
I have got this crash report in firebase crashlytics, titled -
SQLiteConnection.java
android.database.sqlite.SQLiteConnection.nativeExecute
and the stacktrace lists these error:
Fatal Exception: java.lang.IllegalStateException
The file system on the device is in a bad state. WorkManager cannot access the app's internal data store.
androidx.work.impl.utils.ForceStopRunnable.run (ForceStopRunnable.java:128)
androidx.work.impl.utils.SerialExecutor$Task.run (SerialExecutor.java:91)
java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1162)
java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:636)
previous items in the stack
Caused by android.database.sqlite.SQLiteDatabaseLockedException: database is locked (code 5)
at android.database.sqlite.SQLiteConnection.nativeExecute(SQLiteConnection.java)
at android.database.sqlite.SQLiteConnection.execute(SQLiteConnection.java:569)
at android.database.sqlite.SQLiteSession.beginTransactionUnchecked(SQLiteSession.java:323)
at android.database.sqlite.SQLiteSession.beginTransaction(SQLiteSession.java:298)
at android.database.sqlite.SQLiteDatabase.beginTransaction(SQLiteDatabase.java:539)
at android.database.sqlite.SQLiteDatabase.beginTransaction(SQLiteDatabase.java:450)
at androidx.sqlite.db.framework.FrameworkSQLiteDatabase.beginTransaction(FrameworkSQLiteDatabase.java:69)
at androidx.work.impl.WorkDatabase$2.onOpen(WorkDatabase.java:163)
at androidx.work.impl.WorkDatabase_Impl$1.onOpen(WorkDatabase_Impl.java:113)
at androidx.room.RoomOpenHelper.onOpen(RoomOpenHelper.java:136)
at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.onOpen(FrameworkSQLiteOpenHelper.java:195)
at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:349)
at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:238)
at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.getWritableSupportDatabase(FrameworkSQLiteOpenHelper.java:145)
at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper.getWritableDatabase(FrameworkSQLiteOpenHelper.java:106)
at androidx.room.RoomDatabase.inTransaction(RoomDatabase.java:622)
at androidx.room.RoomDatabase.assertNotSuspendingTransaction(RoomDatabase.java:399)
at androidx.work.impl.model.SystemIdInfoDao_Impl.getWorkSpecIds(SystemIdInfoDao_Impl.java:120)
at androidx.work.impl.background.systemjob.SystemJobScheduler.reconcileJobs(SystemJobScheduler.java:298)
at androidx.work.impl.utils.ForceStopRunnable.cleanUp(ForceStopRunnable.java:249)
at androidx.work.impl.utils.ForceStopRunnable.forceStopRunnable(ForceStopRunnable.java:215)
at androidx.work.impl.utils.ForceStopRunnable.run(ForceStopRunnable.java:110)
at androidx.work.impl.utils.SerialExecutor$Task.run(SerialExecutor.java:91)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
at java.lang.Thread.run(Thread.java:764)
SO the SQLiteDatabaseLockedException is happening at SystemIdInfoDao_Impl.getWorkSpecIds(SystemIdInfoDao_Impl.java:120) line, while working with workmanager internal table SystemIdInfo and ForceStopRunnable.forceStopRunnable(ForceStopRunnable.java:215) line, forceStopRunnable method of ForceStopRunnable is calling that.
I wanted to understand more on when these function are called.
The description
"WorkManager is restarted after an app was force stopped.
Alarms and Jobs get cancelled when an application is force-stopped. To reschedule, we
create a pending alarm that will not survive force stops."
is not clear to me.
Can someone help me understand these and help me fix the crash?
EDIT - As the sqliteLockException is thrown at forceStopRunnable() metjod of forceStopRunnable class and it passes the exception to the InitializationExceptionHandler of the workmanager if workmanager is configured to have one.
I have passed an implementation for InitializationExceptionHandler to workmanager, while initializing. This could be possible FIX.
Will update here, once confirmed.
The problem is you are not closed previous actions and try to do another actions in the database. you have to close your SQLiteDatabase after perform some actions.By using this code
db.setTransactionSuccessful()
then start your next CRUD actions
I've been getting reports of the following crash
SecurityException: <<other_package>> from uid xxx not allowed to perform READ_CLIPBOARD
The crash occurred when a user clicks on a button that copies a text into clipboard as shown below.
val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
val clip = ClipData.newPlainText("label", shareUrl)
clipboard.setPrimaryClip(clip)
So my app doesn't try to read anything from clipboard. Really confusing why this error could happen.
Does anyone know how this crash happen and how can I fix this?
Additional Information
This crash only happens in Android 9 and Android 10 and not happens easily (only 6 users from 200k monthly active users)
I only saw two <<other_package>> in Crashlytics (one is a Bank app and another is a Music app).
I tried to read the source code of ClipboardService.java and AppOpsManager.java and found that the crash might came from noteOp in AppOpsManager.
Here is the stack trace of the crash:
Fatal Exception: java.lang.SecurityException: <<other_package>> from uid xxx not allowed to perform READ_CLIPBOARD
at android.os.Parcel.createException(Parcel.java:2087)
at android.os.Parcel.readException(Parcel.java:2055)
at android.os.Parcel.readException(Parcel.java:2003)
at android.content.IClipboard$Stub$Proxy.setPrimaryClip(IClipboard.java:293)
at android.content.ClipboardManager.setPrimaryClip(ClipboardManager.java:106)
at my.package.MyClass.copyToClipboard(MyClass.java:63)
at android.view.View.performClick(View.java:7375)
at android.view.View.performClickInternal(View.java:7336)
at android.view.View.access$3900(View.java:822)
at android.view.View$PerformClick.run(View.java:28214)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:238)
at android.app.ActivityThread.main(ActivityThread.java:7829)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:986)
Caused by android.os.RemoteException: Remote stack trace:
at android.app.AppOpsManager.noteOp(AppOpsManager.java:2568)
at com.android.server.clipboard.ClipboardService.clipboardAccessAllowed(ClipboardService.java:933)
at com.android.server.clipboard.ClipboardService.setPrimaryClipInternal(ClipboardService.java:775)
at com.android.server.clipboard.ClipboardService.setPrimaryClipInternal(ClipboardService.java:710)
at com.android.server.clipboard.ClipboardService$ClipboardImpl.setPrimaryClip(ClipboardService.java:358)
I can finally reproduce the crash in Android 9. This is what I found...
Root cause: When foreground app calls setPrimaryClipboard, the ClipboardService will broadcast the event to PrimaryClipChangedListener (if any) and will also make a call to AppOpsManager.noteOp to inform about READ_CLIPBOARD operation.
If the listener is not allowed to READ_CLIPBOARD (user can disallow by using adb shell command: cmd appops set <package> READ_CLIPBOARD deny), AppOpsManager.noteOp will throw a SecurityException and will crash the foreground app.
Now I'm sure that my code doesn't do anything wrong, but unfortunately I think I have to put try/catch around setPrimaryClip
I have a widget which I am trying to use to display information from my app's local database inside of a listview.
I'm using the RemoteViewsService.RemoteViewsFactory interface to load my list's contents. If I run the block of code which reloads the list in the onDataSetChanged method. the app crashes with the following message:
11-01 16:40:39.540: E/ACRA(27175): DataDisplay fatal error : Permission Denial: reading com.datadisplay.content.ContentProviderAdapter uri content://com.datadisplay.provider.internalDB/events from pid=573, uid=10029 requires the provider be exported, or grantUriPermission()
However, this same code run in the class's constructor works just fine. Of course, I need to have this also work in the onDataSetChanged method for updating and stuff.
Here is my provider's entry in the manifest:
<provider android:name="com.datadisplay.content.ContentProviderAdapter"
android:authorities="com.datadisplay.provider.internalDB"
android:exported="true"
android:enabled="true"
android:grantUriPermissions="true">
<grant-uri-permission android:pathPattern="/events/"/>
</provider>
I am both exporting it AND granting Uri permissions like the error message requests, but it still fails. I found this question, where the guy had an issue but eventually removes his custom permissions and it worked. I don't have any custom permissions like that, but still no luck:
Widget with content provider; impossible to use ReadPermission?
If anyone has insight I'd be really grateful, this is getting incredibly frustrating, haha.
This is happening because RemoteViewsFactory is being called from a remote process, and that context is being used for permission enforcement. (The remote caller doesn't have permission to use your provider, so it throws a SecurityException.)
To solve this, you can clear the identity of the remote process, so that permission enforcement is checked against your app instead of against the remote caller. Here's a common pattern you'll find across the platform:
final long token = Binder.clearCallingIdentity();
try {
[perform your query, etc]
} finally {
Binder.restoreCallingIdentity(token);
}
Put this in your onDataSetChanged() method:
Thread thread = new Thread() {
public void run() {
query();
}
};
thread.start();
try {
thread.join();
} catch (InterruptedException e) {
}
Fetch data from the database inside query() method. I do not know why fetching data in a separate thread helps get around this problem, but it works! I got this from one of the Android examples.
If this only happens for 4.2 and not the rest, you need to set the android:exported="true", because the default is changed:
http://developer.android.com/about/versions/android-4.2.html
Content providers are no longer exported by default. That is, the default value for the android:exported attribute is now “false". If it’s important that other apps be able to access your content provider, you must now explicitly set android:exported="true".
Alright, so I'm trying to implement Data Backup into my application, and have been following this guide. I've implemented my BackupAgentHelper using a SharedPreferencesBackupHelper. I don't get any errors, and I'm being sure to call dataChanged() after all preference changes, but when I test the backup (`adb shell bmgr run) I get this information in LogCat:
07-07 12:29:00.258: V/BackupManagerService(291): Scheduling immediate backup pass
07-07 12:29:00.258: V/BackupManagerService(291): Running a backup pass
07-07 12:29:00.258: V/BackupManagerService(291): clearing pending backups
07-07 12:29:00.258: V/PerformBackupTask(291): Beginning backup of 1 targets
07-07 12:29:00.289: V/BackupServiceBinder(291): doBackup() invoked
07-07 12:29:00.289: D/PerformBackupTask(291): invokeAgentForBackup on #pm#
07-07 12:29:00.297: I/PerformBackupTask(291): no backup data written; not calling transport
So for reference, in my manifest I've added:
<application
android:allowBackup="true"
android:backupAgent="com.kcoppock.sudoku.SudokuBackupAgent"
as well as
<meta-data
android:name="com.google.android.backup.api_key"
android:value="my_key_goes_here" />
and my BackupAgentHelper is implemented like so:
public class SudokuBackupAgent extends BackupAgentHelper {
static final String SCORES = "SCORES";
static final String BACKUP_ID = "sudoku_backup";
#Override
public void onCreate() {
SharedPreferencesBackupHelper backupHelper =
new SharedPreferencesBackupHelper(this, SCORES);
addHelper(BACKUP_ID, backupHelper);
}
}
and finally, in my main activity, I call for a data backup like this:
edit.putString(id + "_values", valueCache.toString());
edit.putString(id + "_hints", hintCache.toString());
edit.commit();
BackupManager backup = new BackupManager(this);
backup.dataChanged();
I've tried debugging, and it seems my onCreate() in SudokuBackupAgent is never called. Or at least it's never reached from the debugger. It seems it isn't finding any updated data, and I have double checked to ENSURE there is data to be backed up. Is there something I'm missing here?
EDIT: I should add, I'm testing on a device (Galaxy Nexus), and I've even tried using an exported release APK for testing purposes.
1) Put Log.i() into your onCreate, to see if it's called.
2) Logcat indicates that your function didn't write anything. Check if you have shared_prefs/SCORES file in your app's private folder (assumes using appropriate file manager on rooted device). This is the file you're attempting to have in backup.
Probably your preferences file is something else than this file, in such case fix your String SCORES to reflect real preferences file.
3) I tried to debug BackupAgentHelper.onCreate in my app, and it can be debugged after invoking adb shell bmgt... so it is possible to step here in debugger.
I had the same problem today with Android SDK 4.1. Using 2.3.3 versions, however, helped:
07-15 13:59:56.459: V/LocalTransport(61): performBackup() pkg=com........
07-15 13:59:56.469: V/LocalTransport(61): Got change set key=filehelper:../databases/database.db size=8208 key64=ZmlsZWhlbHBlcjouLi8kYXRhYmFzZXMvZXhwZW5zZXIuZGI=
07-15 13:59:56.469: V/LocalTransport(61): data size 8208
07-15 13:59:56.469: V/LocalTransport(61): finishBackup()
If you do not change your preferences data it will just back up once but not subsequently.
https://developer.android.com/reference/android/app/backup/SharedPreferencesBackupHelper.html
"Whenever a backup is performed, it will back up all named shared preferences that have changed since the last backup operation."
As other poster said make sure to have a log statement in your onCreate.
You can force a backup by:
// bmgr wipe TRANSPORT PACKAGE
bmgr wipe com.google.android.backup/.BackupTransportService com.kcoppock.sudoku
bmgr run
The default is com.google.android.backup/.BackupTransportService, but best to check for yourself with bmgr list transports.
You'll be much happier running against the local transport, not the default Google Transport. Check the dev docs on this.
My problem is the next :
When an user hold search's button on an android phone, and this, while a progress bar is in action, the following error message is displayed:
ERROR / AndroidRuntime ( 16794 ): java.lang. SecurityException: Requesting codes from com.google.android.voicesearch (with uid 10028) to be run in process com.xxxx.myApplication (with uid 10088)
Thus, further to this message I tried several things: kill the process ' com.google.android.voicesearch ' :
JAVA code :
if (event.getKeyCode() == KeyEvent.KEYCODE_SEARCH)
{
if (!event.isLongPress() && !Utils.getMyProgress().isShowing())
{
searchProducts();
}
else
{
android.os.Process.killProcess(android.os.Process.getUidForName("com.google.android.voicesearch"));
}
return true;
}
Unsuccessfully! Thus the idea is to prevent the process 'com.google.android.voicesearch' from being started
every time the user of the telephone maintainings for a long time the key(touch) "to look for" of its telephone (example on htc, this key(touch) exists. Rather, a physical and not tactile key(touch)!)
Maybe is it possible to block the launch of this process ('com.google.android.voicesearch') in the in the manifest.xml, while my application is launched :
manifest.xml :
<application
android:debuggable="false"
android:enabled="false"
android:killAfterRestore="false"
android:process="com.google.android.voicesearch">
</application>
Any idea ?
Thanks for answers !
In order to implement search with assistance from the Android system (to deliver search queries to an activity and provide search suggestions), your application must provide a search configuration in the form of an XML file called the searchable configuration. It configures certain UI aspects of the search dialog or widget and defines how features such as suggestions and voice search behave. This file is traditionally named searchable.xml and must be saved in the res/xml/ project directory.
According to this page, you only have to remove the voice entries from that file.