Sunday, January 13, 2019

Làm chuông báo thức

Điện thoại android có đồng hồ báo thức mặc định, nhưng ta muốn tự làm để có âm chuông báo theo ý muốn.
Tạo một file chuong.xml trong thư mục layout.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="280dp"
    android:layout_height="wrap_content"
    android:orientation="vertical" >
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="13dp"
         android:layout_gravity="center_horizontal"
        android:orientation="horizontal" >
        <TextView
            android:layout_width="40dp"
            android:layout_height="wrap_content"
            android:gravity="right"
            android:singleLine="true"
            android:textColor="#0C090A"
            android:textSize="13sp" />
        <Spinner
            android:id="@+id/spin"
            android:layout_width="98dp"
            android:layout_height="43dp"
            android:background="@drawable/bu3"
            android:singleLine="true"
          android:textAppearance="?android:attr/textAppearanceSmall" />
        <Spinner
            android:id="@+id/spin2"
            android:layout_width="98dp"
            android:layout_height="43dp"
            android:layout_marginLeft="1dp"
            android:background="@drawable/bu3"
            android:lineSpacingExtra="4dp"
            android:singleLine="true"
          android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
            android:id="@+id/t"
            android:layout_width="40dp"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:clickable="true"
            android:onClick="tatchuong"
            android:layout_marginLeft="1dp"
            android:singleLine="true"
            android:textColor="#0C090A"
            android:textSize="18sp" />
    </LinearLayout>
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="43dp"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="10dp"
        android:layout_gravity="center_horizontal" >
        <Button
            android:id="@+id/b1"
            android:layout_width="75dp"
            android:layout_height="42dp"
            android:background="@drawable/bu"
            android:text="OK"
            android:textColor="#0000cd"
            android:textSize="15sp" />
        <Button
            android:id="@+id/b2"
            android:layout_width="75dp"
            android:layout_height="42dp"
            android:layout_marginLeft="4dp"
            android:background="@drawable/bu"
            android:text="Cancel"
            android:textColor="#0000cd"
            android:textSize="15sp" />
    </LinearLayout>
</LinearLayout>
Thêm quyền vào file manifest.xml.
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.GET_TASKS" />
Khai báo service lên trên dòng </application> cuối cùng.
<service
       android:name=".service"
       android:enabled="true"
    android:exported="false" />
Khai báo class chuong nếu nó không phải là main(là main nó sẽ được tự động khai báo, chỉ thêm dòng Theme.Holo.Light vào)
<activity
 android:name=".chuong"       android:theme="@android:style/Theme.Holo.Light.Dialog.NoActionBar"
 android:screenOrientation="portrait">
</activity>
Khai báo vào file dimens.xml trong thẻ values.
<dimen name="he3">150dip</dimen>
<dimen name="he4">50dip</dimen>
Class service sẽ như sau.
public class service extends Service {
     String d = "Đang đặt chuông";
     private WindowManager wm;
     TextView mView;
     int til = 0;
     private MediaPlayer mediaPlayer;
     WindowManager.LayoutParams myParams;
     static IntentFilter s_intentFilter = new IntentFilter();
     static {
     s_intentFilter.addAction(Intent.ACTION_SCREEN_ON);
     s_intentFilter.addAction(Intent.ACTION_USER_PRESENT);
     }
     int dem = 0;
     int dachay = 0;
     int dachay2 = 0;
     private PowerManager pm;
      WakeLock wakeLock=null;
     public void onCreate() {
          super.onCreate();
          registerReceiver(ti, s_intentFilter);
          mediaPlayer = new MediaPlayer();
          mediaPlayer = MediaPlayer.create(this, R.raw.d);
          mediaPlayer.setLooping(true);
     }
     int con = 0;
     @Override
     public int onStartCommand(Intent intent, int flags, int startId) {
          // TODO
          int ki = intent.getIntExtra("to", 0);
          int ki2 = intent.getIntExtra("to2", 0);
          til = ki * 60 * 60 + ki2 * 60;
          String p = new Date().toString();
          p = p.trim();
          String a[] = p.split(" ");
          String a1[] = a[3].split(":");
          int ho = Integer.parseInt(a1[0]);
          int mi = Integer.parseInt(a1[1]);
          int se = Integer.parseInt(a1[2]);
          int pu2 = ho * 60 * 60 + mi * 60 + se;
          pu2 = pu2 * 1000;
          con = 86400000 - pu2;
          til = til * 1000;
          if (til>pu2) {
               con = til - pu2;
          } else {
               con = con + til;
          }
          set();
          mView = new TextView(this);
          //mView.setBackgroundResource(R.drawable.bu4);
          mView.setTextColor(Color.parseColor("#ffffff"));
          mView.setGravity(Gravity.CENTER);
          if(ki2==0){
               mView.setText(d+"\n"+ki+":"+ki2+"0");   
          }
          else{
          mView.setText(d+"\n"+ki+":"+ki2);  
          }
         
mView.setTextSize(android.util.TypedValue.COMPLEX_UNIT_DIP,
                     (float) 14.5);
     mView.setTypeface(null, Typeface.BOLD);
wm = (WindowManager) getSystemService(WINDOW_SERVICE);
          int ro = (int) getResources().getDimension(R.dimen.he3);
          int ro2 = (int) getResources().getDimension(R.dimen.he4);
          myParams = new WindowManager.LayoutParams(ro, ro2,
                     LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
                     LayoutParams.TYPE_SYSTEM_ERROR,
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
|WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                     /* | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON */,
                     PixelFormat.RGBA_8888);
myParams.gravity = Gravity.CENTER | Gravity.CENTER_VERTICAL;
     myParams.setTitle("Load Average");
     mView.setClickable(true);
     mView.setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View v) {
          Intent i = new Intent(getApplicationContext(),service.class);
          stopService(i);
               }
          });
     return Service.START_STICKY;
}

private final BroadcastReceiver ti = new BroadcastReceiver() {
     @Override
public void onReceive(Context context, Intent intent) {
          final String action = intent.getAction();
KeyguardManager myKM = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
     if (action.equals(Intent.ACTION_USER_PRESENT)) {
               if (dem == 1) {
                     wm.removeView(mView);
                     dem = 0;
                     dachay=0;
               }
          }
if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
     if (myKM.inKeyguardRestrictedInputMode()) {
          if (dem == 0) {
          wm.addView(mView, myParams);
          dem = 1;
          dachay=1;
               }
          }
     }
}
};
     @SuppressWarnings("deprecation")            
public void set() {
BroadcastReceiver receiver = new BroadcastReceiver() {
     @SuppressLint("Wakelock")
     @Override
public void onReceive(Context co, Intent i) {
pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK
|PowerManager.ACQUIRE_CAUSES_WAKEUP| PowerManager.ON_AFTER_RELEASE, "MyWakeLock");
          wakeLock.acquire();
          mediaPlayer.start();
          dachay2=1;
co.unregisterReceiver(this);             }
     };
this.registerReceiver(receiver, new IntentFilter("com.e.vidu"));
PendingIntent pintent = PendingIntent.getBroadcast(this, 0, new Intent("com.e.vidu"), 0);
AlarmManager manager = (AlarmManager) (this.getSystemService(Context.ALARM_SERVICE));
manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                     SystemClock.elapsedRealtime() + con, pintent);
}
@Override
public void onDestroy() {
     super.onDestroy();
     if (mediaPlayer != null) {
          mediaPlayer.stop();
          mediaPlayer = null;
     }
     if(dachay==1){
if (mView != null) {
((WindowManager) getSystemService(WINDOW_SERVICE))
                          .removeView(mView);
     mView = null;
     }
     }
if(dachay2==1){
     wakeLock.release(); 
          }
unregisterReceiver(ti);
}
@Override
public IBinder onBind(Intent intent) {
          // TODO Auto-generated method stub
return null;
}
}
Trong class này ta nhận thời gian chuyển sang và tính thời gian còn lại đến lúc bật chuông. Tạo một view nổi ở ngoài màn hình khóa, trên đó ghi thông báo đặt chuông và giờ đặt. Dùng broadcast để chờ, đến thời gian đặt thì bật màn hình lên, phát nhạc. Ta cũng set để nếu người dùng chạm vào view sẽ hủy chuông báo thức đi. Trong onDestroy() ta hủy các tác vụ tùy theo nó đã xảy ra chưa, xảy ra thì có biến đếm để xác định. Nếu ta không dùng cách này, khi mới đặt chuông xong mà hủy ngay, chưa gọi wakeLock mà đã hủy sẽ khiến app bị crash.
Tại class chính, khai báo lên trên Override onCreate()
Button b1,b2;
private ArrayAdapter<String> adapter,adap2;
private Spinner sp,sp2;
String[] data = {"1", "2","3","4", "5","6","7", "8","9","10","11","12", "13","14","15","16","17", "18","19","20","21","22", "23"};
     String[] data2 = {"00","10","20","30","40","50"};
int[] t = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23};
       int[] t2 = {0,10,20,30,40,50};
      int gio=6;
      int pu=0;
      TextView on;
      String van2="";
      String van="";
    Intent mIntent;
Thêm vào bên dưới setContentView(R.layout.chuong);
     on = (TextView) findViewById(R.id.t);
     sp = (Spinner) findViewById(R.id.spin);
     sp2 = (Spinner) findViewById(R.id.spin2);
     adapter=new customadapter(this, data,3);
     adap2=new customadapter(this, data2,3);
final SharedPreferences prefs = PreferenceManager
                      .getDefaultSharedPreferences(this);
     int vn = prefs.getInt("vi", 0);    
     int vn2 = prefs.getInt("vi2", 0);
     int vit=0;
     for (int i = 0; i <t2.length; i++) {
     if(vn2==t2[i]){
     vit=i;
     }
     }
     chay=isRunning(this);
          if(chay==true){
          on.setText("ON");
          on.setBackgroundColor(Color.GREEN);
          on.setTextColor(Color.WHITE);
          on.setTypeface(null, Typeface.BOLD);
           }
          else{
          on.setText("OFF");
          on.setTextColor(Color.RED);
          on.setBackgroundColor(Color.LTGRAY);    
         }
sp.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view,
     int position, long id) {             
     van=sp.getSelectedItem().toString();    
     for (int i = 0; i <data.length; i++) {
     if(van.equals(data[i])){
     gio=t[i];
     }
}   
final SharedPreferences.Editor edit = prefs.edit();
     edit.putInt("vi", gio);
     edit.putInt("vi2", pu);
     edit.commit();
     chay=isRunning(getApplicationContext());
     if(chay==true){
     Bundle mBundle = new Bundle();
     mBundle.putInt("to", gio);
     mBundle.putInt("to2", pu);
     mIntent.putExtras(mBundle);
     startService(mIntent);   
     }
     }
     @Override
     public void onNothingSelected(AdapterView<?> arg0) {
                     // TODO Auto-generated method stub

          }
     });
     sp.setAdapter(adapter);
     sp.setSelection(vn-1);
     sp2.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
          @Override
public void onItemSelected(AdapterView<?> parent, View view,
     int position, long id) {             
     van2=sp2.getSelectedItem().toString();
     for (int i = 0; i <data2.length; i++) {
          if(van2.equals(data2[i])){
               pu=t2[i];
          }
     }   
final SharedPreferences.Editor edit = prefs.edit();
          edit.putInt("vi", gio);
          edit.putInt("vi2", pu);
          edit.commit();
          chay=isRunning(getApplicationContext());
          if(chay==true){
          Bundle mBundle = new Bundle();
          mBundle.putInt("to", gio);
          mBundle.putInt("to2", pu);
          mIntent.putExtras(mBundle);
          startService(mIntent);   
                      }
               }
     @Override
public void onNothingSelected(AdapterView<?> arg0) {
                     // TODO Auto-generated method stub

     }
});
     sp2.setAdapter(adap2);
     sp2.setSelection(vit);
     mIntent = new Intent(chuong.this, service.class);
     b1 = (Button) findViewById(R.id.b1);
     b1.setOnClickListener(new View.OnClickListener() {
          @Override
public void onClick(View v) {
final SharedPreferences.Editor edit = prefs.edit();
               edit.putInt("vi", gio);
               edit.putInt("vi2", pu);
               edit.commit();
                  Bundle mBundle = new Bundle();
                  mBundle.putInt("to", gio);
                  mBundle.putInt("to2", pu);
                  mIntent.putExtras(mBundle);
                     startService(mIntent);
                      chay=isRunning(chuong.this);
                      if(chay==true){
                          on.setText("ON");
                          on.setBackgroundColor(Color.GREEN);
                          on.setTextColor(Color.WHITE);
                          on.setTypeface(null, Typeface.BOLD);
                           }
               }
          });
          b2 = (Button) findViewById(R.id.b2);
     b2.setOnClickListener(new View.OnClickListener() {
               @Override
               public void onClick(View v) {
                     finish();

               }
          });
          b1.setTextSize(android.util.TypedValue.COMPLEX_UNIT_DIP, 15);
     b2.setTextSize(android.util.TypedValue.COMPLEX_UNIT_DIP, 15);
Copy lên trên ngoặc đóng cuối cùng.
public static boolean isRunning(Context context) {
       ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
         for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
             if (service.class.getName().equals(service.service.getClassName())){
          return true;
         }
     }
       return false;
}
Thêm hàm khi ấn textview để tắt chuông đi.
public void tatchuong(View v) {
               on.setText("OFF");
               on.setTextColor(Color.RED);
               on.setBackgroundColor(Color.LTGRAY);
               on.setTypeface(null, Typeface.NORMAL);
               stopService(new Intent(chuong.this, service.class));              
}
Trong class này ta lấy giá trị giờ chọn, lưu lại để lần sau mở ra nó giữ nguyên như cũ. Khi ấn OK sẽ truyền dữ liệu vào service để set ra ngoài màn hình. Nếu đã đặt chuông mà lại ấn vào textView ON thì sẽ chuyển sang OFF, tắt chuông đi.
Để mở vào class này nếu nó không phải là class main.
Intent in = new Intent(MainActivity.this, chuong.class);
                     startActivity(in);   
Để tạo customadapter bạn xem ở bài này.

No comments:

Post a Comment