android 数据库怎么监听数据变化

android 数据库怎么监听数据变化,第1张

在android中经常会用到改变数据库内容后再去使用数据库更新的内容,很多人会重新去query一遍,但是这样的问题就是程序会特别占内存,而且有可能会搂关cursor而导致程序内存未释放等等。其实android内部提供了一种ContentObserver的东西来监听数据库内容的变化。

ContentObserver的构造函数需要一个参数Hanlder,因为ContentObserver内部使用了一个实现Runnable接口的内部类NotificationRunnable,来实现数据库内容的变化。需要使用hanlder去post消息。注册ContentObserver的方法是:getContentResolver().registerContentObserver(uri, notifyForDescendents, observer).

上面3个参数为:uri----Uri类型,是需要监听的数据库的uri.

notifyForDescendents---boolean  true的话就会监听所有与此uri相关的uri。false的话则是直接特殊的uri才会监听。一般都设置为true.

observer-----ContentObserver  就是需要的contentobserver.

初始化一个ContentObserver对象,重载onChange(boolean ),在这个方法里去 *** 作数据库的使用,针对变化后的使用。

写了一个小demo,可以参考下。提示这种监听方式必须是contentprovider才能使用,因为contentprovider有uri.简单的那种sqlite数据库没有uri是使用不了的。

下面demo *** 作的是在一个activityA里点击button跳转至另外一个activityB,在B中点击button往数据库中加数据,加完后关闭B回到A。A的button的文字自动变化设置到数据库中的字符串。[code]

package ty.com.lto    

02         

03    import android.app.Activity    

04    import android.content.Intent    

05    import android.database.ContentObserver    

06    import android.os.Bundle    

07    import android.os.Handler    

08    import android.view.View    

09    import android.widget.Button    

10         

11    public class ListenDataTest extends Activity{    

12        private Button testBtn    

13         

14            @Override    

15            protected void onCreate(Bundle savedInstanceState) {    

16                    super.onCreate(savedInstanceState)    

17                    setContentView(R.layout.listen_data_test)    

18                   getContentResolver().registerContentObserver(DataChangeProvider.CONTENT_URI,    

19                                    true, cob)    

20                         

21                    testBtn = (Button)findViewById(R.id.test_btn)    

22                    testBtn.setOnClickListener(new View.OnClickListener() {    

23                                 

24                            public void onClick(View v) {    

25                                    Intent in = newIntent(ListenDataTest.this,DataChangeTest.class)    

26                                    startActivity(in)    

27                                         

28                            }    

29                    })    

30                         

31            }    

32                 

33            private ContentObserver cob = new ContentObserver(new Handler()) {    

34         

35                    @Override    

36                    public boolean deliverSelfNotifications() {    

37                            return super.deliverSelfNotifications()    

38                    }    

39         

40                    @Override    

41                    public void onChange(boolean selfChange) {    

42                            super.onChange(selfChange)    

43                           testBtn.setText(DataUtils.getChangeName(getApplicationContext()))    

44                    }    

45                          

46             }    

47         

48            @Override    

49            protected void onDestroy() {    

50                    super.onDestroy()    

51                    getContentResolver().unregisterContentObserver(cob)    

52            }    

53              

54                  

55    }    

[code]01    package ty.com.lto    

02         

03    import android.app.Activity    

04    import android.content.ContentValues    

05    import android.content.Intent    

06    import android.database.ContentObservable    

07    import android.database.ContentObserver    

08    import android.os.Bundle    

09    import android.os.Handler    

10    import android.view.View    

11    import android.widget.Button    

12         

13    public class DataChangeTest extends Activity{    

14         private Button dataBtn    

15         DataSqlite mDataSqlite    

16         @Override    

17         protected void onCreate(Bundle savedInstanceState) {    

18            super.onCreate(savedInstanceState)    

19            setContentView(R.layout.data_change_test)    

20            dataBtn = (Button)findViewById(R.id.data_test_btn)    

21            mDataSqlite = new DataSqlite(this)    

22            dataBtn.setOnClickListener(new View.OnClickListener() {    

23                     

24                public void onClick(View v) {    

25                    ContentValues con = new ContentValues()    

26                    con.put("name", "数据变化了")    

27                    getContentResolver().insert(DataChangeProvider.CONTENT_URI, con)    

28                    finish()    

29                }    

30            })    

31         }    

32    }    

[code]view sourceprint?

001    package ty.com.lto    

002          

003          

004    import android.content.ContentProvider    

005    import android.content.ContentUris    

006    import android.content.ContentValues    

007    import android.content.Context    

008    import android.content.UriMatcher    

009    import android.database.Cursor    

010    import android.database.SQLException    

011    import android.database.sqlite.SQLiteDatabase    

012    import android.database.sqlite.SQLiteOpenHelper    

013    import android.database.sqlite.SQLiteQueryBuilder    

014    import android.database.sqlite.SQLiteDatabase.CursorFactory    

015    import android.net.Uri    

016    import android.text.TextUtils    

017          

018    public class DataChangeProvider extends ContentProvider{    

019        private SQLiteOpenHelper mOpenHelper    

020        private static final int ALARMS = 1    

021        private static final int ALARMS_ID = 2    

022        private static final UriMatcher sURLMatcher = new UriMatcher(UriMatcher.NO_MATCH)    

023        public static final Uri CONTENT_URI = Uri.parse("content://ty.com.lto/test")    

024          

025        static {    

026            sURLMatcher.addURI("ty.com.lto", "test", ALARMS)    

027            sURLMatcher.addURI("ty.com.lto", "test/#", ALARMS_ID)    

028        }    

029             

030        private static class DatabaseHelper extends SQLiteOpenHelper{    

031             private static final String TEST_DATABASE = "test.db"    

032             private static final int VERSION = 1    

033                  

034             public DatabaseHelper(Context context) {    

035                 super(context, TEST_DATABASE, null, VERSION)    

036                 // TODO Auto-generated constructor stub    

037             }    

038                   

039          

040             @Override    

041             public void onCreate(SQLiteDatabase db) {    

042                 String sql = "CREATE TABLE "+"test"+" (" +    

043                         "_id INTEGER PRIMARY KEY," +    

044                         "name TEXT "+    

045                          ")"    

046                 db.execSQL(sql)    

047             }    

048          

049             @Override    

050             public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {    

051                 String sql = "DROP TABLE IF EXIST "+TEST_DATABASE    

052                 db.execSQL(sql)    

053                 onCreate(db)    

054             }    

055                  

056        }    

057             

058        public DataChangeProvider() {    

059        }    

060             

061        @Override    

062        public int delete(Uri url, String where, String[] whereArgs) {    

063            SQLiteDatabase db = mOpenHelper.getWritableDatabase()    

064            int count    

065            long rowId = 0    

066            switch (sURLMatcher.match(url)) {    

067                case ALARMS:    

068                    count = db.delete("test", where, whereArgs)    

069                    break    

070                case ALARMS_ID:    

071                    String segment = url.getPathSegments().get(1)    

072

众所周知Android在4.4上增加了不少安全措施,除了把SELinux设置为enforce外,在短信方向也加强了限制。4.4之后,新增了一个default sms的机制,详细的描述,可以参考我的另一篇文章《谈谈4.4中的新增功能对安全类软件的影响》。简而言之,就是如果要在4.4之后实现短信拦截功能,就必须成为default sms,把所有短信相关的功能都包揽了,然后再做短信拦截。但这种做法,适配性和兼容性的工作是非常巨大的,短信、wapush(多种)、彩信、单双卡等等,相当于要求短信拦截类的软件要集成一个功能非常完善的通讯录类应用的功能。

那么,是否有一种方法,可以在不成为default sms的同时也可以对短信进行“写 *** 作”(这可是让4.4一下子回到解放前啊。。。。)? 答案是有的。

XDA大牛有人发现了一种比较讨巧的方法,原文可以参考这里。

原理很简单,主要是利用4.2+后的添加的App Ops权限管理功能,在MESSAGE的TAB中找到自己的App,并进入相应的权限管理界面,如下图所示,FinalDemo是我自己测试的一个DEMO:

留意到Write SMS/MMS的开头,默认是OFF的,但我们可以把它打开。

打开之后,我们就可以通过监控短信数据库变化的方法实现短信拦截了,我也写了个简单的测试代码,测试成功,把代码和相关的配置也放了来吧

打开App Ops的代码

[java] view plaincopy

<span style="white-space:pre"> </span>Intent intent = new Intent(Intent.ACTION_MAIN)

ComponentName cn = new ComponentName("com.android.settings", "com.android.settings.Settings")

什么意思啊? 是 *** 作短信数据库吗?你可以使用 contentobserver类监控短信数据库,插入成功,短信数据库就会发生变化,就会触发这个监听,如果插入失败,这个监听就不会触发. 使用api *** 作数据库应该也会有返回值啊,判断返回值...


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/sjk/6670587.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-03-26
下一篇 2023-03-26

发表评论

登录后才能评论

评论列表(0条)

保存