PendingIntentとAlarmManagerについて検証してみる

Android

使ってみないとよくわからない機能の一つがPendingIntentですよね。
今回は、アラームなどでよく利用するPendingIntentで、忘れてしまったことやちょっとわかりにくいことが個人的にあったので、記録しておきます。

次のようなサンプルコードを用意します。

 //AlarmTestActivity.java
 public class AlarmTestActivity extends Activity {
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_aram_test);
 
        String type = "ON";
        PendingIntent alarmSender = getPendingIntent(4, type);
 
        // アラーム時間設定
        Calendar cal = Calendar.getInstance();
 
        // 設定した時刻をカレンダーに設定
        cal.set(Calendar.HOUR_OF_DAY, 12);
        cal.set(Calendar.MINUTE, 02);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
 
 
        AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), alarmSender);
        } else {
            am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), alarmSender);
        }
 
 
        // アラーム時間設定 2
        Calendar cal2 = Calendar.getInstance();
 
        // 設定した時刻をカレンダーに設定
        cal2.set(Calendar.HOUR_OF_DAY, 12);
        cal2.set(Calendar.MINUTE, 05);
        cal2.set(Calendar.SECOND, 0);
        cal2.set(Calendar.MILLISECOND, 0);
 
       /* SimpleDateFormat df2 = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
        Date alarm_day2 = cal2.getTime();
        String alarmDate2 = df2.format(alarm_day2);
        Log.d("AramTestActivity", alarmDate2);*/
 
        AlarmManager am2 = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            am2.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, cal2.getTimeInMillis(), alarmSender);
        } else {
            am2.set(AlarmManager.RTC_WAKEUP, cal2.getTimeInMillis(), alarmSender);
        }
 
 
    }
 
 
     public PendingIntent getPendingIntent(int i, String type) {
 
        Intent intent = new Intent(this, AlarmReceiver.class);
        intent.putExtra("type", type);
 
        // アラーム時に起動するアプリケーションを登録
        PendingIntent pendingIntent = null;
        if (type.equals("ON")) {
 
            pendingIntent = PendingIntent.getBroadcast(this,
                    10000 + i,
                    intent, PendingIntent.FLAG_UPDATE_CURRENT);
 
        } 
 
        return pendingIntent;
    }
 
 }
 //AlarmReceiver.java
 public class AlarmReceiver extends BroadcastReceiver {
 
    private final static String TAG = "AlarmReceiver"; 
    
    @Override
    public void onReceive(Context context, Intent i) {
 
        try {
            
            Bundle extras = i.getExtras();
            String type = extras.getString("type");
            Log.d(TAG, "AlarmReceiver起動");
            
            if(type != null){
             
                Intent intent = null;
                if(type.equals("ON")){
     
                    intent = new Intent(context, LocationUpdateAlwaysService.class);
    
                }
            
            }
            
        } catch (Exception e) {
            
            Log.d(TAG, "エラー" + e);
        
        }
 
    }
 
 }

12時2分と12時5分にAlarmReceiverが動作しそうですが、しません。
この場合は、5分のやつだけ動作します。
時間を逆にしてみたらどうでしょうか。
先に5分のやつ、次に2分のやつに順序を変更してみます。

       PendingIntent alarmSender = getPendingIntent(4, type);
 
        // アラーム時間設定
        Calendar cal = Calendar.getInstance();
 
        // 設定した時刻をカレンダーに設定
        cal.set(Calendar.HOUR_OF_DAY, 12);
        cal.set(Calendar.MINUTE, 05);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
 
        AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), alarmSender);
        } else {
            am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), alarmSender);
        }
 
       // PendingIntent alarmSender2 = getPendingIntent(4, type);
 
        // アラーム時間設定
        Calendar cal2 = Calendar.getInstance();
 
        // 設定した時刻をカレンダーに設定
        cal2.set(Calendar.HOUR_OF_DAY, 12);
        cal2.set(Calendar.MINUTE, 02);
        cal2.set(Calendar.SECOND, 0);
        cal2.set(Calendar.MILLISECOND, 0);
 
        AlarmManager am2 = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            am2.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, cal2.getTimeInMillis(), alarmSender);
        } else {
            am2.set(AlarmManager.RTC_WAKEUP, cal2.getTimeInMillis(), alarmSender);
        }

この場合は、2分のやつだけ動作します。

PendingIntentのフラグに

 PendingIntent.FLAG_ONE_SHOT

を設定しても、動作は同じです。
上書き設定された方が動作するわけですね。

       String type = "ON";
        PendingIntent alarmSender = getPendingIntent(4, type);
 
        // アラーム時間設定
        Calendar cal = Calendar.getInstance();
 
        // 設定した時刻をカレンダーに設定
        cal.set(Calendar.HOUR_OF_DAY, 12);
        cal.set(Calendar.MINUTE, 05);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
 
        AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), alarmSender);
        } else {
            am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), alarmSender);
        }
 
        //これが新しいPendingIntent
        PendingIntent alarmSender2 = getPendingIntent(4, type);
 
        Calendar cal2 = Calendar.getInstance();
 
        // 設定した時刻をカレンダーに設定
        cal2.set(Calendar.HOUR_OF_DAY, 12);
        cal2.set(Calendar.MINUTE, 02);
        cal2.set(Calendar.SECOND, 0);
        cal2.set(Calendar.MILLISECOND, 0);
 
        AlarmManager am2 = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            am2.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, cal2.getTimeInMillis(), alarmSender2);
        } else {
            am2.set(AlarmManager.RTC_WAKEUP, cal2.getTimeInMillis(), alarmSender);
        } 

2番目のアラームは、違うPendingIntentを作成してみます。
PendingIntent alarmSender と PendingIntent alarmSender2 があります。
ただし、リクエストコードは4で一緒です。
これも、2分のものしか動作しません。
同じリクエストコードだと、上書きされちゃうんですね。

リクエストコードを変更します。

 PendingIntent alarmSender2 = getPendingIntent(5, type);

今度は2分のアラームも5分のアラームも動作します。

PHS(Willcom)カードが正常に動作しない

Windows Vista

Air EdgeのHONDA ELECTRON(現在ネットインデックス)製PCカード AH-H407PがVistaで認識されない。

メーカーのサイトにあるとおり、手動でドライバをインストールしたが「正常にインストールされない」となってしまう。
デバイスの状態をみると「エラーコード10」となってしまう。
パソコンの機種はHPのCompaq nx7300。

この問題はリソースの競合で発生するようです。
OSにてリソース値を振り当てているため、パソコン側でのリソース設定変更が必要です。
(競合が発生している機器を一時的に動作を止める、またはリソース値の変更等)

他機種での、コード10表示の対処方法記載を見て、対処しました。
http://h50221.www5.hp.com/CPO_TC/notepc/doc/NBQA000124.html

  1. デバイスマネージャーの[モデム]カテゴリ配下のご使用のPCカードのプロパティを開きます。
  2. [リソース]タブを開きます。
  3. [手動構成]ボタンが存在する場合はそれをクリックします。
  4. 自動設定のチェックを外します。
  5. “設定の登録名”のプルダウンメニューで、”基本構成0001″から順番に選択し、I/Oの範囲が 03E8-03EF になる構成を探します。
  6. I/Oの範囲が 03E8-03EF の構成に選択できましたら、IRQが 07 であることを確認します。
  7. IRQが 07 以外の場合は、IRQをクリックして[設定の変更]をクリックし、 値を 07 に変更してください。

[OK]をクリックしてプロパティを閉じます。
もし、上記設定で認識されない場合は、I/Oの範囲が 2E8-2EF 、IRQ 07 の設定でお試しください。

パソコンのメーカー・機種により解決方法が違いますので、パソコンメーカーに問い合わせてみるのがよいでしょう。

PHPエラー Deprecated Function …is deprecated

PHP

PHPエラー Deprecated:Function …is deprecated

PHP5.3

私の場合はPHP5.3にしたとたん

 
 Deprecated: Function set_magic_quotes_runtime() is deprecated in C:\xampp\htdocs\***.php on line 18

 Deprecated: Function ereg() is deprecated in C:\xampp\htdocs\***.php on line 18

が大量発生して困りました。

これは、Function ○○の部分の関数が、非推奨、廃止予定だよ、というエラーメッセージです。
とはいえ、古いプログラムをメンテナンスする際に、こういうものを全部置き換えるわけにいかないと思います。

とりあえず、このエラーを表示させないためにはphp.iniで

 error_reporting = E_ALL & ~E_DEPRECATED

と設定します。

それでもエラーが表示されるような場合は、プログラム内で

 error_reporting();

が設定されていないか、.htaccessで設定されていないか、見てみましょう。

PHPを無料で学べるwebサービスまとめ

PHP

初心者が使ってわかりやすそうなプログラミング学習サービスを厳選しました。

ドットインストール

プログラミング学習サイトと言えば、これみたいな存在。
プログラミングを動画で解説してくれ、さらに動画で解説したコードもすべて公開されているので、簡単に自分で試すことができます。
http://dotinstall.com/lessons/basic_php_beginner

Codeprep

サイト上で実際にコードを書きながら、初歩の初歩からPHPを学べます。
自分の書いたコードがリアルタイムで間違っているか正しいかチェックできるので便利で楽しい。
解説も行っているので、とてもわかりやすい。
http://codeprep.jp/

Codecademy

こちらもCodeprepと同じように、サイト上でコードを書くことができ、間違いを指摘してくれたりします。
しかし、一部日本語だけど、ほぼ英語と言っていいので英語が読めない方はできないと思います。
http://www.codecademy.com/