• 安卓小项目实战之--定时提醒备忘录


    写在前面:

          安卓的学习也有半年多了,期间也曾写过博客,但大多都是一些琐碎的笔记,基本没用任何参考价值,这几天闲来无事,便想做个小项目来玩玩,巩固一下基本知识,并且完整的记录下来整个开发的过程,以作留念。

    /————————我是华丽的分割线—————————-/
          本次项目选择了可定时提示的备忘录。原理是利用系统每分钟发送一条时间改变的广播,通过接受这条广播来判断是否为用户设置的时间,如果是则与用户交互提醒用户。
    首先,在Eclipse中创建一个Android项目,取名为Notification

    类:MainActivity.java

    MainActivity
    此Activity主要用于用户添加备忘录页面的转跳与已添加备忘录的展示。
    在其布局文件activity_main.xml中加入一个Button和一个TextView 。目前还没有实现多事件的共同设置,所以暂时使用TextView显示事件。
    因为储存的数据比较少,这里采用SharedPreferences进行存储,在Activity的onCreate()方法中进行成员变量的初始化操作:

            protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            init();
            sp = getSharedPreferences("UserNote",MODE_PRIVATE);
        }
    
    public void init() {
    
            button = (Button) findViewById(R.id.bt);
            title = (TextView) findViewById(R.id.main_title);
            note = (TextView) findViewById(R.id.main_note);
            time = (TextView)findViewById(R.id.main_time);
        }

    在onStart()中对按钮bt添加点击事件监听,并通过startActivity(intent)启动AddActivity转跳到添加的Activity:

        protected void onStart() {
            super.onStart();
            button.setOnClickListener(new OnClickListener() {
    
                @Override
                public void onClick(View arg0) {
                    Intent intent = new Intent(MainActivity.this, AddActivity.class);
                    startActivity(intent);
                }
            });
    
        }

    在onResume()方法中,获取SharedPerfences中的数据并更新TextView的内容:

    protected void onResume(){
            super.onResume();
            strTime = sp.getString("time","null");
            strTitle = sp.getString("title","null");
            strNote = sp.getString("text","null");
            title.setText(strTitle);
            note.setText(strNote);
            time.setText(strTime);
            System.out.println("onResume");
    
        }

    MainActivity.java整体代码如下:

    package com.example.notification;
    
    import android.app.Activity;
    import android.content.Intent;
    import android.content.SharedPreferences;
    import android.os.Bundle;
    import android.support.v7.app.ActionBarActivity;
    import android.util.Log;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.TextView;
    
    public class MainActivity extends Activity {
        private Button button;
        private SharedPreferences sp;
        private TextView title, note,time;
        private String strTitle,strNote,strTime;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            init();
            sp = getSharedPreferences("UserNote",MODE_PRIVATE);
        }
    
        @Override
        protected void onStart() {
            super.onStart();
            button.setOnClickListener(new OnClickListener() {
    
                @Override
                public void onClick(View arg0) {
                    Intent intent = new Intent(MainActivity.this, AddActivity.class);
                    startActivity(intent);
                }
            });
    
        }
        protected void onResume(){
            super.onResume();
            strTime = sp.getString("time","null");
            strTitle = sp.getString("title","null");
            strNote = sp.getString("text","null");
            title.setText(strTitle);
            note.setText(strNote);
            time.setText(strTime);
            System.out.println("onResume");
    
        }
    
        public void init() {
    
            button = (Button) findViewById(R.id.bt);
            title = (TextView) findViewById(R.id.main_title);
            note = (TextView) findViewById(R.id.main_note);
            time = (TextView)findViewById(R.id.main_time);
        }
    }
    
    该Activity布局文件activity_main.xml如下
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        tools:context="com.example.notification.MainActivity"
        android:background="#fcf3ea" >
    
        <Button
            android:id="@+id/bt"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="添加备忘录"
            android:textSize="20dp" />
    
        <TextView
            android:id="@+id/setting"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/bt"
            android:textSize="20dp"
            android:text="" />
    
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignTop="@+id/setting"
            android:layout_toRightOf="@+id/setting"
            android:orientation="vertical" >
    
            <TextView
                android:id="@+id/main_time"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textSize="20dp"
                android:text="" />
            <TextView
                android:id="@+id/main_title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textSize="20dp"
                android:text="" />
              <TextView
                android:id="@+id/main_note"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textSize="20dp"
                android:text="" />
        </LinearLayout>
    
    </RelativeLayout>

    类:AddActivity.java

    AddActivity
    该Activity为用户添加备忘录事件的Activity,用户通过EditText和DatePicker和TimePicker进行数据的输入,单击按钮由SharedPerfences记录用户输入的数据.在onCreate()中进行初始化,在onStart()中对按钮添加监听,并且将时间选择器和用户输入的内容存入SharedPerfences,这里应当注意的是,时间选择器选择的数据如果为一位数如1月 则记录的日期为1 并非01,这点与SimpleDateFormat生成的不一致,所以我们需要自己建立一个类来规范我们的时间,这个类取名为MyTime,在存储完毕用户键入的数据以后,Activity会启动一个服务NotifyService,并且调用finish()关闭自身。

    AddActivity代码如下:
    package com.example.notification;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    import android.annotation.SuppressLint;
    import android.app.Activity;
    import android.content.Intent;
    import android.content.SharedPreferences;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.DatePicker;
    import android.widget.EditText;
    import android.widget.TimePicker;
    import android.widget.Toast;
    
    public class AddActivity extends Activity {
        private Button conButton;
        private TimePicker tp;
        private DatePicker dp;
        private EditText etTitle, etNote;
        private String title, text;
        private SharedPreferences sp;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_add);
            init();
        }
    
        protected void onStart() {
            super.onStart();
            conButton.setOnClickListener(new OnClickListener() {
    
                @Override
                public void onClick(View arg0) {
                    saveTime();
    
                }
            });
        }
    
        @SuppressLint("NewApi")
        public void init() {
            conButton = (Button) findViewById(R.id.add_bt_confirm);
            tp = (TimePicker) findViewById(R.id.timePicker1);
            dp = (DatePicker) findViewById(R.id.datePicker1);
            etTitle = (EditText) findViewById(R.id.add_et_title);
            etNote = (EditText) findViewById(R.id.add_et_note);
            tp.setIs24HourView(true);
            dp.setCalendarViewShown(false);
            sp = getSharedPreferences("UserNote", MODE_PRIVATE);
        }
    
        public void saveTime() {
            text = etNote.getText().toString();
            title = etTitle.getText().toString();
            int day = dp.getDayOfMonth();
            int mon = dp.getMonth()+1;//getMonth 返回从0开始
            System.out.println("setMon is"+mon);
            int year = dp.getYear();
            int hour = tp.getCurrentHour();
            int min = tp.getCurrentMinute();
    
            SimpleDateFormat sdf = new SimpleDateFormat("HHmm");
    
            String time = MyTime.getTime(year,mon,day,hour, min);
            System.out.println(time);
            SharedPreferences.Editor editor = sp.edit();
            editor.putString("text", text);
            editor.putString("time", time);
            editor.putString("title",title);
            editor.commit();
            System.out.println(time);
            Intent intent = new Intent(AddActivity.this, NotifyService.class);
            startService(intent);
            Log.i("ADD","intent完毕");
            finish();
        }
    
    }
    
    MyTime.java如下
    package com.example.notification;
    
    public class MyTime {
    
        public MyTime() {
            // TODO 自动生成的构造函数存根
        }
    
        public static String getTime(int year,int mon,int day,int hour, int min) {
    
            String mins,mons,days,hours;
            if(hour<10)
                hours = 0+String.valueOf(hour);
            else
                hours = String.valueOf(hour);
            if(min<10)
                mins =0+ String.valueOf(min);
            else
                mins = String.valueOf(min);
            if(mon<10)
                mons =0+ String.valueOf(mon);
            else
                mons = String.valueOf(mon);
            if(day<10)
                days = 0+String.valueOf(mon);
            else
                days = String.valueOf(day);
            return year+":"+mons+":"+days+":"+hours+":"+mins;
    
        }
    }
    

    服务NotifyService.java

    新建服务需要在AndroidManifest.xml进行注册,在节点下加入以下代码进行注册

      <service android:name=".NotifyService" ></service>

    该服务主要功能为判断当前时间与用户储存时间是否一致,并进行相应动作,在onCreate()方法动态注册一个广播接收器TimeRecevier,该广播接收器接收系统时间变化的广播,该广播每分钟由系统发出一次,并在OnDestroy()方法中注销该广播接收器。具体ACTION如下(要接收该广播,必须进行动态注册):

    private String ACTION = Intent.ACTION_TIME_TICK;

    在onStartCommand()方法中,利用SimpleDateFormat将当前系统时间格式化与本地存储一致的格式,当前时间可以通过new Date()获取(new Date()实质上就是System.currentTimeMillis());然后进行时间的比对,如果一致,则通知栏通知用户,并且启动一个可以在锁屏状态下唤醒屏幕的Activity。这里值得注意的是,在服务中启动一个Activity必须为调用的intent添加一个Flag如下:

    ActIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  

    最后调用stopSelf()方法,关闭自身.

    NotifyService.java代码如下:
    package com.example.notification;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    import android.app.Notification;
    import android.app.NotificationManager;
    import android.app.PendingIntent;
    import android.app.Service;
    import android.content.Intent;
    import android.content.IntentFilter;
    import android.content.SharedPreferences;
    import android.os.IBinder;
    import android.util.Log;
    
    public class NotifyService extends Service {
        private NotificationManager nm;
        private boolean isRec = false;
        private boolean isFirst = true;
        private String ACTION = Intent.ACTION_TIME_TICK;
        private SharedPreferences sp;
        private IntentFilter ifter;
        private TimeReceiver receiver;
    
        @Override
        public IBinder onBind(Intent arg0) {
            // TODO 自动生成的方法存根
            return null;
        }
    
        @Override
        public void onCreate() {
            // TODO 自动生成的方法存根
            super.onCreate();
            sp = getSharedPreferences("UserNote", MODE_PRIVATE);
            nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
            ifter = new IntentFilter();
            ifter.addAction(ACTION);
            receiver = new TimeReceiver();
            if (isRec == false) {
                registerReceiver(receiver, ifter);
                isRec = true;
            }
            Log.i("Service","onCreate");
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
            System.out.println("服务拜拜");
            unregisterReceiver(receiver);
        }
    
        @SuppressWarnings("deprecation")
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            // TODO 自动生成的方法存根
            Log.i("Service","onStart");
            if (isFirst) {
                isFirst = false;
            } else {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy:MM:dd:HH:mm");
                String curTime = sdf.format(new Date());
                System.out.println(curTime);
    
                String time =sp.getString("time", "0000");
                System.out.println("curTime"+curTime+" setTime"+time);
                if (curTime.equals(time)) {
                    String text = sp.getString("text", "默认事件");
                    System.out.println("onStart");
                    Notification notify = new Notification(R.drawable.ic_launcher,
                            "小贴士", System.currentTimeMillis());
                    PendingIntent pi = PendingIntent.getActivity(this,0, 
                            new Intent(this,MainActivity.class),0);
                    notify.setLatestEventInfo(this, "小贴士提醒您", time+"  "+text, pi);
                    notify.defaults = Notification.DEFAULT_ALL;
                    nm.notify(1044, notify);
                    Intent ActIntent = new Intent(this,DialogActivity.class);
                    ActIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
                    startActivity(ActIntent);
    
                    stopSelf();
                }
            }
            return super.onStartCommand(intent, flags, startId);
    
        }
    
    }
    

    类,广播接收器:TimeReceiver.java

    整个接收器的作用只有一个,就是每次接收到广播,便启动服务NotifyService。

    TimeReceiver.java如下
    package com.example.notification;
    
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    
    public class TimeReceiver extends BroadcastReceiver{
    
    
    
        @Override
        public void onReceive(Context context, Intent intent) {
            System.out.println("recevice");
            context.startService(new Intent(context,NotifyService.class));
    
        }
    
    }
    

    类DialogActivity.java

    DialogActivity
    该Activity为用户预设的时间到了通知用户的Activity,该Activity有如下特性:
          1.可以点亮屏幕。
          2.可以在锁屏状态下启动。
    实现这两个特点并不困难,只需要加入这两句话:

     getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                        | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);

    另外,值得一提的是,QQ客户端的锁屏聊天窗口就是这样实现的(如图):
    QQ对话框
    这个窗口看似是在弹窗之上。其实本身只是一个Activity,玄机就在他的背景图片,他是一个以系统壁纸为背景的没有标题栏的Activity。因此为了不让Activity突然弹出看起来那么突兀,我们要自定义一个Theme。在AndroidManifest.xml的节点下加入以下代码

    <activity
                android:name=".DialogActivity"
                android:label="提醒您" 
                android:theme="@android:style/Theme.Wallpaper.NoTitleBar"
                >

    在res/values/styles.xml加入自定义的Style

      <style name="FullScreenTheme" parent="@android:style/Theme.Light.NoTitleBar">
            <item name="android:windowBackground">@android:color/transparent</item>
            <item name="android:colorBackgroundCacheHint">@null</item>
            <item name="android:windowNoTitle">true</item>
            <item name="android:windowIsTranslucent">true</item>
        </style>

    完成

    感谢你的阅读,在此我们就完成了定时提醒备忘录这个小项目,当然这个项目还有很多不足,只是一个功能的实现,如果有兴趣你可以根据源代码添加想要的功能例如多条事件的添加,还可以加上桌面组件.

    源码下载地址:

    http://download.csdn.net/detail/wingichoy/8717199

  • 相关阅读:
    2020 CCPC-Wannafly Winter Camp Day6 ---I. 变大!
    Codeforces 1295F Good Contest
    2020 CCPC-Wannafly Winter Camp Day6 ---A. Convolution
    centos下kubernetes+flannel部署(旧)
    无网络centos7中部署kubernetes
    利用Openvswitch实现不同物理机中的Docker容器互连
    docker-py的配置与使用
    通过Docker配置DNS服务器
    在 OS X Yosemite 中部署Mesos
    Docker初识
  • 原文地址:https://www.cnblogs.com/muyuge/p/6333583.html
Copyright © 2020-2023  润新知