Android自動開閉機が実現


Androidの自動シャットダウンについては、インターネット上で多くのアプリケーションや例があります。自動起動に対して、自動シャットダウンはアプリケーション層にalarmを設定することによって実現されます。自動起動して、ネット上の紹介は比較的に少なくなりました。この間、お客様のニーズに合わせて自動開閉機を実現しました。ここで共有します。
1.概要
私の実現は設定プログラムにインターフェースを追加して、ユーザーに自動開閉機をセットさせます。この自動開閉機の設定は目覚まし時計の設定を参照してもいいです。自動シャットダウンについては、シャットダウンを考慮して、ユーザが重要な操作をしている可能性があります。今のシャットダウンをキャンセルする機会をユーザーに与えるべきです。
1)BroadcastReceiver一つは、次のような情報を受信する。
a)カスタムACT ION_REQUST_POWER_OFF:aut power offを設定する場合、AlarmManagerで設定したRTC_WAKEUP時計。設定されたシャットダウン時間になると、前にAlarmManagerに設定されたこのアクションが放送されます。私たちが実現したこのBroadcastReceiverはこのメッセージを受信した後、パワーオフプロセスを開始します。
b) カスタムACT ION_REQUST_POWER_ON:aut power onを設定する場合、AlarmManagerで設定したRTC_WAKEUP時計。私たちはパワーオンがRTCを設定するべきだと知っています。WAKEUPのalarmは何をしていますか?実際には、ユーザーが自動的にオフに設定した時、私は2つのクロックを設定しました。一つはRTCクロックで、オフの状態で起動します。もう一つはこのRTC_です。WAKEUP時計。この時計をセットしたのは、月曜日から金曜日まで毎日7時半に自動的に起動します。木曜日の朝7時に携帯電話を開けました。このように7時半までに設定した時計は期限が切れます。再設定しないと、金曜日の朝は自動的に起動しません。だからこの時、前に設置したRTC_WAKEUPはこのような情報を受け取って、次回の自動起動の時計を再設定します。
c)BOOT_COMPLETEとTIMEZONE change、Time setなどの時間に関するaction:システムの起動が完了した時や時間、タイムゾーンが変更された時に、再度alarmを設定する必要があります。
2)1つの処理パワーオフのServiceは、BroadcastReceiverがACT ION_を受信したときに、REQUST_POWER_OFFして、私達はユーザーに現在の自動シャットダウンをキャンセルする機会を与えます。このサービスの役割は背景のないページを起動し、ユーザーに提示することです。同時に再生する前にユーザが設定したメッセージ音や振動があります。
3)一つのActivity:dialogがユーザーに自動的にシャットダウンするように指示し、タイマーでカウントダウンします。ユーザがシャットダウンを確認したり、タイマーが時間になったらシャットダウンします。現在のシャットダウンをキャンセルし、次回の自動シャットダウンをリセットします。
2.自動シャットダウンの実現。自動シャットダウンの実現は比較的簡単です。ここでは主にalarmの設定とシャットダウンの実現について説明します。
1)自動シャットダウンのalarmを設定する:
 
    AlarmManager am = (AlarmManager) context
                .getSystemService(Context.ALARM_SERVICE);

        Intent intent = new Intent(
                "com.android.settings.action.REQUEST_POWER_OFF");

        PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0,
                intent, PendingIntent.FLAG_CANCEL_CURRENT);
        am = (AlarmManager) context
                .getSystemService(Context.ALARM_SERVICE);
        am.set(AlarmManager.RTC_WAKEUP, time, pendingIntent);
2)自動的にシャットダウンしたのは。/fram eworks/base/services/java/com/android/server/Shutdown Activity.java:
        Intent newIntent = new Intent(Intent.ACTION_REQUEST_SHUTDOWN);
        newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(newIntent);
Intent.ACT ION_REQUST_SHUTDOWNはIntentの隠れたactionです。
 
3.自動起動の実現。上層アプリケーションとframe ebookをずっと作っていますが、下の階はよく分かりません。ちょうど同僚がいます。前にオフのベルを作ったので、彼の前の実現を少し変えてもいいです。システムpower offの状態で自動的に起動します。私たちはETCクロックを設定したいです。ユーザーが自動起動を設定すると、AlarmManagerServiceによって時計を設定していきます。この学は底辺の支持が必要です。ここでの実現は私達自身のrtc alarm typeを定義することです。
1) まず最初にヘッダファイルで定義します。
a) ケネル/include/linux/android_alarm.h
#define ANDROID_ALARM_GET_TIME(type)        ALARM_IOW(4, type, struct timespec)
#define ANDROID_ALARM_SET_RTC               _IOW('a', 5, struct timespec)

/* we define ANDROID_RTC_ALARM_SET for auto power off */
#define ANDROID_RTC_ALARM_SET               _IOW('a', 7, int)

#define ANDROID_ALARM_BASE_CMD(cmd)         (cmd & ~(_IOC(0, 0, 0xf0, 0)))
b) bionic/libc/ケネル/common/linux/android_alarm.h
#define ANDROID_RTC_ALARM_SET _IOW('a', 7, int)
2) 定義が完了したら、さらに実現が必要です。ケネル/drivers/rtc/alarm-dev.cファイルのalarm_ioctlメソッドに、caseを追加し、alarmを設定することができます。
    case ANDROID_RTC_ALARM_SET:
        {
            unsigned int rtc_alarm_time;
            struct rtc_time rtc_now;
            if (copy_from_user(&rtc_alarm_time, (void __user *)arg,
                sizeof(rtc_alarm_time))) {
                rv = -EFAULT;
                goto err1;
            }
            if (pmic_rtc_get_time(&rtc_now) < 0) {
                rtc_now.sec = 0;
                if (pmic_rtc_start(&rtc_now) < 0) {
                    printk("get and set rtc info failed
"); break; } } pmic_rtc_disable_alarm(PM_RTC_ALARM_1); rtc_now.sec += rtc_alarm_time; pmic_rtc_enable_alarm(PM_RTC_ALARM_1, &rtc_now); break; }
もちろん忘れないでください。includeを追加します。
#include <mach/pmic.h>
3)フレームワーク/base/services/jni/com_android_server_AlarmManager Service.cppに時計をセットする方法を追加しました。
static void android_server_AlarmManagerService_updateRtcAlarm(JNIEnv* env, jobject obj, jint fd, jint seconds)
{
#if HAVE_ANDROID_OS
    int result = ioctl(fd, ANDROID_RTC_ALARM_SET, &seconds);
    LOGE("set rtc alarm to %d later: %s
", seconds, strerror(errno)); if (result < 0) { LOGE("Unable to set rtc alarm to %d later: %s
", seconds, strerror(errno)); } #endif }
そしてインターフェースを定義することを忘れないでください。
{"updateRtcAlarm", "(II)V", (void*)android_server_AlarmManagerService_updateRtcAlarm},
4) frame eworks/base/services/java/com/android/server/AlarmManagerService.javaでは、nativeの設定alarmを定義する方法を定義しています。呼出すれば、自動的にシャットダウンされるalarm設定が可能です。
定義:prvate native void udateRtcAlarm(int fd,int seconds);
呼び出し:
    public void setRepeating(int type, long triggerAtTime, long interval, 
            PendingIntent operation) {
        if (operation == null) {
            Slog.w(TAG, "set/setRepeating ignored because there is no intent");
            return;
        }
        synchronized (mLock) {
            Alarm alarm = new Alarm();
            alarm.type = type;
            alarm.when = triggerAtTime;
            alarm.repeatInterval = interval;
            alarm.operation = operation;

            // Remove this alarm if already scheduled.
            removeLocked(operation);

            if (localLOGV) Slog.v(TAG, "set: " + alarm);

            int index = addAlarmLocked(alarm);
            if (index == 0) {
                setLocked(alarm);
            }

            // Start to setup auto power on alarm
            if ((alarm.type == AlarmManager.ELAPSED_REALTIME_WAKEUP) && 
                                alarm.operation.getTargetPackage().equals("com.android.settings")) {
                updateRtcAlarm(mDescriptor, (int)((alarm.when - System.currentTimeMillis()) / 1000));
            }
            // End to setup auto power on alarm
        }
    }
5)アプリケーション層に自動起動を設定する
        AlarmManager am = (AlarmManager) context
                .getSystemService(Context.ALARM_SERVICE);
        Intent intent = new Intent(
                "com.android.settings.action.REQUEST_POWER_ON");
        PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0,
                intent, PendingIntent.FLAG_CANCEL_CURRENT);
        am = (AlarmManager) context
                .getSystemService(Context.ALARM_SERVICE);
        am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, time, pendingIntent);
4.まとめ
1)自動起動の原理は簡単ですが、下の階のサポートが必要ですので、応用やフレームワーク層の技術者にとっては、実現がちょっと面倒です。2)自動開閉機を設置する時、考慮すべきことが多いです。例えば、時間/時間帯の変更、携帯は電源を入れるかそれとも電源を切るかなどです。