传智播客_Android笔记2

使用ContentProvider共享数据

ContentProvider类主要方法的作用:

public boolean onCreate()

该方法在ContentProvider创建后就会被调用, Android在系统启动时就会创建ContentProvider 。

public Uri insert(Uri uri, ContentValues values)

该方法用于供外部应用往ContentProvider添加数据。

public int delete(Uri uri, String selection, String[] selectionArgs)

该方法用于供外部应用从ContentProvider删除数据。

public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)

该方法用于供外部应用更新ContentProvider中的数据。

public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)

该方法用于供外部应用从ContentProvider中获取数据。

public String getType(Uri uri)

该方法用于返回当前Url所代表数据的MIME类型。如果操作的数据属于集合类型,那么MIME类型字符串应该以vnd.android.cursor.dir/开头,例如:要得到所有person记录的Uri为content://cn.itcast.provider.personprovider/person,那么返回的MIME类型字符串应该为:“vnd.android.cursor.dir/person”。如果要操作的数据属于单一数据,那么MIME类型字符串应该以vnd.android.cursor.item/开头,例如:得到id为10的person记录,Uri为content://cn.itcast.provider.personprovider/person/10,那么返回的MIME类型字符串应该为:“vnd.android.cursor.item/person”。

使用ContentResolver操作ContentProvider中的数据

当外部应用需要对ContentProvider中的数据进行添加、删除、修改和查询操作时,可以使用ContentResolver 类来完成,要获取ContentResolver 对象,可以使用Activity提供的getContentResolver()方法。 ContentResolver 类提供了与ContentProvider类相同签名的四个方法:

public Uri insert(Uri uri, ContentValues values)

该方法用于往ContentProvider添加数据。

public int delete(Uri uri, String selection, String[] selectionArgs)

该方法用于从ContentProvider删除数据。

public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)

该方法用于更新ContentProvider中的数据。

public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)

该方法用于从ContentProvider中获取数据。

这些方法的第一个参数为Uri,代表要操作的是哪个ContentProvider和对其中的什么数据进行操作,假设给定的是: Uri.parse(“content://cn.itcast.provider.personprovider/person/10”),那么将会对主机名为cn.itcast.provider.personprovider的ContentProvider进行操作,操作的数据为person表中id为10的记录。

使用ContentResolver操作ContentProvider中的数据

使用ContentResolver对ContentProvider中的数据进行添加、删除、修改和查询操作:

ContentResolver resolver =  getContentResolver();

Uri uri = Uri.parse("content://cn.itcast.provider.personprovider/person");

//添加一条记录

ContentValues values = new ContentValues();

values.put("name", "itcast");

values.put("age", 25);

resolver.insert(uri, values);              

//获取person表中所有记录

Cursor cursor = resolver.query(uri, null, null, null, "personid desc");

while(cursor.moveToNext()){

         Log.i("ContentTest", "personid="+ cursor.getInt(0)+ ",name="+ cursor.getString(1));

}

//把id为1的记录的name字段值更改新为liming

ContentValues updateValues = new ContentValues();

updateValues.put("name", "liming");

Uri updateIdUri = ContentUris.withAppendedId(uri, 2);

resolver.update(updateIdUri, updateValues, null, null);

//删除id为2的记录

Uri deleteIdUri = ContentUris.withAppendedId(uri, 2);

resolver.delete(deleteIdUri, null, null);

 

<uses-permission android:name="android.permission.READ_CONTACTS"/>

读取联系人信息

Cursor cursor = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, 

    null, null, null, null); 

  while (cursor.moveToNext()) { 

   String contactId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID)); 

   Log.i("RongActivity", "contactId="+ contactId);

   String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)); 

   Log.i("RongActivity", "name="+ name);

  

   Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, 

        null, 

        ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = "+ contactId, 

        null, null); 

    while (phones.moveToNext()) { 

     String phoneNumber = phones.getString(phones.getColumnIndex( 

         ContactsContract.CommonDataKinds.Phone.NUMBER)); 

     Log.i("RongActivity", "phoneNumber="+phoneNumber);

    } 

    phones.close(); 

  

       Cursor emails = getContentResolver().query(ContactsContract.CommonDataKinds.Email.CONTENT_URI, 

       null, 

       ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = " + contactId, 

       null, null); 

       while (emails.moveToNext()) { 

        // This would allow you get several email addresses 

        String emailAddress = emails.getString(emails.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));

        Log.i("RongActivity", "emailAddress="+ emailAddress);

       } 

       emails.close(); 

  } 

  cursor.close();

 

为应用添加新的Activity

第一步:新建一个继承Activity的类,如:NewActivity

public class NewActivity extends Activity {

    @Override protected void onCreate(Bundle savedInstanceState) {

                   super.onCreate(savedInstanceState);

         //这里可以使用setContentView(R.layout.xxx)显示某个视图....

     }

}

第二步:需要在功能清单AndroidManifest.xml文件中添加进上面Activity配置代码(红色部分):

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

      package="cn.itcast.action"

      android:versionCode="1"

      android:versionName="1.0">

    <application android:icon="@drawable/icon" android:label="@string/app_name">

        .....

         <activity android:name=".NewActivity" android:label="新activity的页面标题"/>

    </application>

    ...

</manifest>

android:name属性值的前面加了一个点表示NewActivity是当前包cn.itcast.action下的类,如果类在应用的当前包下,可以省略点符号,如果类在应用的子包下必须加点,如:NewActivity类在cn.itcast.action.user包下可以这样写:<activity android:name=“.user.NewActivity“ />

打开新的Activity ,不传递参数

在一个Activity中可以使用系统提供的startActivity(Intent intent)方法打开新的Activity,在打开新的Activity前,你可以决定是否为新的Activity传递参数:

第一种:打开新的Activity,不传递参数

public class MainActivity extends Activity {

  @Override protected void onCreate(Bundle savedInstanceState) {

         .......

         Button button =(Button) this.findViewById(R.id.button);

                           button.setOnClickListener(new View.OnClickListener(){//点击该按钮会打开一个新的Activity

                   public void onClick(View v) {

                          //新建一个显式意图,第一个参数为当前Activity类对象,第二个参数为你要打开的Activity类

                       startActivity(new Intent(MainActivity.this, NewActivity.class));

         }});

         }

}

打开新的Activity,并传递若干个参数给它

第二种:打开新的Activity,并传递若干个参数给它:

public class MainActivity extends Activity {

  @Override protected void onCreate(Bundle savedInstanceState) {

         .......

          button.setOnClickListener(new View.OnClickListener(){//点击该按钮会打开一个新的Activity

                   public void onClick(View v) {

                    Intent intent = new Intent(MainActivity.this, NewActivity.class)

Bundle bundle = new Bundle();//该类用作携带数据

bundle.putString("name", "传智播客");

bundle.putInt("age", 4);

intent.putExtras(bundle);//附带上额外的数据

startActivity(intent);

         }}); }

}

在新的Activity中接收前面Activity传递过来的参数:

public class NewActivity extends Activity {

            @Override protected void onCreate(Bundle savedInstanceState) {

              ........     

              Bundle bundle = this.getIntent().getExtras();

              String name = bundle.getString("name");

                      int age = bundle.getInt("age");

            }

}

 

Bundle类的作用

Bundle类用作携带数据,它类似于Map,用于存放key-value名值对形式的值。相对于Map,它提供了各种常用类型的putXxx()/getXxx()方法,如:putString()/getString()和putInt()/getInt(),putXxx()用于往Bundle对象放入数据,getXxx()方法用于从Bundle对象里获取数据。Bundle的内部实际上是使用了HashMap<String, Object>类型的变量来存放putXxx()方法放入的值:

public final class Bundle implements Parcelable, Cloneable {

            ......

 Map<String, Object> mMap;

 public Bundle() {

       mMap = new HashMap<String, Object>();

        ......

 }

 public void putString(String key, String value) {

      mMap.put(key, value);

 }

public String getString(String key) {

       Object o = mMap.get(key);

        return (String) o;

        ........//类型转换失败后会返回null,这里省略了类型转换失败后的处理代码

}

}

在调用Bundle对象的getXxx()方法时,方法内部会从该变量中获取数据,然后对数据进行类型转换,转换成什么类型由方法的Xxx决定,getXxx()方法会把转换后的值返回。

为Intent附加数据的两种写法

第一种写法,用于批量添加数据到Intent:

Intent intent = new Intent();

Bundle bundle = new Bundle();//该类用作携带数据

bundle.putString("name", "传智播客");

intent.putExtras(bundle);//为意图追加额外的数据,意图原来已经具有的数据不会丢失,但key同名的数据会被替换

第二种写法:这种写法的作用等价于上面的写法,只不过这种写法是把数据一个个地添加进Intent,这种写法使用起来比较方便,而且只需要编写少量的代码。

Intent intent = new Intent();

intent.putExtra("name", "传智播客");

Intent提供了各种常用类型重载后的putExtra()方法,如: putExtra(String name, String value)、 putExtra(String name, long value),在putExtra()方法内部会判断当前Intent对象内部是否已经存在一个Bundle对象,如果不存在就会新建Bundle对象,以后调用putExtra()方法传入的值都会存放于该Bundle对象,下面是Intent的putExtra(String name, String value)方法代码片断:

public class Intent implements Parcelable {

private Bundle mExtras;

public Intent putExtra(String name, String value) {

        if (mExtras == null) {

            mExtras = new Bundle();

        }

        mExtras.putString(name, value);

        return this;

 }

得到新打开Activity 关闭后返回的数据

如果你想在Activity中得到新打开Activity 关闭后返回的数据,你需要使用系统提供的startActivityForResult(Intent intent, int requestCode)方法打开新的Activity,新的Activity 关闭后会向前面的Activity 传回数据,为了得到传回的数据,你必须在前面的Activity中重写onActivityResult(int requestCode, int resultCode, Intent data)方法:

public class MainActivity extends Activity {

      @Override protected void onCreate(Bundle savedInstanceState) {

         .......

         Button button =(Button) this.findViewById(R.id.button);

                           button.setOnClickListener(new View.OnClickListener(){//点击该按钮会打开一个新的Activity

                   public void onClick(View v) {

                   //第二个参数为请求码,可以根据业务需求自己编号

                   startActivityForResult (new Intent(MainActivity.this, NewActivity.class),  1);

         }});

         }

    //第一个参数为请求码,即调用startActivityForResult()传递过去的值

    //第二个参数为结果码,结果码用于标识返回数据来自哪个新Activity

   @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {

         String result = data.getExtras().getString(“result”));//得到新Activity 关闭后返回的数据

    }

}    当新Activity关闭后,新Activity返回的数据通过Intent进行传递,android平台会调用前面Activity 的onActivityResult()方法,把存放了返回数据的Intent作为第三个输入参数传入,在onActivityResult()方法中使用第三个输入参数可以取出新Activity返回的数据。

 

使用startActivityForResult(Intent intent, int requestCode)方法打开新的Activity,新Activity关闭前需要向前面的Activity返回数据需要使用系统提供的setResult(int resultCode, Intent data)方法实现:

public class NewActivity extends Activity {

         @Override protected void onCreate(Bundle savedInstanceState) {

                   ......

                 button.setOnClickListener(new View.OnClickListener(){

                   public void onClick(View v) {

                            Intent intent = new Intent();//数据是使用Intent返回

                            intent.putExtra(“result”, “传智播客的学生很可爱”);//把返回数据存入Intent

                             NewActivity.this.setResult(RESULT_OK, intent);//设置返回数据

                             NewActivity.this.finish();//关闭Activity

                   }});

         }

}

setResult()方法的第一个参数值可以根据业务需要自己定义,上面代码中使用到的RESULT_OK是系统Activity类定义的一个常量,值为-1,代码片断如下:

public class android.app.Activity extends ......{

  public static final int RESULT_CANCELED = 0;

  public static final int RESULT_OK = -1;

  public static final int RESULT_FIRST_USER = 1;

}

请求码的作用

使用startActivityForResult(Intent intent, int requestCode)方法打开新的Activity,我们需要为startActivityForResult()方法传入一个请求码(第二个参数)。请求码的值是根据业务需要由自已设定,用于标识请求来源。例如:一个Activity有两个按钮,点击这两个按钮都会打开同一个Activity,不管是那个按钮打开新Activity,当这个新Activity关闭后,系统都会调用前面Activity的onActivityResult(int requestCode, int resultCode, Intent data)方法。在onActivityResult()方法如果需要知道新Activity是由那个按钮打开的,并且要做出相应的业务处理,这时可以这样做:

 @Override  public void onCreate(Bundle savedInstanceState) {

        ....

        button1.setOnClickListener(new View.OnClickListener(){

           public void onClick(View v) {

                      startActivityForResult (new Intent(MainActivity.this, NewActivity.class), 1);

            }});

        button2.setOnClickListener(new View.OnClickListener(){

           public void onClick(View v) {

                      startActivityForResult (new Intent(MainActivity.this, NewActivity.class), 2);

            }});

       @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {

               switch(requestCode){

                   case 1:

                       //来自按钮1的请求,作相应业务处理

                   case 2:

                     //来自按钮2的请求,作相应业务处理

                }

          }

}

结果码的作用

在一个Activity中,可能会使用startActivityForResult()方法打开多个不同的Activity处理不同的业务,当这些新Activity关闭后,系统都会调用前面Activity的onActivityResult(int requestCode, int resultCode, Intent data)方法。为了知道返回的数据来自于哪个新Activity,在onActivityResult()方法中可以这样做(ResultActivity和NewActivity为要打开的新Activity):

public class ResultActivity extends Activity {

       .....

       ResultActivity.this.setResult(1, intent);

       ResultActivity.this.finish();

}

public class NewActivity extends Activity {

       ......

        NewActivity.this.setResult(2, intent);

        NewActivity.this.finish();

}

public class MainActivity extends Activity { // 在该Activity会打开ResultActivity和NewActivity

       @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {

               switch(resultCode){

                   case 1:

                       // ResultActivity的返回数据

                   case 2:

                    // NewActivity的返回数据

                }

          }

}

Intent(意图)

Android基本的设计理念是鼓励减少组件间的耦合,因此Android提供了Intent (意图) ,Intent提供了一种通用的消息系统,它允许在你的应用程序与其它的应用程序间传递Intent来执行动作和产生事件。使用Intent可以激活Android应用的三个核心组件:活动、服务和广播接收器。

Intent可以划分成显式意图和隐式意图。

显式意图:调用Intent.setComponent()或Intent.setClass()方法指定了组件名或类对象的Intent为显式意图,显式意图明确指定了Intent应该传递给哪个组件。

隐式意图:没有调用Intent.setComponent()或Intent.setClass()方法指定组件名或类对象的Intent为隐式意图。 Android系统会根据隐式意图中设置的动作(action)、类别(category)、数据(URI和数据类型)找到最合适的组件来处理这个意图。那么Android是怎样寻找到这个最合适的组件呢?记的前面我们在定义活动时,指定了一个intent-filter,Intent Filter(过滤器)其实就是用来匹配隐式Intent的,如果Intent Filter定义的动作、类别、数据(URI和数据类型)与Intent匹配,就会使用Intent Filter所在的组件来处理该Intent。想要接收使用startActivity()方法传递的隐式意图的活动必须在它们的意图过滤器中包含"android.intent.category.DEFAULT"

 

Activity生命周期

Activity有三个状态:

l   当它在屏幕前台时(位于当前任务堆栈的顶部),它是激活或运行状态。它就是响应用户操作的Activity。

l   当它失去焦点但仍然对用户可见时(如右图),它处于暂停状态。即在它之上有另外一个Activity。这个Activity也许是透明的,或者没有完全覆盖全屏,所以被暂停的Activity仍对用户可见。暂停的Activity仍然是存活状态(它保留着所有的状态和成员信息并保持和窗口管理器的连接),但系统处于极低内存时仍然可以杀死这个Activity。

l   完全被另一个Activity覆盖时则处于停止状态。它仍然保留所有的状态和成员信息。然而对用户是不可见的,所以它的窗口将被隐藏,如果其它地方需要内存,则系统经常会杀死这个Activity。

当Activity从一种状态转变到另一种状态时,会调用以下保护方法来通知这种变化:

void onCreate(Bundle savedInstanceState)

void onStart()

void onRestart()

void onResume()

void onPause()

void onStop()

void onDestroy()

 

这七个方法定义了Activity的完整生命周期。实现这些方法可以帮助我们监视其中的三个嵌套生命周期循环:

l   Activity的完整生命周期自第一次调用onCreate()开始,直至调用onDestroy()为止。Activity在onCreate()中设置所有“全局”状态以完成初始化,而在onDestroy()中释放所有系统资源。例如,如果Activity有一个线程在后台运行从网络上下载数据,它会在onCreate()创建线程,而在 onDestroy()销毁线程。

l   Activity的可视生命周期自onStart()调用开始直到相应的onStop()调用结束。在此期间,用户可以在屏幕上看到Activity,尽管它也许并不是位于前台或者也不与用户进行交互。在这两个方法之间,我们可以保留用来向用户显示这个Activity所需的资源。例如,当用户不再看见我们显示的内容时,我们可以在onStart()中注册一个BroadcastReceiver来监控会影响UI的变化,而在onStop()中来注消。onStart() 和 onStop() 方法可以随着应用程序是否为用户可见而被多次调用。

l   Activity的前台生命周期自onResume()调用起,至相应的onPause()调用为止。在此期间,Activity位于前台最上面并与用户进行交互。Activity会经常在暂停和恢复之间进行状态转换——例如当设备转入休眠状态或者有新的Activity启动时,将调用onPause() 方法。当Activity获得结果或者接收到新的Intent时会调用onResume() 方法。关于前台生命周期循环的例子请见下方备注。

 

Activity的前台生命周期循环例子:

1》创建一个Activity,添加七个生命周期方法,方法内输出各个方法名称。再添加一个按钮用于打开下面新添加的Activity。

    startActivity(new Intent(LifeActivity.this, CustomDialogActivity.class));

2》添加一个新Activity,代码如下:

public class CustomDialogActivity extends Activity {

    @Override protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        //必须在调用setContentView()之前调用requestWindowFeature()

        requestWindowFeature(Window.FEATURE_LEFT_ICON);//要标题栏显示图标

        setContentView(R.layout.dialog_activity);      

        getWindow().setFeatureDrawableResource(Window.FEATURE_LEFT_ICON, android.R.drawable.ic_dialog_alert);//设置图标

    }

}

3》在AndroidManifest.xml文件配置Activity,并且通过主题指定该Activity以对话框样式显示。

 <application android:icon="@drawable/icon" android:label="@string/app_name" >

        .....

        <activity android:name=".CustomDialogActivity" android:label="对话框activity"

         android:theme="@android:style/Theme.Dialog"/>

 </application>

 

 

 

从Internet获取数据

利用HttpURLConnection对象,我们可以从网络中获取网页数据.

URL url = new URL("http://www.sohu.com");

HttpURLConnection conn = (HttpURLConnection) url.openConnection();

conn.setConnectTimeout(6* 1000);//设置连接超时

if (conn.getResponseCode() != 200) throw new RuntimeException("请求url失败");

InputStream is = conn.getInputStream();//得到网络返回的输入流

String result = readData(is, "GBK");

conn.disconnect();

System.out.println(result);

//第一个参数为输入流,第二个参数为字符集编码

public static String readData(InputStream inSream, String charsetName) throws Exception{

         ByteArrayOutputStream outStream = new ByteArrayOutputStream();

         byte[] buffer = new byte[1024];

         int len = -1;

         while( (len = inSream.read(buffer)) != -1 ){

                   outStream.write(buffer, 0, len);

         }

         byte[] data = outStream.toByteArray();

         outStream.close();

         inSream.close();

         return new String(data, charsetName);

}

利用HttpURLConnection对象,我们可以从网络中获取文件数据.

URL url = new URL("http://photocdn.sohu.com/20100125/Img269812337.jpg");

HttpURLConnection conn = (HttpURLConnection) url.openConnection();

conn.setConnectTimeout(6* 1000);

if (conn.getResponseCode() != 200) throw new RuntimeException("请求url失败");

InputStream is = conn.getInputStream();

readAsFile(is, "Img269812337.jpg");

public static void readAsFile(InputStream inSream, File file) throws Exception{

         FileOutputStream outStream = new FileOutputStream(file);

         byte[] buffer = new byte[1024];

         int len = -1;

         while( (len = inSream.read(buffer)) != -1 ){

                   outStream.write(buffer, 0, len);

         }

        outStream.close();

         inSream.close();

}

 

向Internet发送请求参数

利用HttpURLConnection对象,我们可以向网络发送请求参数.

String requestUrl = "http://localhost:8080/itcast/contanctmanage.do";

Map<String, String> requestParams = new HashMap<String, String>();

requestParams.put("age", "12");

requestParams.put("name", "中国");

 StringBuilder params = new StringBuilder();

for(Map.Entry<String, String> entry : requestParams.entrySet()){

         params.append(entry.getKey());

         params.append("=");

         params.append(URLEncoder.encode(entry.getValue(), "UTF-8"));

         params.append("&");

}

if (params.length() > 0) params.deleteCharAt(params.length() - 1);

byte[] data = params.toString().getBytes();

URL realUrl = new URL(requestUrl);

HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection();

conn.setDoOutput(true);//发送POST请求必须设置允许输出

conn.setUseCaches(false);//不使用Cache

conn.setRequestMethod("POST");        

conn.setRequestProperty("Connection", "Keep-Alive");//维持长连接

conn.setRequestProperty("Charset", "UTF-8");

conn.setRequestProperty("Content-Length", String.valueOf(data.length));

conn.setRequestProperty("Content-Type","application/x-www-form-urlencoded");

DataOutputStream outStream = new DataOutputStream(conn.getOutputStream());

outStream.write(data);

outStream.flush();

if( conn.getResponseCode() == 200 ){

        String result = readAsString(conn.getInputStream(), "UTF-8");

        outStream.close();

        System.out.println(result);

}

 

向Internet发送xml数据

利用HttpURLConnection对象,我们可以向网络发送xml数据.

StringBuilder xml =  new StringBuilder();

xml.append("<?xml version=\"1.0\" encoding=\"utf-8\" ?>");

xml.append("<M1 V=10000>");

xml.append("<U I=1 D=\"N73\">中国</U>");

xml.append("</M1>");

byte[] xmlbyte = xml.toString().getBytes("UTF-8");

URL url = new URL("http://localhost:8080/itcast/contanctmanage.do?method=readxml");

HttpURLConnection conn = (HttpURLConnection) url.openConnection();

conn.setConnectTimeout(6* 1000);

conn.setDoOutput(true);//允许输出

conn.setUseCaches(false);//不使用Cache

conn.setRequestMethod("POST");        

conn.setRequestProperty("Connection", "Keep-Alive");//维持长连接

conn.setRequestProperty("Charset", "UTF-8");

conn.setRequestProperty("Content-Length", String.valueOf(xmlbyte.length));

conn.setRequestProperty("Content-Type", "text/xml; charset=UTF-8");

DataOutputStream outStream = new DataOutputStream(conn.getOutputStream());

outStream.write(xmlbyte);//发送xml数据

outStream.flush();

if (conn.getResponseCode() != 200) throw new RuntimeException("请求url失败");

InputStream is = conn.getInputStream();//获取返回数据

String result = readAsString(is, "UTF-8");

outStream.close();

 

广播接收者--BroadcastReceiver

广播接收者(BroadcastReceiver)用于异步接收广播Intent,广播Intent的发送是通过调用Context.sendBroadcast()、Context.sendOrderedBroadcast()或者Context.sendStickyBroadcast()来实现的。通常一个广播Intent可以被订阅了此Intent的多个广播接收者所接收,广播接收者和JMS中的Topic消息接收者很相似。要实现一个广播接收者方法如下:

第一步:继承BroadcastReceiver,并重写onReceive()方法。

public class IncomingSMSReceiver extends BroadcastReceiver {

         @Override public void onReceive(Context context, Intent intent) {

         }

}

第二步:订阅感兴趣的广播Intent,订阅方法有两种:

第一种:使用代码进行订阅

IntentFilter filter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");

IncomingSMSReceiver receiver = new IncomingSMSReceiver();

registerReceiver(receiver, filter);

第二种:在AndroidManifest.xml文件中的<application>节点里进行订阅:

<receiver android:name=".IncomingSMSReceiver">

    <intent-filter>

         <action android:name="android.provider.Telephony.SMS_RECEIVED"/>

    </intent-filter>

</receiver>

 

使用广播接收者窃听短信

 

如果你想窃听别人接收到的短信,达到你不可告人的目的,那么本节内容可以实现你的需求。

当系统收到短信时,会发出一个action名称为android.provider.Telephony.SMS_RECEIVED的广播Intent,该Intent存放了接收到的短信内容,使用名称“pdus”即可从Intent中获取短信内容。

public class IncomingSMSReceiver extends BroadcastReceiver {

private static final String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";

@Override public void onReceive(Context context, Intent intent) {

if (intent.getAction().equals(SMS_RECEIVED)) {

         SmsManager sms = SmsManager.getDefault();

         Bundle bundle = intent.getExtras();

         if (bundle != null) {

         Object[] pdus = (Object[]) bundle.get("pdus");

         SmsMessage[] messages = new SmsMessage[pdus.length];

         for (int i = 0; i < pdus.length; i++) messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);

                   for (SmsMessage message : messages){

                            String msg = message.getMessageBody();

                            String to = message.getOriginatingAddress();

                            sms.sendTextMessage(to, null, msg, null, null);

}}}}}

在AndroidManifest.xml文件中的<application>节点里对接收到短信的广播Intent进行订阅:

<receiver android:name=".IncomingSMSReceiver">

<intent-filter><action android:name="android.provider.Telephony.SMS_RECEIVED"/></intent-filter></receiver>

在AndroidManifest.xml文件中添加以下权限:

<uses-permission android:name="android.permission.RECEIVE_SMS"/><!-- 接收短信权限 -->

<uses-permission android:name="android.permission.SEND_SMS"/><!-- 发送短信权限 -->

 

广播接收者

除了短信到来广播Intent,Android还有很多广播Intent,如:开机启动、电池电量变化、时间已经改变等广播Intent。

l   接收电池电量变化广播Intent ,在AndroidManifest.xml文件中的<application>节点里订阅此Intent:

<receiver android:name=".IncomingSMSReceiver">

    <intent-filter>

         <action android:name="android.intent.action.BATTERY_CHANGED"/>

    </intent-filter>

</receiver>

l   接收开机启动广播Intent,在AndroidManifest.xml文件中的<application>节点里订阅此Intent:

<receiver android:name=".IncomingSMSReceiver">

    <intent-filter>

         <action android:name="android.intent.action.BOOT_COMPLETED"/>

    </intent-filter>

</receiver>

并且要进行权限声明:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

 

通常一个BroadcastReceiver对象的生命周期不超过5秒,所以在BroadcastReceiver里不能做一些比较耗时的操作,如果需要完成一项比较耗时的工作,可以通过发送Intent给Activity或Service,由Activity或Service来完成。

public class IncomingSMSReceiver extends BroadcastReceiver {

         @Override public void onReceive(Context context, Intent intent) {

            //发送Intent启动服务,由服务来完成比较耗时的操作

            Intent service = new Intent(context, XxxService.class);

            context.startService(service);

            //发送Intent启动Activity,由Activity来完成比较耗时的操作

            Intent newIntent = new Intent(context, XxxActivity.class);

            context.startActivity(newIntent);

         }

}

 

 

 

 

 

 

 

 

 

转载于:https://www.cnblogs.com/sanic/archive/2011/12/20/2294568.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值