顯示具有 BroadcastReceiver 標籤的文章。 顯示所有文章
顯示具有 BroadcastReceiver 標籤的文章。 顯示所有文章

2012年4月1日 星期日

[TQC+ Android] 3-4 接收簡訊 Use SmsMessage , BroadcastReceiver





設計接收簡訊程式 , 以DDMS模擬產生一則簡訊 , 簡訊送達時使用Toast 顯示傳送者電話及簡訊內容 , 這題實作的技巧其實在之前的文章 [TQC+ Android] 3-2 接收SMS Use BroadcastReceiver, SmsMessage, onNewIntent 都講完了 , 而且這題只是單純的顯示接收到的簡訊內容 , 記得註冊user-permission 和 "android.provider.Telephony.SMS_RECEIVED" , 相當的簡單 , 以下是程式碼。


package COM.TQC.GDD03;

import android.app.Activity; 
import android.os.Bundle; 
import android.widget.TextView; 

public class GDD03 extends Activity 
{ 
  private TextView mTextView1; 
  /** Called when the activity is first created. */ 
  @Override 
  public void onCreate(Bundle savedInstanceState) 
  { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 
     
    mTextView1 = (TextView) findViewById(R.id.myTextView1); 
    mTextView1.setText("等待接收簡訊..."); 
  }
}
這是一個等待簡訊進來的 main Activity。






接下來是 GDD03_SM_Receiver.java , 是用來等待簡訊事件的


package COM.TQC.GDD03 ;

import java.util.Set;

import android.content.BroadcastReceiver; 
import android.content.Context; 
import android.content.Intent; 
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.util.Log;
import android.widget.Toast;



public class GDD03_SM_Receiver extends BroadcastReceiver 
{ 
 
  @Override 
  public void onReceive(Context context, Intent intent) 
  { 
    // TODO Auto-generated method stub 
    
    Toast t = Toast.makeText(context, "", Toast.LENGTH_LONG);
   
 if(intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED"))
    {     
  Bundle bundle = intent.getExtras();
  
  //檢查一下返回的Bundle裡面有哪些的資訊, 檢查Key
  Set KeySet = bundle.keySet();
     
     for(String s : KeySet)
     {
        Log.d("We have key elements", "Key:"+s);
     }
          
  Object messages[] = (Object[]) bundle.get("pdus");
  SmsMessage[] smsMessage = new SmsMessage[messages.length];
  for (int n = 0; n < messages.length; n++)
  {
   smsMessage[n] = SmsMessage.createFromPdu((byte[]) messages[n]);
      //將原始的PDU格式的資料轉為smsMessage的格式, 由於傳入的簡訊由於長度的限制可能不止一封
  }
  
     t.setText("接收到來自:"+smsMessage[0].getOriginatingAddress()+"\n----傳來的簡訊----\n"+smsMessage[0].getDisplayMessageBody());
     t.show();
    }
    else
    {
     t.setText(intent.getAction());
     t.show();
    }   
  } 
} 






最後別忘了 AndroidManifest.xml

    
    
        
            
                
                
            
        
        
            
                
            
        
    
    
 






P.S. 題目中所要求的Variable和Method皆會保留 , 也會根據題目所要求的流程去實作 , 縱使題目要求繞遠路....



2012年3月31日 星期六

[TQC+ Android] 3-2 接收SMS Use BroadcastReceiver, SmsMessage, onNewIntent







設計接收SMS的程式, 程式一執行時顯示 "Waiting SMS", 在接收到由DDMS傳送的簡訊之後, 即會將儲存於本機內的圖片顯示於畫面上。現在來說明一下整個完成這項功能的處理流程, 首先進入Main Activity等待SMS 的訊息, 而我們已經在AndroidManifest.xml 靜態的註冊了一個BroacastReceiver 名稱為 SMSreceiver 它的功用是在處理System接收SMS的Action 發生
  
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>


而SMSreceiver收到了receive SMS action之後就會啟動Image activity, 並把簡訊內容和電話號碼的資訊傳給它, 而根據題目的要求, 當Image被啟動的時候使用的Image圖片是交替顯示的, 並且請使用者預先在res/drawable 資料夾底下分別載入sdk.png 和 android_118.png , 以下是程式碼的部分。


package COM.TQC.GDD03;

import android.app.Activity;
import android.os.Bundle;


public class GDD03 extends Activity
{
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);        
    }
}


這個Activity很簡單, 就是一個mian Activity, 他的layout檔只放了一個TextView所以就不特別附上 ,下面要貼的是Image Activity的layout , 也相當的簡單。







接著是SMSreceiver class 它是一個BroadcastReceiver, 功能就是當有SMS傳進來時, 從簡訊中取得來電號碼和簡訊內容將它們放入 intent並啟動Image.class, 先來看看程式碼。
package COM.TQC.GDD03;


import java.util.Set;
import android.content.BroadcastReceiver; 
import android.content.Context; 
import android.content.Intent; 
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.util.Log;


public class SMSreceiver extends BroadcastReceiver
{
 @Override 
   public void onReceive(Context context, Intent intent) 
   {       
    SmsMessage[] smsMessage = null;
      
      //先判斷這個intent是不是簡訊傳入的action
   if(intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED"))
      {       
    Bundle bundle = intent.getExtras();
    
    //檢查一下返回的Bundle裡面有哪些的資訊, 檢查Key
    Set KeySet = bundle.keySet();
       
       for(String s : KeySet)
       {
          Log.d("We have key elements", "Key:"+s);
       }
              
    Object messages[] = (Object[]) bundle.get("pdus");
    smsMessage = new SmsMessage[messages.length];
    for (int n = 0; n < messages.length; n++)
    {
     smsMessage[n] = SmsMessage.createFromPdu((byte[]) messages[n]);
        //將原始的PDU格式的資料轉為smsMessage的格式, 由於傳入的簡訊由於長度的限制可能不止一封
    }
      }      
   
   Intent NewIntent = new Intent();
   NewIntent.setClass(context, Image.class);
   //指定目的地Activity
   
   NewIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
   //如果是由非Activity來啟動另一個Activity, 需要加入這個flag
   
   NewIntent.putExtra("Phone", smsMessage[0].getOriginatingAddress());
   //取出來電號碼, 因為輸入的訊息長度不會拆成多封簡訊所以這邊我只取第一封, 或許可以再做更嚴謹的判斷
   
   NewIntent.putExtra("Message", smsMessage[0].getDisplayMessageBody());
   //取出簡訊內容
   
   context.startActivity(NewIntent);
     
   } 
}





再來是被SMSreceiver 呼叫的 Image.java
package COM.TQC.GDD03;

import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.widget.ImageView;
import android.widget.TextView;


public class Image extends Activity 
{    
 Intent intent;
 int count;
 TextView tv;
 ImageView iv;
 
 /** Called when the activity is first created. */
 
 @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.image);
        
        intent = this.getIntent();
        handleIntent(intent);
        //將intent 送去handleIntent將newIntent中的資訊取出顯示
    }
 
 @Override
 protected void onNewIntent(Intent newIntent)
 {
  // TODO Auto-generated method stub
    
  super.onNewIntent(newIntent);    
  Log.d("Test","onNewIntent()");
  //如果Activity已經存在的話, 系統會將intent發送給 onNewIntent(), 而不是再去 call onCreate()
  
  setIntent(newIntent);
  //告知將換成newIntent
  
     handleIntent(newIntent);
     //將newIntent 送去handleIntent將newIntent中的資訊取出顯示
 }
 
 private void handleIntent(Intent intent)
 {
  tv = (TextView) this.findViewById(R.id.TextView1);
  iv = (ImageView) this.findViewById(R.id.imageView1);
  
  Bundle bundle = intent.getExtras();  
  SharedPreferences sPreferences = this.getSharedPreferences("SMSCount", MODE_PRIVATE);
  
  tv.setText("電話號碼:"+ bundle.getString("Phone") +", SMS內容:"+bundle.getString("Message"));
  count = sPreferences.getInt("Count", 0);
  Log.d("Test","Count:"+count);  
  
  if(count%2==0) iv.setImageResource(R.drawable.android_118);
  else iv.setImageResource(R.drawable.sdk);
  count++;
  //處理圖片交替顯示的部分
  
  sPreferences.edit().putInt("Count", count).commit();
  
 }
 
/*  另一個不要重複產生Instance的方法是在切換到另一個Activity之前
           在onStop()就call finish() destroy Instance
      
 @Override
 protected void onStop()
 {
  // TODO Auto-generated method stub    
    
  super.onStop();
  this.finish();
 } 
*/
}


當BroadcastReceiver每收到一個SMS的訊息, 它就會startActivity一次(也就是create Instance), 而這樣一來當我們沒有按下Back鍵回到main Activity, 而又收到SMS的話, 在Activity stack中就會產生多個 Image Activity, 這種情況顯然不是我們想見到的, 為了處理這種情況, 有簡單的兩種方法, 


1. 在onStop()的時候finish() 當前的Activity, 因為onStop() method 不管在我們按下Back鍵, 或是被強行跳出到新的Image Activity之前都會被執行的method。


2. 在AndoridManifest.xml中宣告Image Activity的lauchMode為singleTop, 因為singleTop的屬性規則是如果此Activity已經產生在Top of Activity stack的話, system就不會再替他create instance, 實際上只是不去call onCreate() method, 取而代之的是call onNewIntent() method, 所以我們要在程式中override onNewIntent() method, 把設定圖片來源的code 在這邊處理。




最後是AndroidManifest.xml的部分

    
    
        
            
                
                
            
        
                    
        
        
            
                
            
        
    
    
 


這邊要注意的地方就是先前提到的記得幫 Image Activity宣告lauchMode:singleTop, 另外還要幫SMSreceiver 在intent-filter中宣告 <action android:name="android.provider.Telephony.SMS_RECEIVED"/> , 最後別忘記因為我們會讀取到簡訊的內容, 所以記得別忘了user-permission: <uses-permission android:name="android.permission.RECEIVE_SMS"/>









P.S. 題目中所要求的Variable和Method皆會保留 , 也會根據題目所要求的流程去實作 , 縱使題目要求繞遠路....



2010年10月26日 星期二

[Android] 如何在桌面建立捷徑圖示 (1.Launcher 的 BroadcastReceiver)



這幾天在找關於建立捷徑的資料 , 從中歸類出兩種方法 , 首先是第一種透過Launcher
的BroadcastReceiver 的方法建立快捷 , Launcher 為了讓其他應用程式能建立自己的捷
所以就註冊了一個BroadcastReceiver 專門接收其他應用程式發出的建立捷徑訊息
下面是Launcher的AndroidManifest.xml文件中Install-ShortcutReceiver的註冊訊息


 

 
 


接下來我們就要宣告並發送一個用來告知Launcher要建立桌面捷徑的Intent , 不過首先我
從Launcher那取得權限 , 權限名稱宣告如下:

private static final String INSTALL_SHORTCUT = "com.android.launcher.action.INSTALL_SHORTCUT";



接著我們需要宣告一個Intent , 用他來告知Launcher建立桌面捷徑 , 而對於這一個用來
Creates a shortcut 的Intent來說 , 他必須包含三個資訊 , 下面是Android Reference


Activity Action: Creates a shortcut.
Input: Nothing.
Output: An Intent representing the shortcut. The intent must contain three extras: 
SHORTCUT_INTENT (value: Intent), 
SHORTCUT_NAME (value: String),
SHORTCUT_ICON (value: Bitmap) or SHORTCUT_ICON_RESOURCE (value: ShortcutIconResource).


程式碼實作如下:

public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        Intent shortcutIntent = new Intent(INSTALL_SHORTCUT);
        
        // 如果宣告的Intent是用來建立桌面捷徑的話
        // 必須在Intent中加入名稱 , 圖示 , 要執行的動作
        // 所以此時 shortcutIntent.putExtra 分別載入
        // 上面所需要的三個資訊          
       
     
     shortcutIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME,getString(R.string.app_name));
        shortcutIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE,Intent.ShortcutIconResource.fromContext(this,R.drawable.logo));
        //可以用 SHORTCUT_ICON (value: Bitmap)代替
        
        shortcutIntent.putExtra("duplicate", false);
        // 如果桌面上已經存在了之前建立的捷徑
        // 那麼參數false代表不能再建立相同的捷徑
        // 預設為true , 代表允許重複建立捷徑
        // 網路上有人使用 putExtra(EXTRA_SHORTCUT_DUPLICATE, false);
        // 我是使用Android 2.2的版本 , EXTRA_SHORTCUT_DUPLICATE 似乎已經被移除了
        // 所以使用 "duplicate" 代替
        
        
        Intent TaskIntent = new Intent();
        // 這邊宣告的Intent代表要執行動作
        
        TaskIntent.setComponent(new ComponentName(this.getPackageName(),".ShortcutTest"));        
        // 執行主程式
        
        shortcutIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT,TaskIntent);
        sendBroadcast(shortcutIntent);
        // 通知Launcher
    }


另外也別忘了在AndroidManifest.xml要加上uses-permission的標籤




成功之後就會出現以下的結果




                                當成功產生捷徑的時候 , 會有一個Toast訊息





接著可以看到桌面多出了一個Shortcut的捷徑!!!!


點擊捷徑就可以執行我們的主程式了 , 另外如果想把捷徑當作快速撥號的話 , 只要稍作修改如下
Intent TaskIntent = new Intent(Intent.ACTION_CALL,Uri.parse("tel://119"));
//撥號動作 , 打119


相關文章:
[Android] 如何在桌面建立捷徑圖示 (2.接受Intent.ACTION_CREATE_SHORTCUT動作)

Google Analytics