2012-02-29 60 views
15

所以我剛剛爲我的應用程序實現了一個小部件。它通過我的ContentProvider從數據庫中獲取數據。我定義我自己的讀/寫權限在我的清單,狀態,我使用他們(似乎並沒有發揮作用),並要求他們在內容提供商:帶內容提供商的小工具;不可能使用ReadPermission?

<!-- Define my permissions for the provider --> 
<permission 
    android:name="com.nononsenseapps.notepad.permissions.read" 
    android:description="@string/permission_read_desc" 
    android:label="@string/permission_read_label" 
    android:permissionGroup="android.permission-group.PERSONAL_INFO" 
    android:protectionLevel="normal" /> 
<permission 
    android:name="com.nononsenseapps.notepad.permissions.write" 
    android:description="@string/permission_write_desc" 
    android:label="@string/permission_write_label" 
    android:permissionGroup="android.permission-group.PERSONAL_INFO" 
    android:protectionLevel="normal" /> 
...... 
<uses-permission android:name="com.nononsenseapps.notepad.permissions.read" /> 
<uses-permission android:name="com.nononsenseapps.notepad.permissions.write" /> 
<uses-permission android:name="android.permission.BIND_REMOTEVIEWS" /> 
...... 
<provider 
     android:name=".NotePadProvider" 
     android:authorities="com.nononsenseapps.NotePad" 
     android:enabled="true" 
     android:exported="true" 
     android:label="@string/app_name" 
     android:readPermission="com.nononsenseapps.notepad.permissions.read" 
     android:syncable="true" 
     android:writePermission="com.nononsenseapps.notepad.permissions.write" > 
     <grant-uri-permission android:pathPattern=".*" /> 
    </provider> 

我通過更新我的窗口小部件Service(按照Widget教程):

<!-- List Widget --> 
    <receiver android:name="com.nononsenseapps.notepad.widget.ListWidgetProvider" > 
     <intent-filter> 
      <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> 
     </intent-filter> 

     <meta-data 
      android:name="android.appwidget.provider" 
      android:resource="@xml/listwidgetinfo" /> 
    </receiver> 

    <service 
     android:name="com.nononsenseapps.notepad.widget.ListWidgetService" 
     android:exported="false" 
     android:permission="android.permission.BIND_REMOTEVIEWS" /> 

而反過來說Service做到這一點(有沒有包括一串代碼):

/** 
* This is the service that provides the factory to be bound to the collection 
* service. 
*/ 
public class ListWidgetService extends RemoteViewsService { 

@Override 
public RemoteViewsFactory onGetViewFactory(Intent intent) { 
    return new StackRemoteViewsFactory(this.getApplicationContext(), intent); 
} 
} 

/** 
* This is the factory that will provide data to the collection widget. 
*/ 
class StackRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory { 

public StackRemoteViewsFactory(Context context, Intent intent) { 
    mContext = context; 
    observer = new ListChecker(null); 
    mAppWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, 
      AppWidgetManager.INVALID_APPWIDGET_ID); 
} 
public void onDataSetChanged() { 
    Log.d(TAG, "onDataSetChanged"); 
    // Refresh the cursor 
    if (mCursor != null) { 
     mCursor.close(); 
    } 

    // Get widget settings 
    SharedPreferences settings = mContext.getSharedPreferences(
      ListWidgetConfigure.getSharedPrefsFile(mAppWidgetId), 
      mContext.MODE_PRIVATE); 
    if (settings != null) { 
     String listWhere = settings.getString(ListWidgetConfigure.LIST_WHERE, null); 
     listId = settings.getLong(ListWidgetConfigure.LIST_ID, -1); 
     String sortOn = settings.getString(ListWidgetConfigure.SORT_ON, NotePad.Notes.ALPHABETIC_ASC_ORDER); 

     mCursor = mContext.getContentResolver().query(
       NotePadProvider.CONTENT_VISIBLE_URI, PROJECTION, listWhere, null, 
       sortOn); 
    } 
} 
} 

所以這裏的問題:當我將小部件添加到主屏幕時,當我嘗試查詢提供程序時,SecurityException立即引發到onDataSetChanged()方法中。這似乎是因爲主屏幕沒有讀取我的內容提供者的權限。我的直覺是,這不會是一個問題,因爲我的應用程序有權限,並且服務顯然是我的應用程序的一部分。

如果我從提供程序中刪除ReadPermission要求,一切都會很好。但這似乎是一個安全問題,因爲任何應用程序都可以訪問提供程序,而無需用戶批准任何內容。

那麼有沒有辦法使用帶有小部件的ReadPermission提供程序?或者你是否被迫使用不安全的導出提供者?

+0

我有完全相同的問題,你有沒有找到任何解決辦法了嗎?如果是這樣,你能否描述一下你如何解決它? – 2012-04-19 21:20:30

+0

可悲的是。發現沒有解決方案,所以我剛剛刪除了所需的權限:( – 2012-04-21 09:37:50

+0

也有這個問題... – JMRboosties 2012-11-01 23:33:23

回答

13

我能找到答案here,功勞歸於Kostya Vasilyev。

雖然上下文實際上是正確的,但是它綁定到錯誤的過程。

所以關鍵是要做到這一點:

public void onDataSetChanged() { 
    // Revert back to our process' identity so we can work with our 
    // content provider 
    final long identityToken = Binder.clearCallingIdentity(); 

    // Update your cursor or whaterver here 
    // ... 

    // Restore the identity - not sure if it's needed since we're going 
    // to return right here, but it just *seems* cleaner 
    Binder.restoreCallingIdentity(identityToken); 
} 
+0

完美的迴應。即使沒有在contentprovider上設置讀/寫權限,只要將其與導出設置爲「false」即可解決該問題。 – 2015-11-21 23:26:50

0

最有可能的是,這是因爲您正在使用小部件的上下文,這將是主屏幕的上下文。試試下面的行代碼:我

mCursor = ListWidgetService.this.getContentResolver().query(
      NotePadProvider.CONTENT_VISIBLE_URI, PROJECTION, listWhere, null, 
      sortOn); 

注意如何更換mContext.。服務是其自身的上下文,根據您的清單,服務應具有正確的權限。

+0

其實,如果你看看代碼,你會發現傳遞給RemoteViewsFactory的上下文正是你的建議。我進一步調查,我找到了解決方案!作爲回答發表吧! – 2013-10-02 17:14:09

+0

事實上,你是對的,不知道我是如何錯過的:)但我很高興它把你放在正確的軌道:) – 2013-10-02 17:40:37