转载请注明出处: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、根据用户的设置,上课时自动将手机调节振动,下课后将手机恢复正常铃声;
编辑、添加、删除和查看课程表;
【核心功能】
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保存一标志位,判断是否是第一次创建数据库表。
详细的工程文件截图如下:
各文件的源代码如下,详细的注释代码里面都有,这里不再详细说明:
<AndroidManifest.xml>文件
<AndroidManifest.xml>文件
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="zyb.org.androidschedule"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="17" />
<!-- 授予程序访问振动器的权限 -->
<uses-permission android:name="android.permission.VIBRATE"/>
<!-- 授予程序访问系统开机事件的权限 -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<application
android:icon="@drawable/ic_launcher"
android:allowBackup="true"
android:theme="@style/ConcealTitle" >
<uses-library android:name="android.test.runner"/>
<activity
android:name="zyb.org.load.LoadActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="zyb.org.androidschedule.MainActivity"
android:label="@string/app_name" >
</activity>
<activity
android:name="zyb.org.editschedule.SetActivity"
android:label="@string/app_name" >
</activity>
<activity
android:name="zyb.org.about.AboutUsActivity"
android:label="@string/app_name" >
</activity>
<activity
android:name="zyb.org.version.VersionActivity"
android:label="@string/app_name" >
</activity>
<activity
android:name="zyb.org.editschedule.RemindActivity"
android:theme="@android:style/Theme.Dialog" >
</activity>
<receiver
android:name="zyb.org.service.RemindReceiver"
android:process=":remote">
</receiver>
<receiver
android:name="zyb.org.service.LauncherReceiver"
android:process=":remote">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
<service
android:name="zyb.org.service.SetQuietService" >
<intent-filter>
<action android:name="zyb.org.service.QUIET_SERVICE" />
</intent-filter>
</service>
</application>
</manifest>
<LoadActivity.java>文件,用来设置启动画面
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);
}
}
<activity_load.xml>布局文件,与<LoadActivity.java>文件相对应
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:gravity="center|center"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/load">
</LinearLayout>
<MainActivity.java>文件,设置主界面上的相关操作
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;
@Override
protected 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<tabWidget.getChildCount();i++){
TextView tv = (TextView)tabWidget.getChildAt(i).findViewById(android.R.id.title);
tv.setTextColor(0xff004499);
}
//设置打开时默认的选项卡是当天的选项卡
tabs.setCurrentTab(ShareMethod.getWeekDay());
//用适配器为各选项卡添加所要显示的内容
for(int i=0;i<7;i++){
cursor[i]=MainActivity.db.select(i);
list[i].setAdapter(adapter(i));
}
//声明一个获取系统音频服务的类的对象
final AudioManager audioManager = (AudioManager)getSystemService(Service.AUDIO_SERVICE);
//获取手机之前设置好的铃声模式,该数据将用来传递给activity_set
final int orgRingerMode = audioManager.getRingerMode();
//为退出按钮绑定监听器
exitButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//创建AlertDialog.Builder对象,该对象是AlterDialog的创建器,AlterDialog用来创建弹出对话框
final AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
exit(builder);
}
});
//为设置按钮绑定监听器
setButton.setOnClickListener(new OnClickListener() {
@Overr