Android多功能课程表项目实现(完整版)

博主分享了自己制作的一款Android多功能课程表项目的实现过程,包括从构思到开发,期间遇到的问题及解决办法。项目源码已开源在Github,并在小米应用商店上线。
摘要由CSDN通过智能技术生成

转载请注明出处: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保存一标志位,判断是否是第一次创建数据库表。


详细的工程文件截图如下:

各文件的源代码如下,详细的注释代码里面都有,这里不再详细说明:
<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
评论 39
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值