2012年4月16日月曜日

AndroidでiPhone風のスイッチを作る

普通のAndroidのToggleButtonを使ってもつまらないですね!

デザインならiPhoneが今のところ一番だと考えます。

なるべく近づけてみましょう。

論より証拠ということで以下のコードを参考にしてみてください。
←普通のToggleButton

←これがカスタマイズした後のToggleButton

手順は以下の通りです。
1、以下のコードをres/drawable/customtoggle.xmlとでもして保存して下さい。
2、backgroundプロパティに指定して下さい。
3、on textとoff textにそれぞれ半角スペースを指定して下さい。


<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
    <item android:state_checked="false">
        <layer-list>
            <item>
                <shape>
                    <size android:height="27dp" android:width="60dp" />

                    <gradient android:angle="270" android:centerColor="#c0c0c0" android:centerX="0.5" android:centerY="0.5" android:endColor="#c0c0c0" android:gradientRadius="10" android:startColor="#c0c0c0" android:type="linear" />

                    <corners android:radius="8dp" />

                    <solid android:color="#c0c0c0" />

                    <stroke android:width="1dip" android:color="#808080" />
                </shape>
            </item>
            <item android:left="30dp">
                <shape>
                    <size android:height="27dp" android:width="30dp" />
                    <corners android:radius="8dp" />
<gradient android:angle="270" android:centerColor="#B0C4DE" android:centerX="0.5" android:centerY="0.5" android:endColor="#778899" android:gradientRadius="10" android:startColor="#ADD8E6" android:type="linear" />


                    <stroke android:width="1dip" android:color="#808080" />
                </shape>
            </item>
            <item android:left="-30dp">
                <bitmap android:src="@drawable/off" android:gravity="center" />
            </item>
        </layer-list>
    </item>
    <item android:state_checked="true">
        <layer-list>
            <item>
                <shape>
                    <size android:height="27dp" android:width="60dp" />

                    <corners android:radius="8dp" />

                    <solid android:color="#ffffff" />

                    <stroke android:width="1dip" android:color="#808080" />
                </shape>
            </item>
            <item android:right="30dp">
                <shape>
                    <size android:height="27dp" android:width="30dp" />
<gradient android:angle="270" android:centerColor="#B0C4DE" android:centerX="0.5" android:centerY="0.5" android:endColor="#778899" android:gradientRadius="10" android:startColor="#ADD8E6" android:type="linear" />
                    <corners android:radius="8dp" />

                    <stroke android:width="1dip" android:color="#808080" />
                </shape>
            </item>
            <item android:right="-29dp">
                <bitmap android:src="@drawable/on" android:gravity="center" />
            </item>
        </layer-list>
    </item>

</selector>

2012年4月14日土曜日

Androidでアラームを作るための手順の例

ネットで「Android アラーム 開発」などとググるといろんな方が記事を書いています。

しかし、断片的なイメージが強かったのでまとめてみたいと思います。

■今回作成するアプリの概要
AlarmManagerを用いて、指定した時間後にアラーム通知画面が表示され、アラーム音を鳴らす

■手順
SampleActivity(アラーム設定画面とします)

(任意)MyAlarmManager(設定されたアラームを管理する独自クラス)

MyAlarmService(サービスを起動してブロードキャストメッセージを送ります)

MyAlarmNotificationReceiver(メッセージを受信して通知画面を起動します)

AlarmNotificationActivity(通知画面です)

■条件
1、スリープ画面であってもアラーム画面を表示する

■実装
まず、マニフェストファイルで設定しないといけない項目があります。
以下のXMLをAndroidManifest.xmlのapplicationタグ内の適切なところに配置します。
intent-filterで独自のメッセージ「"MyAlarmAction"」を受信するようにしてます。
------------------------------------------------------------------------------------------------
 <receiver android:name="MyAlarmNotificationReceiver">
            <intent-filter>
                <action android:name="MyAlarmAction"/>
            </intent-filter>
</receiver>
<service android:name="MyAlarmService"></service>
<activity android:name="AlarmNotificationActivity"></activity>
------------------------------------------------------------------------------------------------

以下の2行をmanifesstタグ直下に配置します。
これは、スリープ状態を解除するために必要な権限です。
------------------------------------------------------------------------------------------------ 
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>
------------------------------------------------------------------------------------------------

【SampleActivity.java】
アラームをセットするために必要なのは以下の2行だけです。
実行する場所はどこでもいいと思います。ボタンを押したタイミングなど...

今回はテストのため簡略化しています。
便宜上引数を設けた方がいいと思います。
MyAlarmManager mam = new MyAlarmManager(this);
mam.addAlarm();

【MyAlarmManager.java】
import java.util.Calendar;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

public class MyAlarmManager {
    Context c;
    AlarmManager am;
    private PendingIntent mAlarmSender;
   
    public MyAlarmManager(Context c){
    this.c = c;
    am = (AlarmManager)c.getSystemService(Context.ALARM_SERVICE);
    Log.v("MyAlarmManger","初期化完了");
    }
   
    public void addAlarm(/*今はなにもなしで*/){
    mAlarmSender = PendingIntent.getService(c, -1, new Intent(c, MyAlarmService.class), PendingIntent.FLAG_UPDATE_CURRENT);
    // アラーム時間設定
    Calendar cal = Calendar.getInstance();
    cal.setTimeInMillis(System.currentTimeMillis());
    cal.add(Calendar.MINUTE, 1);
    cal.set(Calendar.SECOND, 0);
    cal.set(Calendar.MILLISECOND, 0);
    Log.v("MyAlarmManagerログ",cal.getTimeInMillis()+"ms");
    am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), mAlarmSender);
    Log.v("MyAlarmManagerログ","アラームセット完了");
    }
}

【MyAlarmService.java】
Serviceを継承してます。

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

public class MyAlarmService extends Service {

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
    Log.v("MyAlarmServiceログ","Create");
    Thread thr = new Thread(null, mTask, "MyAlarmServiceThread");
    thr.start();
    Log.v("MyAlarmServiceログ","スレッド開始");
    }

    /**
     * アラームサービス
     */
    Runnable mTask = new Runnable() {
    public void run() {
        // ここでアラーム通知する前の処理など...

        Intent alarmBroadcast = new Intent();
        alarmBroadcast.setAction("MyAlarmAction");//独自のメッセージを送信します
        sendBroadcast(alarmBroadcast);
        Log.v("MyAlarmServiceログ","通知画面起動メッセージを送った");
        MyAlarmService.this.stopSelf();//サービスを止める
        Log.v("MyAlarmServiceログ","サービス停止");
    }
    };
}

【MyAlarmNotificationReceiver.java】
これは、サービスから送られて来たメッセージを受信する役割を担います。
今回はただ通知画面を起動するだけです。

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

public class MyAlarmNotificationReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
    Log.v("レシーバログ", "action: " + intent.getAction());
    Intent notification = new Intent(context,
        AlarmNotification.class);
    //ここがないと画面を起動できません
    notification.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    context.startActivity(notification);
    }

}

【AlarmNotificationActivity.java】
これが実際に表示されるアラーム通知画面です。
onStartでアラーム音を再生しています。
onDestroyでリソースを解放します。

import android.app.Activity;
import android.app.KeyguardManager;
import android.app.KeyguardManager.KeyguardLock;
import android.content.Context;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.util.Log;

public class AlarmNotification extends Activity {
    private WakeLock wakelock;
    private KeyguardLock keylock;

    MediaPlayer mp;

    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.alarm);
    Log.v("通知ログ", "create");
    // スリープ状態から復帰する
    wakelock = ((PowerManager) getSystemService(Context.POWER_SERVICE))
        .newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK
            | PowerManager.ACQUIRE_CAUSES_WAKEUP
            | PowerManager.ON_AFTER_RELEASE, "disableLock");
    wakelock.acquire();

    // スクリーンロックを解除する
    KeyguardManager keyguard = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
    keylock = keyguard.newKeyguardLock("disableLock");
    keylock.disableKeyguard();
    }

    @Override
    public void onStart() {
    super.onStart();
    if (mp == null)
        mp = MediaPlayer.create(this, R.raw.alarm);
    mp.start();
    }

    @Override
    public void onDestroy() {
    super.onDestroy();
    stopAndRelaese();
    }

    private void stopAndRelaese() {
    if (mp != null) {
        mp.stop();
        mp.release();
    }
    }
}


大まかにこんな感じでアラームが起動します。
必要に応じてコードは書き換えて下さい。
リソースファイルなどを用意していないと動きません。
コピペで動く保障はしません。

他にも手段はあります。
あくまでも一例としてみて頂ければと思います。

アドバイス、指摘などありましたらコメントをお願いいたします。