Android多功能课程表项目实现(完整版)
16lz
2022-04-13
转载请注明出处:http://blog.csdn.net/ns_code/article/details/11269957
鉴于很多网友发私信或者留言想我所要课程表项目源码,我这里将其开源到我的Github上:
https://github.com/mmc-maodun/Multi-function-curriculum-Based-on-Android
工欲善其事,必先利其器,刚接触Android一个月的时候,便准备做一款Android平台下的多功能课程表,做了一周多,便出去实习了,近几个月一直在忙公司(实习)的事情,利用断断续续的闲暇时间,将该APP做出来了,虽说这东东不算难做,但真要做起来,遇到的问题还是蛮多的,在不断的发现问题与解决问题中成长,也是对自己的一种锻炼。
该APP已经上传到小米应用商店,欢迎下载:http://app.xiaomi.com/detail/42115
编辑、添加、删除和查看课程表;
【核心功能】
1、打开课表时来,默认显示当天的课程信息;
2、根据用户的设置,在上课前通知提醒;
3、根据用户的设置,上课时自动将手机调节振动,下课后将手机恢复正常铃声;
先附上几张在模拟器上截取的效果图片:
完成这个APP之后,大致总结了几点局部功能的实现方法(不是很全),如下:
1、上课自动静音功能的实现:
通过开关控制是否启动后台的SetQuierService,从而在程序退出后一直在后台运行,
在SetQuierService中,用TimeTask,每隔一分钟从数据库中取出一次数据,
并从系统取得一次当天是星期几,以及当前的时间,
通过二者对比较,确定是否开启振动模式以及恢复原始铃声模式设置。
另外:这里写了一个LauncherReceiver用来监听系统开机事件,当用户开启了SetQuierService,但是因为某种原因关机了,
再次开机后,它会在这种情况下开机自启动SetQuierService。
2、课前提醒功能的实现:
通过开关控制是否每隔一分钟发送一次广播,而该广播会被RemindReceiver接收到,从而每隔一分钟从数据库中取得一次数据,
并从系统中取得一次当天是星期几,以及当前的时间,
通过对二者的比较,确定是否启动提醒用户的RemindActivity
另外,该广播的发送通过AlarmManager来实现,参数里设置的休眠不发送广播,但开机后会继续发送,因此不受关机影响。
3、完全退出应用程序采用的方法:
建立一个继承自Application的类MyApplication,在其中定义一个放置Activity的容器,用单例设计模式取得唯一的MyApplication实例,每建立一个Activity,就将其添加到该MyApplication实例的容器中。
4、第一次打开APP时直接创建数据库表,之后直接调用数据库:
采用单例设计模式创建数据库表,通过SharedPreferences保存一标志位,判断是否是第一次创建数据库表。
详细的工程文件截图如下:
各文件的源代码如下,详细的注释代码里面都有,这里不再详细说明:
文件
<?xml version="1.0" encoding="utf-8"?>
package zyb.org.load;import zyb.org.androidschedule.MainActivity;import zyb.org.androidschedule.R;import android.app.Activity;import android.content.Intent;import android.graphics.PixelFormat;import android.os.Bundle;import android.os.Handler;import android.view.WindowManager;public class LoadActivity extends Activity { //time for picture display private static final int LOAD_DISPLAY_TIME = 3000; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().setFormat(PixelFormat.RGBA_8888); getWindow().addFlags(WindowManager.LayoutParams.FLAG_DITHER); setContentView(R.layout.activity_load); new Handler().postDelayed(new Runnable() { public void run() { //Go to main activity, and finish load activity Intent mainIntent = new Intent(LoadActivity.this, MainActivity.class); LoadActivity.this.startActivity(mainIntent); LoadActivity.this.finish(); } }, LOAD_DISPLAY_TIME); }}
布局文件,与
<?xml version="1.0" encoding="utf-8"?>
package zyb.org.androidschedule;import temp.DataBase;import temp.MyApplication;import temp.MyDialog;import temp.ShareMethod;import zyb.org.editschedule.SetActivity;import android.media.AudioManager;import android.os.Bundle;import android.app.Activity;import android.app.AlertDialog;import android.app.Service;import android.content.Context;import android.content.DialogInterface;import android.content.Intent;import android.content.SharedPreferences;import android.database.Cursor;import android.support.v4.widget.SimpleCursorAdapter;import android.util.Log;import android.view.GestureDetector;import android.view.Menu;import android.view.MenuItem;import android.view.MotionEvent;import android.view.View;import android.view.View.OnClickListener;import android.view.View.OnTouchListener;import android.widget.AdapterView;import android.widget.AdapterView.OnItemClickListener;import android.widget.ListView;import android.widget.TabHost;import android.widget.TabWidget;import android.widget.TextView;public class MainActivity extends Activity { public ListView list[] = new ListView[7];private TabHost tabs = null;private TextView exitButton = null; private TextView setButton = null;public static DataBase db;public Cursor[] cursor=new Cursor[7];public SimpleCursorAdapter adapter;private SharedPreferences pre; //定义手势检测器实例private GestureDetector detector = null; //定义手势动作两点之间的最小距离private final int FLIP_DISTANCE = 200;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//将该activity加入到MyApplication对象实例容器中MyApplication.getInstance().addActivity(this);db=new DataBase(MainActivity.this);pre=getSharedPreferences("firstStart",Context.MODE_PRIVATE);/* * 判断程序是否第一次运行,如果是创建数据库表 */if(pre.getBoolean("firstStart", true)){SingleInstance.createTable();(pre.edit()).putBoolean("firstStart",false).commit();//finish();}exitButton = (TextView)findViewById(R.id.exitButton);setButton = (TextView)findViewById(R.id.setButton);list[0] = (ListView)findViewById(R.id.list0);list[1] = (ListView)findViewById(R.id.list1);list[2] = (ListView)findViewById(R.id.list2);list[3] = (ListView)findViewById(R.id.list3);list[4] = (ListView)findViewById(R.id.list4);list[5] = (ListView)findViewById(R.id.list5);list[6] = (ListView)findViewById(R.id.list6);tabs = (TabHost)findViewById(R.id.tabhost); //创建手势检测器 detector = new GestureDetector(this, new DetectorGestureListener()); //在配置任何的TabSpec之前,必须在TabHost上调用该方法tabs.setup();//为主界面注册七个选项卡TabHost.TabSpec spec = null;addCard(spec,"tag1",R.id.list0,"日");addCard(spec,"tag2",R.id.list1,"一");addCard(spec,"tag3",R.id.list2,"二");addCard(spec,"tag4",R.id.list3,"三");addCard(spec,"tag5",R.id.list4,"四");addCard(spec,"tag6",R.id.list5,"五");addCard(spec,"tag7",R.id.list6,"六");//修改tabHost选项卡中的字体的颜色TabWidget tabWidget = tabs.getTabWidget();for(int i=0;i arg0, View arg1,final int id, long arg3) {final int currentDay=tabs.getCurrentTab();final int n=id; final AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); builder.setIcon(R.drawable.ic_launcher);builder.setTitle("选择");TextView tv=(TextView)arg1.findViewById(R.id.ltext0);Log.i("Test",(tv.getText().toString().equals(""))+"");//如果课程栏目为空就启动添加对话框if((tv.getText()).toString().equals("")){//通过数组资源为对话框中的列表添加选项内容,这里只有一个选项builder.setItems(R.array.edit_options1, new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {//如果单击了该列表项,则跳转到编辑课程信息的界面if(which == 0){new MyDialog(MainActivity.this).add(currentDay,n);}}});builder.create().show(); }//否则启动修改对话框,或直接删除数据else{builder.setItems(R.array.edit_options2, new DialogInterface.OnClickListener() {@SuppressWarnings("deprecation")@Overridepublic void onClick(DialogInterface dialog, int which) {//如果单击了该列表项,则跳转到编辑课程信息的界面if(which == 0){new MyDialog(MainActivity.this).modify(currentDay,n);}if(which == 1){cursor[currentDay].moveToPosition(n);int n1=Integer.parseInt(cursor[currentDay].getString(7));//课程的总节数int n2=Integer.parseInt(cursor[currentDay].getString(8));//选中的为该课程的第几节switch(n2){case 0:for(int m=0;m=0;m--){MainActivity.db.deleteData(currentDay,n-m+1);}break;default:break;}cursor[currentDay].requery();list[currentDay].invalidate();}}});builder.create().show();}}});}}//内部类,实现GestureDetector.OnGestureListener接口class DetectorGestureListener implements GestureDetector.OnGestureListener{@Overridepublic boolean onDown(MotionEvent e) {return false;}//当用户在触屏上“滑过”时触发此方法@Overridepublic boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,float velocityY) {int i = tabs.getCurrentTab();//第一个触点事件的X坐标值减去第二个触点事件的X坐标值超过FLIP_DISTANCE,也就是手势从右向左滑动if(e1.getX() - e2.getX() > FLIP_DISTANCE){if(i<6)tabs.setCurrentTab(i+1);//float currentX = e2.getX();//list[i].setRight((int) (inialX - currentX));return true;}//第二个触点事件的X坐标值减去第一个触点事件的X坐标值超过FLIP_DISTANCE,也就是手势从左向右滑动else if(e2.getX() - e1.getX() > FLIP_DISTANCE){if(i>0)tabs.setCurrentTab(i-1);return true;}return false;}@Overridepublic void onLongPress(MotionEvent e) {}@Overridepublic boolean onScroll(MotionEvent e1, MotionEvent e2,float distanceX, float distanceY) {return false;}@Overridepublic void onShowPress(MotionEvent e) {}@Overridepublic boolean onSingleTapUp(MotionEvent e) {return false;}}//覆写Activity中的onTouchEvent方法,将该Activity上的触碰事件交给GestureDetector处理@Overridepublic boolean onTouchEvent(MotionEvent event) {return detector.onTouchEvent(event);}//设置菜单按钮@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.activity_main, menu);return true;}//当点击菜单中的“退出”键时,弹出提示是否退出的对话框@Overridepublic boolean onOptionsItemSelected(MenuItem item) {//创建AlertDialog.Builder对象,该对象是AlterDialog的创建器,AlterDialog用来创建弹出对话框 final AlertDialog.Builder builder = new AlertDialog.Builder(this);if(item.getItemId() == R.id.menu_exit){exit(builder);return true;}if(item.getItemId() == R.id.menu_settings){Intent intent = new Intent(MainActivity.this, SetActivity.class);startActivity(intent);return true;}return super.onOptionsItemSelected(item);} //子 方法:为主界面添加选项卡public void addCard(TabHost.TabSpec spec,String tag,int id,String name){spec = tabs.newTabSpec(tag);spec.setContent(id);spec.setIndicator(name);tabs.addTab(spec);}//子方法:用来弹出是否退出程序的对话框,并执行执行是否退出操作public void exit(AlertDialog.Builder builder){//为弹出的对话框设置标题和内容builder.setIcon(R.drawable.ic_launcher);builder.setTitle("退出程序");builder.setMessage("确定要退出随身课程表吗?");//设置左边的按钮为“确定”键,并且其绑定监听器,点击后退出builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {//退出应用程序,即销毁地所有的activityMyApplication.getInstance().exitApp();}});//设置右边的按钮为“取消”键,并且其绑定监听器,点击后仍然停留在当前界面builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {}});//创建并显示弹出的对话框builder.create().show();}/* * 为每一个list提供数据适配器 */@SuppressWarnings("deprecation")public SimpleCursorAdapter adapter(int i){return new SimpleCursorAdapter(this, R.layout.list_v2,cursor[i],new String[]{"_id","classes","location","teacher","zhoushu"},new int[]{R.id.number,R.id.ltext0,R.id.ltext1,R.id.ltext6,R.id.ltext7} );}/* * 第一次运行时创建数据库表 */static class SingleInstance{static SingleInstance si;private SingleInstance(){for(int i=0;i<7;i++){db.createTable(i);}}static SingleInstance createTable(){if(si==null)return si=new SingleInstance();return null;}}}
布局文件,与
package temp;import android.content.ContentValues;import android.content.Context;import android.database.Cursor;import android.database.sqlite.SQLiteDatabase;import android.database.sqlite.SQLiteOpenHelper;public class DataBase extends SQLiteOpenHelper{private final static String DB_NAME="myBase";private final static String[] TB_NAME={"Mon","Tue","Wed","Thur","Fri","Sat","Sun"};public final static String ID="_id";public final static String CLASS="classes";public final static String LOCA="location";public final static String TEACHER="teacher";public final static String ZHOUSHU="zhoushu";public final static String JIESHU="jieshu";public final static String TIME1="time1";public final static String TIME2="time2";public final static String WHICH="which";public DataBase(Context context){super(context,DB_NAME,null,1);}@Overridepublic void onCreate(SQLiteDatabase db) {for(int i=0;i<7;i++){String sql="CREATE TABLE "+TB_NAME[i]+" (_id INTEGER primary key autoincrement,classes varchar(70),location varchar(70)," +"teacher varchar(70),zhoushu varchar(70),time1 varchar(70),time2 varchar(70),jieshu varchar(70),which varchar(70))";db.execSQL(sql);}}@Overridepublic void onUpgrade(SQLiteDatabase db, int oleVersion, int newVersion) {for(int i=0;i<7;i++){String sql="DROP TABLE IF EXISTS "+TB_NAME[i];db.execSQL(sql);}onCreate(db);}public Cursor select(int i){SQLiteDatabase db=DataBase.this.getReadableDatabase();Cursor cursor=db.query(TB_NAME[i],null,null,null,null,null,null);return cursor;}public long insert(int i,String cla,String loca,String tea,String zhou,String jie,String time1,String time2,String which){SQLiteDatabase db=DataBase.this.getWritableDatabase();ContentValues cv=new ContentValues();cv.put(CLASS,cla);cv.put(LOCA, loca);cv.put(TEACHER,tea);cv.put(ZHOUSHU,zhou);cv.put(JIESHU,jie);cv.put(TIME1,time1);cv.put(TIME2,time2);cv.put(WHICH,which);long row=db.insert(TB_NAME[i],null,cv);return row;}public void update(int i,int _id,String cla,String loca,String tea,String zhou,String jie,String time1,String time2,String which){SQLiteDatabase db=DataBase.this.getWritableDatabase();String where="_id = ?";String[] whereValues={Integer.toString(_id)};ContentValues cv=new ContentValues();if(!cla.equals("")) cv.put(CLASS,cla);if(!loca.equals("")) cv.put(LOCA, loca);if(!tea.equals("")) cv.put(TEACHER,tea);if(!zhou.equals("")) cv.put(ZHOUSHU,zhou);if(!jie.equals("")) cv.put(JIESHU,jie);if(!time1.equals("")) cv.put(TIME1,time1);if(!time2.equals("")) cv.put(TIME2,time2);if(!which.equals("")) cv.put(WHICH,which);db.update(TB_NAME[i], cv, where, whereValues);}public void deleteData(int i,int _id){SQLiteDatabase db=DataBase.this.getWritableDatabase();String where="_id = ?";String[] whereValues={Integer.toString(_id)};ContentValues cv=new ContentValues();cv.put("classes","");cv.put("location","");cv.put("teacher","");cv.put("zhoushu","");cv.put("jieshu","");cv.put("time1","");cv.put("time2","");cv.put("which","");db.update(TB_NAME[i], cv, where, whereValues);}public void delete(int i,int _id){SQLiteDatabase db=this.getWritableDatabase();String where="_id = ?";String[] whereValues={Integer.toString(_id)};db.delete(TB_NAME[i], where, whereValues);}public void createTable(int j){for(int i=1;i<=12;i++)insert(j,"", "", "","","","","","");}}
package temp;import zyb.org.androidschedule.MainActivity;import android.content.Context;public class MyAdapter {private Context context;private MainActivity main;public MyAdapter(Context context){this.context=context;main=(MainActivity) context;}}
package temp;import java.util.Calendar;import zyb.org.androidschedule.MainActivity;import zyb.org.androidschedule.R;import android.app.AlertDialog;import android.app.AlertDialog.Builder;import android.app.TimePickerDialog;import android.content.Context;import android.content.DialogInterface;import android.content.DialogInterface.OnClickListener;import android.util.Log;import android.view.LayoutInflater;import android.view.View;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;import android.widget.TimePicker;import android.widget.Toast;public class MyDialog {private EditText course_name;private EditText course_address;private EditText course_teacher;private EditText course_week;//private EditText course_time1,course_time2;private EditText course_count;private View view;private Context context;private LayoutInflater inflater;private Builder builder;MyAdapter adapter;MainActivity main;String s1="",s2="",s3="",s4="",s5="",s6="",s7="";public MyDialog(Context context){this.context=context;main=(MainActivity) context;adapter=new MyAdapter(context);} /* * 点击未编辑的课程列表跳出”添加课程“对话框 */public void add(final int day,final int n){//填装对话框的viewinflater=LayoutInflater.from(context);view=inflater.inflate(R.layout.edit_shedule,null);findWidgetes();//取部件final Button course_time1=(Button)view.findViewById(R.id.time1);final Button course_time2=(Button)view.findViewById(R.id.time2);//为两个输入时间的按钮绑定监听器course_time1.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {TimeSet_Dialog(course_time1);}});course_time2.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {TimeSet_Dialog(course_time2);}});builder=new AlertDialog.Builder(context).setIcon(R.drawable.ic_launcher).setTitle("编辑课程信息").setView(view).setPositiveButton("确认",new OnClickListener(){@SuppressWarnings("deprecation")@Overridepublic void onClick(DialogInterface arg0, int arg1) {if(!(s1=course_name.getText().toString()).equals("")) s1="课程: "+s1;if(!(s2=course_address.getText().toString()).equals("")) s2="地点: "+s2;if(!(s3=course_teacher.getText().toString()).equals("")) s3="老师: "+s3;if(!(s4=course_week.getText().toString()).equals("")) s4="周数: "+s4;if(!(s6=course_time1.getText().toString()).equals("")) s6="时间: "+s6;if(!(s7=course_time2.getText().toString()).equals("")) ;if((s5=course_count.getText().toString()).equals("")||s1.equals("")) {Toast.makeText(context, "请正确输入课程及节数!", 3000).show();return;}else {int i=Integer.parseInt(s5.trim());//i为节数for(int m=0;m=0;m--){MainActivity.db.update(day,n-m+1,s1,s2,s3,s4,s5,s6,s7,Integer.toString(n2-m));}break;}}//若节数有变化,先确定新节数并赋予旧的数据再更新数据else{int n3=Integer.parseInt(s5.trim());//扩充节数if(n3>n1){switch(n2){//更新数据case 0:for(int m=0;m=0;m--){MainActivity.db.update(day,n-m+1,s1,s2,s3,s4,s5,s6,s7,Integer.toString(n2-m));}break;}}//缩减节数:删除旧数据再根据新的节数赋予旧数据最后更新新数据if(n3=0;m--){MainActivity.db.deleteData(day,n-m+1);}break;default:Toast.makeText(context, "error", 3000).show();break;}switch(n2){//更新数据case 0:for(int m=0;m
package temp;import java.util.LinkedList;import java.util.List;import android.app.Activity;import android.app.Application;//MyApplication类用来存储每一个activity,并实现关闭所有activity的操作public class MyApplication extends Application {//定义容activity容器private List activityList = new LinkedList();private static MyApplication instance;private MyApplication(){}//单例设计模式中取得唯一的MyApplication实例public static MyApplication getInstance(){if(instance == null)instance = new MyApplication();return instance;}//添加activity到容器中public void addActivity(Activity activity){activityList.add(activity);}//遍历所有的activity并finishpublic void exitApp(){for(Activity activity : activityList){if(activity != null)activity.finish();}System.exit(0);}//清空缓存@Override public void onLowMemory() { super.onLowMemory(); System.gc(); } }
package temp;import java.util.Calendar;import java.util.Date;public class ShareMethod {//获取当天是星期几,这里星期七、一......分别为数字0、1......public static int getWeekDay(){Calendar calendar=Calendar.getInstance();Date date=new Date(System.currentTimeMillis());calendar.setTime(date);int weekDay=calendar.get(Calendar.DAY_OF_WEEK)-1;return weekDay;}//获取当前的时间,并以字符串"xx:xx"的形式返回public static String getTime(){Calendar c=Calendar.getInstance();int hourOfDay = c.get(Calendar.HOUR_OF_DAY);int minute = c.get(Calendar.MINUTE);//获取完整的时间,在只有一位的数字前面加0StringBuffer s_hour = new StringBuffer();StringBuffer s_minute = new StringBuffer();s_hour.append(hourOfDay);s_minute.append(minute);if(hourOfDay<10){s_hour.insert(0,"0");}if(minute<10){s_minute.insert(0,"0");}return s_hour.toString() + ":" + s_minute.toString();}}
package zyb.org.editschedule;import temp.MyApplication;import zyb.org.about.AboutUsActivity;import zyb.org.androidschedule.R;import zyb.org.service.RemindReceiver;import zyb.org.version.VersionActivity;import android.app.Activity;import android.app.AlarmManager;import android.app.AlertDialog;import android.app.Dialog;import android.app.PendingIntent;import android.app.Service;import android.app.AlertDialog.Builder;import android.content.Context;import android.content.DialogInterface;import android.content.Intent;import android.content.SharedPreferences;import android.media.AudioManager;import android.os.Bundle;import android.util.Log;import android.view.View;import android.view.View.OnClickListener;import android.widget.CompoundButton;import android.widget.CompoundButton.OnCheckedChangeListener;import android.widget.Switch;import android.widget.TextView;import android.widget.Toast;public class SetActivity extends Activity {//声明一个SharedPreferences对象,用来保存switch组件的开关信息private SharedPreferences preferences = null;//editor对象用来向preferences中写入数据private SharedPreferences.Editor editor = null;//声明一个SharedPreferences对象,用来保存time_choice的值private SharedPreferences pre = null;//pre_editor对象用来向pre中写入数据private SharedPreferences.Editor pre_editor = null;//声明一个AlarmManager对象,用来开启课前提醒服务private AlarmManager alarmManager = null;//声明一个PendingIntent对象,用来指定alarmManager要启动的组件private PendingIntent pi = null;private Intent alarm_receiver = null; //定义单选列表对话狂的id,该对话框用于显示课前提醒时间的可选项final int SINGLE_DIALOG = 0x113;//定义选中的时间private int time_choice = 0;private Switch switch_quietButton;private Switch switch_remindButton;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_set);//将该activity加入到MyApplication对象实例容器中MyApplication.getInstance().addActivity(this);//声明一个获取系统音频服务的类的对象final AudioManager audioManager = (AudioManager)getSystemService(Service.AUDIO_SERVICE);//从MainAcivity中获取原始设置的铃声模式Intent intent = getIntent();final int orgRingerMode = intent.getIntExtra("mode_ringer", AudioManager.RINGER_MODE_NORMAL);//获取系统的闹钟定时服务alarmManager = (AlarmManager)getSystemService(Service.ALARM_SERVICE);//指定alarmManager要启动的组件alarm_receiver = new Intent(SetActivity.this,RemindReceiver.class);//alarm_receiver.putExtra("anvance_remindtime", time_choice);pi = PendingIntent.getBroadcast(SetActivity.this, 0, alarm_receiver, 0);//取出各组件TextView backButton = (TextView)findViewById(R.id.backtoMainButton);switch_quietButton = (Switch)findViewById(R.id.switch_quiet);switch_remindButton = (Switch)findViewById(R.id.switch_remind);//这里模式一定要设置为MODE_MULTI_PROCESS,否则即使相应的xml文件中数据有更新,RemindReceiver中也不能获取更新后的数据,而是一直获取上次的数据, 除非清空缓存this.pre = SetActivity.this.getSharedPreferences("time", Context.MODE_MULTI_PROCESS);this.pre_editor = pre.edit();//指定该SharedPreferences数据可以跨进称调用this.preferences = SetActivity.this.getSharedPreferences("switch", Context.MODE_MULTI_PROCESS);this.editor = preferences.edit();//每次创建该activity时,从preferences中读取switch_quietButton和switch_remindButton的开关信息的数据Boolean quiet_status = preferences.getBoolean("switch_quiet", false);Boolean remind_status = preferences.getBoolean("switch_remind", false);switch_quietButton.setChecked(quiet_status);switch_remindButton.setChecked(remind_status);//为返回按钮绑定监听器backButton.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {finish();//Intent intent = new Intent(Set.this,MainActivity.class);//intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);//刷新//startActivity(intent);}});//为自动静音开关按钮绑定监听器switch_quietButton.setOnCheckedChangeListener(new OnCheckedChangeListener() {@Overridepublic void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {//启动自动静音的serviceIntent intent = new Intent();intent.setAction("zyb.org.service.QUIET_SERVICE");if(isChecked){if(startService(intent) != null)Toast.makeText(SetActivity.this, "成功开启,上课期间的来电将自动转为振动模式", 3000).show();else{Toast.makeText(SetActivity.this, "未能成功开启,请重新尝试", 3000).show();switch_quietButton.setChecked(false);}}else{if(stopService(intent))Toast.makeText(SetActivity.this, "成功关闭,恢复到原来的响铃模式", 3000).show();else{Toast.makeText(SetActivity.this, "未能成功关闭,请重新尝试", 3000).show();switch_quietButton.setChecked(true);}audioManager.setRingerMode(orgRingerMode);}//将开关信息数据保存进preferences中SetActivity.this.editor.putBoolean("switch_quiet", isChecked);editor.commit();}});//为课前提醒开关按钮绑定监听器switch_remindButton.setOnCheckedChangeListener(new OnCheckedChangeListener() {@Overridepublic void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {if(isChecked){showDialog(SINGLE_DIALOG);}else{alarmManager.cancel(pi);}//将开关信息数据保存进preferences中SetActivity.this.editor.putBoolean("switch_remind", isChecked);editor.commit();}});}@Override//该方法返回的Dialog将被showDialog()方法回调protected Dialog onCreateDialog(int id, Bundle args) {//判断生成何种类型的对话框if(id == SINGLE_DIALOG){Builder b = new AlertDialog.Builder(this);// 设置对话框的标题b.setTitle("选择课前提醒时间");// 为对话框设置多个列表,参数-1表示默认不选中任何选项b.setSingleChoiceItems(R.array.set_remind, -1, new DialogInterface.OnClickListener(){@Overridepublic void onClick(DialogInterface dialog,int which){switch (which){case 0:time_choice = 5;break;case 1:time_choice = 10;break;case 2:time_choice = 20;break;case 3:time_choice = 30;break;case 4:time_choice = 40;break;case 5:time_choice = 50;break;case 6:time_choice = 60;break;}}});// 添加一个“确定”按钮,用于关闭该对话框b.setPositiveButton("确定", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {//System.out.println("SetActivity:" + time_choice);if(time_choice == 0){Toast.makeText(SetActivity.this, "请选择课前提醒的时间", 3000).show();switch_remindButton.setChecked(false);}else{SetActivity.this.pre_editor.putInt("time_choice", time_choice);pre_editor.commit();//从当前时间开始,每隔一分钟启动一次pi指定的组件,即发送一次广播alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 60000, pi);Toast.makeText(SetActivity.this, "设置成功,系统将在课前" + time_choice + "分钟提醒您", Toast.LENGTH_LONG).show();}}});//添加一个“取消”按钮b.setNegativeButton("取消", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {switch_remindButton.setChecked(false);}});// 创建对话框return b.create(); }elsereturn null;}//如果点击“关于我们”的TextView,则跳转public void click_us(View v){Intent intent = new Intent(SetActivity.this, AboutUsActivity.class);startActivity(intent);}//如果点击“版本支持”的TextView,则跳转public void click_version(View v){Intent intent = new Intent(SetActivity.this, VersionActivity.class);startActivity(intent);}public void click_revision(View v){Log.i("MyDebug", "revision");} }
布局文件,与
<?xml version="1.0" encoding="utf-8"?>
package zyb.org.service;import java.util.Timer;import java.util.TimerTask;import temp.DataBase;import temp.ShareMethod;import android.app.Service;import android.content.Intent;import android.database.Cursor;import android.media.AudioManager;import android.os.IBinder;public class SetQuietService extends Service {//保存时间,temp[day][row][time]表示第day+1个tab选项卡中的第row+1个行中第time+1个表示时间的字符串String[][][] temp = new String[7][12][2];//取得数据库,并定义保存每张表数据的cursor集合DataBase db = new DataBase(SetQuietService.this);Cursor[] cursor = new Cursor[7];@Overridepublic IBinder onBind(Intent arg0){return null;}@Overridepublic void onCreate() {super.onCreate();}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) { //声明一个获取系统音频服务的类的对象 final AudioManager audioManager = (AudioManager)getSystemService(Service.AUDIO_SERVICE); //获取手机之前设置好的铃声模式 final int orgRingerMode = audioManager.getRingerMode(); //每隔一分钟从数据库中取以此数据,获得一次当前的时间,并与用用户输入的上下课时间比较,如果相等,则执行相应的静音或者恢复铃声操作new Timer().schedule(new TimerTask() {@Overridepublic void run() { //取出数据库中每日的数据,保存在cursor数组中 for(int i=0;i<7;i++){cursor[i]=db.select(i);}//从数据库取出用户输入的上课和下课时间,用来设置上课自动静音for(int day=0;day<7;day++){ for(int row=0;row<12;row++){cursor[day].moveToPosition(row);for(int time=0;time<2;time++){temp[day][row][time] = cursor[day].getString(time+5);} if(!temp[day][row][0].equals(""))temp[day][row][0] = temp[day][row][0].substring(temp[day][row][0].indexOf(":")+2);}}//获取当前的是星期几int currentDay = ShareMethod.getWeekDay();for(int j=0;j<12;j++){//获取手机当前的铃声模式int currentRingerMode = audioManager.getRingerMode(); if(temp[currentDay][j][0].equals(ShareMethod.getTime()) && currentRingerMode!=AudioManager.RINGER_MODE_VIBRATE){audioManager.setRingerMode(AudioManager.RINGER_MODE_VIBRATE);//System.out.println("class is on");}if(temp[currentDay][j][1].equals(ShareMethod.getTime()) && currentRingerMode==AudioManager.RINGER_MODE_VIBRATE){audioManager.setRingerMode(orgRingerMode);//System.out.println("class is over");} } }}, 0, 60000);return super.onStartCommand(intent, flags, startId);}}
package zyb.org.service;import java.util.Calendar;import java.util.Date;import temp.DataBase;import temp.ShareMethod;import zyb.org.editschedule.RemindActivity;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.content.SharedPreferences;import android.database.Cursor;public class RemindReceiver extends BroadcastReceiver {//定义保存每张表数据的cursor集合Cursor[] cursor = new Cursor[7];//保存时间,temp[day][row][hm]表示第day+1个tab选项卡中的第row+1个行中用户输入的第一个(即课程开始)时间拆分为时和分//hm为0时表示时,1表示分,2时代表时和分的组合,即未拆分前的字符串String[][][] temp = new String[7][12][3];//将temp数组中的字符串转化为相应的正数,这里去掉了时和分的组合int[][][] start_time = new int[7][12][2];private int advance_time;@Overridepublic void onReceive(Context arg0, Intent arg1) {//取得数据库DataBase db = new DataBase(arg0);//取出数据库中每日的数据,保存在cursor数组中for(int i=0;i<7;i++){cursor[i]=db.select(i);}//从数据库取出用户输入的上课的时和分,用来设置课前提醒for(int day=0;day<7;day++){ for(int row=0;row<12;row++){cursor[day].moveToPosition(row);temp[day][row][2] = cursor[day].getString(5); if(!temp[day][row][2].equals("")){ temp[day][row][2] = temp[day][row][2].substring(temp[day][row][2].indexOf(":")+2); temp[day][row][0] = temp[day][row][2].substring(0, temp[day][row][2].indexOf(":")); temp[day][row][1] = temp[day][row][2].substring(temp[day][row][2].indexOf(":")+1); } else{ temp[day][row][0] = temp[day][row][1] = "0"; } for(int hm=0;hm<2;hm++){ start_time[day][row][hm] = Integer.parseInt(temp[day][row][hm]); }}}//从该context中启动提醒的activity,根据SDK文档的说明,需要加上addFlags()一句Intent remind_intent = new Intent(arg0, RemindActivity.class);remind_intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//获取提前提醒的时间值,如果没有获取到则取默认值30分钟//int advance_time = arg1.getIntExtra("anvance_remindtime", 20);//这里模式一定要设置为MODE_MULTI_PROCESS,否则即使相应的xml文件中数据有更新,RemindReceiver中也不能获取更新后的数据,而是一直获取上次的数据, 除非清空缓存SharedPreferences pre = arg0.getSharedPreferences("time", Context.MODE_MULTI_PROCESS);advance_time = pre.getInt("time_choice", 30);int currentday = ShareMethod.getWeekDay();//System.out.println(advance_time);Calendar c = Calendar.getInstance();//获取当前的时和分int current_hourOfDay = c.get(Calendar.HOUR_OF_DAY);int current_minute = c.get(Calendar.MINUTE);//定义一个标志位,用来排除掉重复的提醒boolean flag = true;//循环判断当天的课前提醒for(int i=0;i<12;i++){if(!(start_time[currentday][i][0]==0 && start_time[currentday][i][1]==0)){//将calendar的时和分设置为提醒时候的时和分c.set(Calendar.HOUR_OF_DAY, start_time[currentday][i][0]);c.set(Calendar.MINUTE, start_time[currentday][i][1]);long remind_time = c.getTimeInMillis()-advance_time*60*1000;Date date=new Date(remind_time);c.setTime(date);//获取设置的提醒的时和分int hourOfDay = c.get(Calendar.HOUR_OF_DAY);int minute = c.get(Calendar.MINUTE);//如果到了设定的提醒时间,就启动提醒的activityif(hourOfDay==current_hourOfDay && minute==current_minute){if(flag){arg0.startActivity(remind_intent);//System.out.println("time remind" + i);flag = false;}}else{flag = true;}}}}}
package zyb.org.service;import android.app.AlarmManager;import android.app.PendingIntent;import android.app.Service;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.content.SharedPreferences;public class LauncherReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context arg0, Intent arg1) {//LauncherReceiver用来监听系统开机事件,如果之前已经设置了启动SetQuietService,即quiet_status为true,//而后来因为某种原因关机了,则开机启动SetQuietServiceSharedPreferences preferences = arg0.getSharedPreferences("switch", Context.MODE_MULTI_PROCESS);Boolean quiet_status = preferences.getBoolean("switch_quiet", false);Boolean remind_status = preferences.getBoolean("switch_remind", false);Intent quiet_intent = new Intent(arg0,SetQuietService.class);Intent remind_intent = new Intent(arg0,RemindReceiver.class);PendingIntent pi_remind = PendingIntent.getBroadcast(arg0, 0, remind_intent, 0);AlarmManager am = (AlarmManager)arg0.getSystemService(Service.ALARM_SERVICE);if(quiet_status){arg0.startService(quiet_intent);}if(remind_status){am.setRepeating(AlarmManager.RTC, System.currentTimeMillis(), 60000, pi_remind);}else{am.cancel(pi_remind);}}}
package zyb.org.editschedule;import zyb.org.androidschedule.R;import android.app.Activity;import android.app.AlertDialog;import android.app.Service;import android.content.Context;import android.content.DialogInterface;import android.content.SharedPreferences;import android.content.DialogInterface.OnClickListener;import android.os.Bundle;import android.os.Vibrator;public class RemindActivity extends Activity{private Vibrator vibrator;@Overridepublic void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);SharedPreferences pre = getSharedPreferences("time", Context.MODE_MULTI_PROCESS);int advance_time = pre.getInt("time_choice", 30);//获取系统的vibrator服务,并设置手机振动2秒vibrator = (Vibrator)getSystemService(Service.VIBRATOR_SERVICE);vibrator.vibrate(2000);// 创建一个对话框final AlertDialog.Builder builder= new AlertDialog.Builder(RemindActivity.this);builder.setIcon(R.drawable.ic_launcher);builder.setTitle("温馨提示");builder.setMessage("童鞋,还有" + advance_time + "分钟就要上课了哦!");builder.setPositiveButton("确定" ,new OnClickListener(){@Overridepublic void onClick(DialogInterface dialog , int which){// 结束该ActivityRemindActivity.this.finish();}}).show();}@Overridepublic void onBackPressed() {super.onBackPressed();// 结束该ActivityRemindActivity.this.finish();}}
点击“关于作者”和“软件相关”,会分别跳转到文件和
网友提醒忘了附上list_v2.xml,list_v.xml和edit_shedule.xml三个布局文件,补充一点:list_v.xml是我第一次设定的listview内的每个item内的布局文件,后来改为了list_v2.xml,在项目中并没有引用list_v.xml文件,因此这里只贴出list_v2.xml和edit_shedule.xml两个布局文件,分别如下:
list_v2.xml文件
<?xml version="1.0" encoding="UTF-8"?>
edit_shedule.xml文件
<?xml version="1.0" encoding="utf-8"?>
更多相关文章
- Android(安卓)APK权限提升到System
- Android(安卓)Studio第一次启动的Fetching android sdk componen
- Android中打电话的数据流程
- Android(安卓)属性动画 源码解析 深入了解其内部实现
- Android(安卓)10 创建文件失败
- Android下SQLite3数据库操作笔记
- mybatisplus的坑 insert标签insert into select无参数问题的解决
- python起点网月票榜字体反爬案例
- NPM 和webpack 的基础使用