-->
当前位置:首页 > 题库 > 正文内容

移动应用开发 课程设计(大作业) by:Luz

Luz4年前 (2021-08-08)题库2896

题目信息

题目

实现“获取手机通话记录”功能的Android程序。

功能要求:

1)  在模拟器中创建联系人并分别进行通话,示例如下:

                                               

2 在自行开发的APP中,以ListView组件形式显示ID、联系人姓名及联系人电话号码,示例如下:

image.png

image.png

 

课程设计结果提交方式:

17周结束前将完整android项目代码电子版+设计文档纸质版统一上交。

设计文档要求:

文档具体书写内容要求如下:

1)  系统的需求分析

2)  系统的概要设计

3)  设计与实现部分

4)  运行画面截图

5)每一部分附上关键性代码

6)课程设计总结体会

评分标准:

根据提交的设计文档、程序功能的实现进行考核:

1)  无任何文档,无程序, 0

2)  文档混乱,没有思路,程序不能运行,10-20分;

3)  文档描述清晰,程序实现了基本功能,20-30分;

4)  文档描述清晰准确,思路清晰,程序实现了要求的所有功能,30-50分;

5)文档完备,设计合理有创新,报告清晰明确,深入分析了自己进行实验的体会感想,程序实现了全部功能,功能完善,并有其它的创新实现50-60分。

 



课程设计报告

目录

系统需求分析... 2

系统概要设计... 2

系统关键性代码... 3

系统测试与运行截图... 10

课程设计总结体会... 12

 


 

系统需求分析

环境需求分析

开发环境:Eclipse

开发语言:JAVA

手机运行:Android2.3.3以及上版本开发软件(API10

所需插件:JDK

基本功能说明

本软件需要实现从手机中获取通话记录的功能。其中,通话记录指手机自带的电话(拨号器)所拨出与收到电话的记录。在自行开发的APP中,以ListView组件形式显示ID、联系人姓名及联系人电话号码。

拓展功能说明

基于线程循环的程序界面实时刷新(通话记录实时获取)

若无此功能,则程序只会在加载时读取一次通话记录。由于只在onCreate中触发更新事件,因此在手机的通话记录更新后(如在程序使用时收到了一通电话),程序并不会再次更新。只有杀死程序进程重启程序后才会再次从系统中获取通话记录。

加入功能后,当系统中的通话记录改变时,程序立即更新,无需重启程序。由于在单独的线程中更新界面,程序主线程不会阻塞,后续程序功能的开展。

 

基于Service的软件背景音乐

软件播放背景音乐,让使用者在查看通话记录时放松心情。

 

系统概要设计

界面设计

本程序主界面显示ListView,在ListView中显示ID、联系人姓名、联系人电话号码。当 通话记录中所包含的电话号码不存在于通讯录列表中时,联系人姓名显示为“未知”。并添加背景图,简洁美观。

通话记录获取功能设计

在安卓系统中,每个应用程序的数据都是采用私有的形式进行操作的,不管这些数据是用文件还是数据库进行保存,都不能被外部应用程序访问。但是在本程序中,用户需要在不同程序之间进行数据交换,即在本程序与系统自带拨号器间进行数据交换。因此,需要使用安卓提供的ContentProvider类,此类的作用是将不同应用程序的数据操作标准联系起来,并且将各个应用程序的数据操作标准表明给其他应用程序。这样,系统拨号器的数据就可以按照ContentProvider所指定的标准被本程序所访问和操作。

image.png

基于runOnUiThread的线程刷新设计

程序启动后另起一个线程实现通讯录的显示功能,AndroidThread+Handler方式实现线程在主界面上的UI刷新较为繁琐,本程序使用Activity提供的另外一种简单的方法runOnUiThread实现线程中的UI更新操作。

Activity.this. runOnUiThread(new Runnable() {

@Override

public void run() {

// refresh ui 的操作代码

}

});

 

基于service的背景音乐播放

在播放音乐的时候把MediaPlayer放在Service中,因为如果放在Activity中会使得界面特别卡。而且音乐不能放到后台里播放,一旦退出Activity,音乐就会暂停播放,Activitiy来启动这个Service。要通过UIService交互,可以通过Intent对象传递消息。

系统关键性代码

MainActivity.java

package com.example.luz;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

import android.os.Bundle;

import android.provider.CallLog;

import android.provider.CallLog.Calls;

import android.app.Activity;

import android.database.Cursor;

import android.view.Menu;

import android.widget.ListView;

import android.widget.SimpleAdapter;

import android.util.Log;

import android.content.Intent;

 

public class MainActivity extends Activity {

private Intent intent;

private Thread thread;

private Runnable runOnUiThread;

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        gettxl();

        startService(new Intent(MainActivity.this, musicService.class));

        thread = new  Thread( new  Runnable() {

          

            @Override

            public  void  run() {

             while(true){

                try  {

                    //延迟两秒

                    Thread.sleep(  2000  );

                }  catch  (InterruptedException e) {

                    e.printStackTrace();

                }

 

                runOnUiThread( new  Runnable() {

                    @Override

                    public  void  run() {

                     gettxl();

                    }

                });

 

            }}

        });

        thread.start();

      

    }

 

    private void contactput(String string, String string2) {

  // TODO Auto-generated method stub

 

 }

 

 @Override

    public boolean onCreateOptionsMenu(Menu menu) {

        // Inflate the menu; this adds items to the action bar if it is present.

        getMenuInflater().inflate(R.menu.main, menu);

        return true;

    }

 @Override

 protected void onDestroy() {

    if(thread!=null) {

           thread.interrupt();

           thread=null;

       }

    Log.i("提示:","中断线程");

    super.onDestroy();

 }

 public void gettxl(){

     ListView callList=null;

     Cursor result=null;

     List<Map<String,Object>>allCalls=null;

     SimpleAdapter simple =null;

     callList=(ListView) super.findViewById(R.id.callList);

     result=super.getContentResolver().query(

       CallLog.Calls.CONTENT_URI, null,null, null, null);

     startManagingCursor(result);

     allCalls=new ArrayList<Map<String,Object>>();

     for(result.moveToFirst();!result.isAfterLast();result

       .moveToNext()){

      Map<String,Object> contact=new HashMap<String,Object>();

      contact.put("_id",

        result.getInt(result.getColumnIndex(Calls._ID)));

      String nameTemp =result.getString(result.getColumnIndex(CallLog.Calls.CACHED_NAME));

      if(nameTemp==null||"".equals(nameTemp)){

       nameTemp="未知";

     

      }

      contact.put("name",nameTemp);

      contact.put("number",

        result.getString(result.getColumnIndex(CallLog.Calls.NUMBER)));

      allCalls.add(contact);

     

     }

     simple=new SimpleAdapter(this,allCalls,R.layout.calls,

       new String[]{"_id","name","number"},new int[]{R.id._id,

       R.id.name,R.id.number});

     callList.setAdapter(simple);

 }

}

 

musicService.java

 

package com.example.luz;

import android.app.Service;

import android.content.Intent;

import android.media.MediaPlayer;

import android.os.Binder;

import android.os.IBinder;

 

public class musicService extends Service implements

        MediaPlayer.OnCompletionListener {

    MediaPlayer player;

    private final IBinder binder = new AudioBinder();

 

    @Override

    public IBinder onBind(Intent intent) {

        return binder;

    }

 

    public void onCreate() {

        super.onCreate();

        player = MediaPlayer.create(this, R.raw.mojito);

        player.setOnCompletionListener(this);

        player.setLooping(true);//

    }

 

    @Override

    public int onStartCommand(Intent intent, int flags, int startId) {

        super.onStartCommand(intent, flags, startId);

        if (!player.isPlaying()) {

            new MusicPlayThread().start();

        } else

            player.isPlaying();

        return START_STICKY;

    }

    public void onCompletion(MediaPlayer mp) {

        stopSelf();

 

    }

 

    public void onDestroy() {

        super.onDestroy();

        if (player.isPlaying()) {

            player.stop();

        }

        player.release();

    }

 

    public class AudioBinder extends Binder {

        public musicService getService() {

            return musicService.this;

        }

    }

 

    private class MusicPlayThread extends Thread {

        public void run() {

            if (!player.isPlaying()) {

                player.start();

            }

        }

    }

 

}

 

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

    package="com.example.luz"

    android:versionCode="1"

    android:versionName="1.0" >

 

    <uses-sdk

        android:minSdkVersion="8"

        android:targetSdkVersion="10" />

<uses-permission android:name="android.permission.READ_CONTACTS"/>

<uses-permission android:name="android.permission.WRITER_CONTACTS"/>

   

    <application

        android:allowBackup="true"

        android:icon="@drawable/ic_launcher"

        android:label="@string/app_name"

        android:theme="@style/AppTheme" >

        <activity

            android:name="com.example.luz.MainActivity"

            android:label="@string/app_name" >

            <intent-filter>

                <action android:name="android.intent.action.MAIN" />

 

                <category android:name="android.intent.category.LAUNCHER" />

            </intent-filter>

        </activity>

        <service

            android:name=".musicService"

            android:exported="true"

            android:enabled="true"

            >

        </service>

    </application>

 

</manifest>

 

 

activity_main.xml

<LinearLayout 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:background="@drawable/bj"

    android:orientation="vertical"

    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=".MainActivity" >

 

    <ListView

        android:id="@+id/callList"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content" >

    </ListView>

 

</LinearLayout>

 

 

calls.xml

<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:tools="http://schemas.android.com/tools"

    android:layout_width="fill_parent"

    android:layout_height="fill_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=".MainActivity"

    android:orientation="vertical" >

 

    <TableRow>

        <TextView

        android:id="@+id/_id"

        android:textSize="20px"

        android:layout_width="30px"

        android:layout_height="wrap_content"/>

        <TextView

        android:id="@+id/name"

        android:textSize="20px"

        android:layout_width="180px"

        android:layout_height="wrap_content"/>

        <TextView

        android:id="@+id/number"

        android:textSize="20px"

        android:layout_width="180px"

        android:layout_height="wrap_content"/>

        </TableRow>>

 

</TableLayout>

 

 

系统测试与运行截图

image.png

0‑1 第一次打开程序图

软件第一次运行时截图如图1所示,其中显示了5个通话记录。此时,背景音乐同时响起

我们让软件进程常驻,避免界面切换后系统杀死进程导致再次打开软件时软件重新加载。

不退出程序,避免重新打开程序后再次触发onCreate事件。(可以听到背景音乐并未关闭)

image.png

2 拨号截图

如图2所示,再次拨号。

image.png

3 第二次切换到程序界面

如图3所示,切换到程序界面,程序主线程未重新加载,但主界面已经被刷新(刚才的通话记录已经出现)

课程设计总结体会

本次的课程设计是一次很宝贵的Android开发的经验,在课程设计中,我对安卓系统中的线程调用与Service有了更深的了解。本程序使用线程实现通话记录在程序界面上的刷新功能,通过service实现背景音乐播放功能。基本达到预期要求。设计中用到很多知识上课都没有讲到过,需要上网查阅相关资料,培养了我自主学习的能力。从各种文档的阅读到开始的需求分析、概念结构设计、逻辑结构设计、物理结构设计。亲身体验了一回系统的设计开发过程。很多东西书上写的很清楚,貌似看着也很简单,思路非常清晰。但真正需要自己想办法去设计一个系统的时候才发现其中的难度。经常做到后面突然就发现自己一开始的设计有问题,然后又回去修改程序,在各种反复中不断完善自己的想法。程序编写过程中,经常遇到不明原因的程序闪退、功能无法使用等错误,学习了安卓代码的调试,积累了宝贵的软件测试经验。

 


发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。