安卓-通讯录

一、实验目的

练习掌握 Android 软件开发基本编程技术、Android 系统 SQLite 数据库的使用、通话、短信的使用等,设计制作一 Android 通讯录软件。

二、实验内容

实现的通讯录功能和界面可在实验开发中由每位同学自己设计,但必须使用SQLite 数据库保存通讯录信息。以下功能和软件界面供参考:仿照一般手机通讯录的使用界面和功能,主要功能可包括: (1)可以添加、删减联系人
(2)联系人的信息包括:姓名、手机号码、工作单位、群组、电子邮件、手机铃声
(3)选择联系人后,可以快速进行操作,如:拨打电话发送短信、查看详细、移出群组、移动分组、删除联系人等。查看详细时显示手机号码、群组、和设定的手机铃声以及同该联系人的通话记录。
(4)在联系人界面,可以查看各群组。点击群组,跳出对应联系人。
(5)有拨号键盘,点击数字将号码显示出来,并可以对手机号码进行删减
(6)可以发送信息,显示信息记录
(7)发送信息时,可以快速选择现有联系人。

三、实验要求

(1)每位同学独立设计软件功能、完成软件的开发与测试。
(2)每位同学独立完成实验报告(根据模板),并提交至网络课堂。

四、数据代码及运行结果截图

全部代码如图所示

//mainactivity.java 代码太多了,所以其他文件的代码就没有贴上。
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.app.NotificationCompat;
import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import android.app.AlertDialog;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.Toast;
import com.google.android.material.navigation.NavigationView;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.pan.coursedesign.recyclerview.Person;
import com.pan.coursedesign.recyclerview_logs.recording;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.litepal.crud.DataSupport;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.List;
import java.util.Map;
import java.util.Set;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class MainActivity extends AppCompatActivity {
    AlertDialog.Builder builder5;//自定义
    AlertDialog dialog;
    private int tag = 0;
    private int DataDownTag = 0;
    private DrawerLayout mDrawerLayout;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //自定义Toolbar并设置进系统
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        //因为滑动菜单不容易被用户知道,所以加一个折叠按钮
        ActionBar actionBar = getSupportActionBar();//得到actionBar的实例(toolbar实现的哦,也就是toolbar对象)
        if (actionBar != null) { //有的话
            actionBar.setDisplayHomeAsUpEnabled(true); //显示一个home按钮,HomeAsUp这个按钮的id永远是Home
            actionBar.setHomeAsUpIndicator(R.drawable.ic_menu); //设置一个图标
        }

        //获取抽屉的实例用于打开和关闭抽屉的事件
        mDrawerLayout = findViewById(R.id.my_drawer);

        //默认加载的碎片,text1
        replaceFragment(new Contacts_Fragment());


        //启动弹窗
        //从文件读取tag数据
        SharedPreferences preferences = getSharedPreferences("statata", MODE_PRIVATE);
        tag = preferences.getInt("tag", 0);
        if (tag == 0) { //tag没被修改,显示弹窗
            loding();
        }
        //设置侧面munu的点击事件
        NavigationView navigationView = (NavigationView) findViewById(R.id.my_nav_view);
        navigationView.setCheckedItem(R.id.nav_text1);
        navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(MenuItem item) {
                //详细设计抽屉菜单的点击事件
                switch (item.getItemId()) {
                    case R.id.nav_text1:
                        replaceFragment(new Contacts_Fragment());
                        mDrawerLayout.closeDrawer(navigationView);
                        break;
                    case R.id.nav_text2:
                        replaceFragment(new Call_Fragment());
                        mDrawerLayout.closeDrawer(navigationView);
                        break;
                    case R.id.nav_text3:
                        replaceFragment(new Call_logs_Fragment());
                        mDrawerLayout.closeDrawer(navigationView);
                        break;
                    case R.id.nav_text4:
                        replaceFragment(new Help_Fragment());
                        mDrawerLayout.closeDrawer(navigationView);
                        break;
                    case R.id.nav_text5:
                        replaceFragment(new About_Fragment());
                        mDrawerLayout.closeDrawer(navigationView);
                        break;
                    default:
                        break;
                }
                return true;
            }
        });
    }


    //动态替换碎片
    private void replaceFragment(Fragment fragment) {
        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction transaction = fragmentManager.beginTransaction();
        transaction.replace(R.id.DTFragment, fragment);
        transaction.commit();
    }

// ----toolbar逻辑----

    //传统的方法实现菜单的植入(command + O快捷键)
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        //设置一个menu
        getMenuInflater().inflate(R.menu.toolbar, menu);
        return true;
    }


    //tab按键事件
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        //设置menu的选项点击事件
        switch (item.getItemId()) {
            case android.R.id.home://这是内置的哦
                mDrawerLayout.openDrawer(GravityCompat.START);//将滑动菜单显示出来,打开抽屉 参数是方式和xml设置的保持一致
                break;
            case R.id.DataDown:
                DataDown();//阿帕奇服务器上下载json数据
                break;
            case R.id.DataUp:
                try {
                    UpData(GetJsonString());//先把数据导出成json文本在作为数据上传到服务器
                } catch (JSONException e) {
                    e.printStackTrace();
                }
//                Toast.makeText(this,"此功能开发中...",Toast.LENGTH_LONG).show();
                break;
            case R.id.settings:
                try {
                    ExportData();
                    Toast.makeText(this, "导出成功: 内部目录file文件夹下", Toast.LENGTH_LONG).show();
                } catch (JSONException e) {
                    e.printStackTrace();
                }
                break;
            case R.id.settings_1:
                if (Import().isEmpty()) {
                    Toast.makeText(this, "导入失败,没有数据", Toast.LENGTH_LONG).show();
                } else {
                    ImportData();
                    Toast.makeText(this, "导入成功", Toast.LENGTH_LONG).show();
                }
                break;
            case R.id.settings_2:
                delall();
                break;
            default:
        }
        return true;
    }


    //1.下载时提示框
    public void DataDown() {
        //启动弹窗
        //从文件读取tag数据
        SharedPreferences preferences = getSharedPreferences("DataDown", MODE_PRIVATE);
        DataDownTag = preferences.getInt("DataDownTag", 0);
        if (DataDownTag == 0) { //tag没被修改,显示弹窗
            //inflate方法返回的是一个view(自定义那个),
            View loginview = LayoutInflater.from(this).inflate(R.layout.datadown_dialog_info, null);
            //loginview里的控件声明一下
            CheckBox checkBox = loginview.findViewById(R.id.info_2);
            Button btnLogin = loginview.findViewById(R.id.datadown);

            btnLogin.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    //把状态计入文件供下次读取
                    if (checkBox.isChecked()) {//如果被选中
                        SharedPreferences.Editor editor = getSharedPreferences("DataDown", MODE_MULTI_PROCESS).edit();
                        editor.putInt("DataDownTag", 1);
                        editor.apply();
                    }
                    dialog.dismiss();
                    DownData();
                }
            });
            //设置Dialog和View
            builder5 = new AlertDialog.Builder(this);
            dialog = builder5.setTitle("重要提示").setView(loginview).setCancelable(false).show();
        } else {
            DownData();
        }
    }

    //从服务器下载json数据
    public void DownData() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    OkHttpClient client = new OkHttpClient();
                    Request request = new Request.Builder()
                            // 指定访问的服务器地址是电脑本机
                            .url("http://172.20.10.5:8081/pro")
                            .build();
                    Response response = client.newCall(request).execute();
                    String responseData = response.body().string();
                    parseJSONWithGSON(responseData);//下载json数据导入解析
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    //导入json进行解析的方法
    private void parseJSONWithGSON(String jsonData) {

        //Log.d("aaaaa---", jsonData);
        Contacts_Fragment contacts_fragment = (Contacts_Fragment) getSupportFragmentManager().findFragmentById(R.id.DTFragment);
        Gson gson = new Gson();
        List<Person> appList = gson.fromJson(jsonData, new TypeToken<List<Person>>() {
        }.getType());
        //c=appList;
        int tag = 0;
        //遍历并先把数据存入数据库
        for (Person person : appList) {
            person.setTel(formatInviteCode(person.getTel()));//获取的数据同样要处理
            if (RemoveRepetition(person.getName())) { //只有数据库没有时才更新
                contacts_fragment.Persons.add(person);
                person.save();
                tag = 1;
            }
        }
        if (tag == 1) {//只要有一个变就刷新
            //这个方法是在任务线程执行的,需要去主线程更新ui
            //加个下载成功的通知
            DataNotification();
            MainActivity.this.runOnUiThread(new Runnable() {
                public void run() {
                    contacts_fragment.load();
                }
            });
        } else {
            DataFailNotification();//找不到服务器/导入的数据都有
        }
    }

    public Boolean RemoveRepetition(String name) {
        List<Person> Persons = DataSupport.select("name", "Tel", "Email").where("name like ?", "%" + name + "%").find(Person.class);
        if (Persons.size() != 0) {
            return false;//如果数据库有,不更新
        }
        return true;
    }

    //下载成功的通知
    public void DataNotification() {
        NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        Notification notification = new NotificationCompat.Builder(this, "5996773")
                .setContentTitle("文件下载的通知")//标题内容
                .setContentText("导入数据成功!")//正文内容
                .setWhen(System.currentTimeMillis())//指定通知被创建的时间
                .setSmallIcon(R.mipmap.ic_launcher)//设置通知小图标
                .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))//设置通知大图标
                .setVibrate(new long[]{0, 1000, 1000, 1000})//通知到了让手机震动
                .setLights(Color.GREEN, 1000, 1000)//设置手机前置LED灯的显示效果
                .setPriority(NotificationCompat.PRIORITY_MAX)//设置通知的重要程度
                .build();//build完算是构建完成notification对象
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel("5996773", "安卓10的通知哦", NotificationManager.IMPORTANCE_HIGH);
            channel.enableLights(true);//是否在桌面icon右上角展示小红点
            channel.setLightColor(Color.GREEN);//小红点颜色
            channel.setShowBadge(false); //是否在久按桌面图标时显示此渠道的通知
            manager.createNotificationChannel(channel);//将channel设置进manager
        }
        //id唯一即可
        manager.notify(1, notification);
    }

    //下载失败的通知
    public void DataFailNotification() {
        NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        Notification notification = new NotificationCompat.Builder(this, "5996774")
                .setContentTitle("文件下载的通知")//标题内容
                .setContentText("文件下载成功,但您不需要导入!")//正文内容
                .setWhen(System.currentTimeMillis())//指定通知被创建的时间
                .setSmallIcon(R.mipmap.ic_launcher)//设置通知小图标
                .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))//设置通知大图标
                .setVibrate(new long[]{0, 1000, 1000, 1000})//通知到了让手机震动
                .setLights(Color.GREEN, 1000, 1000)//设置手机前置LED灯的显示效果
                .setPriority(NotificationCompat.PRIORITY_MAX)//设置通知的重要程度
                .build();//build完算是构建完成notification对象
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel("5996774", "安卓10的通知哦", NotificationManager.IMPORTANCE_HIGH);
            channel.enableLights(true);//是否在桌面icon右上角展示小红点
            channel.setLightColor(Color.GREEN);//小红点颜色
            channel.setShowBadge(false); //是否在久按桌面图标时显示此渠道的通知
            manager.createNotificationChannel(channel);//将channel设置进manager
        }
        //id唯一即可
        manager.notify(2, notification);
    }


    //2.上传json到服务器
    public void  UpData(String body){
        new Thread(new Runnable(){
            @Override
            public void run(){
                String url="http://172.20.10.5:8081/air";//你要訪問的地址
                String mesg = null;//定义服务器返回的结果
                HttpClient httpClient = new HttpClient();//构建HttpClient实例
                httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(60000); //设置请求超时时间
                httpClient.getHttpConnectionManager().getParams().setSoTimeout(60000);//设置响应超时时间
                PostMethod postMethod=new PostMethod(url);//构造PostMethod的实例
                postMethod.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET,"utf-8");
                String jsonString="{'data':" + body + "}";
                //com.alibaba.fastjson.JSONObject意思是导入阿里的parseObject,parseObject第一个参数是json对象
                Map<String,Object> map = com.alibaba.fastjson.JSONObject.parseObject(jsonString,Map.class);
                Set<String> set = map.keySet();
                for(String s : set){
                    postMethod.addParameter(s,map.get(s).toString());
                }
                try {
                    httpClient.executeMethod(postMethod);//执行post请求
                    mesg = postMethod.getResponseBodyAsString();//可以对响应回来的报文进行处理
                    //Log.d("aaaa--", mesg);//获取成功!!!!
                } catch (HttpException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }finally{
                    if(mesg!=null){//有数据
                        DataupNotification();//文件上传成功的通知
                    }
                    //关闭连接释放资源的方法
                    postMethod.releaseConnection();
                    httpClient.getHttpConnectionManager().closeIdleConnections(0);
                }
            }
        }).start();
    }

    //上传成功的通知
    public void DataupNotification() {
        NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        Notification notification = new NotificationCompat.Builder(this, "599111")
                .setContentTitle("文件上传的通知")//标题内容
                .setContentText("上传数据成功!")//正文内容
                .setWhen(System.currentTimeMillis())//指定通知被创建的时间
                .setSmallIcon(R.mipmap.ic_launcher)//设置通知小图标
                .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))//设置通知大图标
                .setVibrate(new long[]{0, 1000, 1000, 1000})//通知到了让手机震动
                .setLights(Color.GREEN, 1000, 1000)//设置手机前置LED灯的显示效果
                .setPriority(NotificationCompat.PRIORITY_MAX)//设置通知的重要程度
                .build();//build完算是构建完成notification对象
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel("599111", "安卓10的通知哦", NotificationManager.IMPORTANCE_HIGH);
            channel.enableLights(true);//是否在桌面icon右上角展示小红点
            channel.setLightColor(Color.GREEN);//小红点颜色
            channel.setShowBadge(false); //是否在久按桌面图标时显示此渠道的通知
            manager.createNotificationChannel(channel);//将channel设置进manager
        }
        //id唯一即可
        manager.notify(3, notification);
    }


    //3.导出json到文件
    public void ExportData() throws JSONException {
        String str = GetJsonString();
        save(str);
    }

    //导出json文本
    public String GetJsonString() throws JSONException {
        //获取碎片实例以调用碎片中的方法
        Contacts_Fragment contacts_fragment = (Contacts_Fragment) getSupportFragmentManager().findFragmentById(R.id.DTFragment);
        List<Person> Persons = contacts_fragment.Persons;

        //转换list为json
        JSONArray jsonArray = new JSONArray();
        JSONObject jsonObject = new JSONObject();//这个巨坑,注意包
        JSONObject tmpObj = null;
        int count = Persons.size();
        for (int i = 0; i < count; i++) {
            tmpObj = new JSONObject();
            tmpObj.put("name", Persons.get(i).getName());
            tmpObj.put("Email", Persons.get(i).getEmail());
            tmpObj.put("Tel", Persons.get(i).getTel());
            jsonArray.put(tmpObj);
            tmpObj = null;
        }
        String personInfos = jsonArray.toString(); // 将JSONArray转换得到String
        //Log.d("DDDDD",personInfos);
        return personInfos;
    }
    //将一段json文本保存到文件中去
    public void save(String inputText) {
        FileOutputStream out = null;
        BufferedWriter writer = null;
        //command + alt + t 快速生成
        try {
            File file = new File(getCacheDir().getPath(), "data.json");
            if (file != null) {
                file.delete();
            } else {
                file.createNewFile();
            }
            out = openFileOutput("data.json", Context.MODE_PRIVATE);
//             out = new FileOutputStream(file);
            // OutputStreamWriter是从字符流到字节流的桥接:字节流搞成了字符流传递给缓冲流
            writer = new BufferedWriter(new OutputStreamWriter(out));
            // 写入
            writer.write(inputText);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (writer != null) {
                    writer.close();//关闭上层流(缓冲流),下层数据流就自动关了
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    //4.从文件导入json
    public void ImportData() {
        String str1 = Import();
        parseJSONWithGSON(str1);//显示
    }
    //从文件中读取json文件
    public String Import() {
        //准备从文件读数据
        FileInputStream in = null;
        //缓冲流,输入
        BufferedReader reader = null;
        StringBuilder content = new StringBuilder();
        try {
            in = openFileInput("data.json");
            reader = new BufferedReader(new InputStreamReader(in));
            String line = "";
            //reader.readLine()是读取一行
            while ((line = reader.readLine()) != null) {
                content.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return content.toString();
    }
    //初始化加载
    private void loding() {
        //inflate方法返回的是一个view(自定义那个),
        View loginview = LayoutInflater.from(this).inflate(R.layout.ui_dialog_info, null);
        //loginview里的控件声明一下
        CheckBox checkBox = loginview.findViewById(R.id.info_2);
        
Button btnLogin = loginview.findViewById(R.id.info_3);
        btnLogin.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
//              把状态计入文件供下次读取
                if (checkBox.isChecked()) {//如果被选中
                    SharedPreferences.Editor editor = getSharedPreferences("statata", MODE_MULTI_PROCESS).edit();
                    editor.putInt("tag", 1);
                    editor.apply();
                }
                dialog.dismiss();
            }
        });
        //设置Dialog和View
        builder5 = new AlertDialog.Builder(this);
        dialog = builder5.setTitle("重要信息").setView(loginview).setCancelable(false).show();
    }
    //5.一键删除
    public void delall() {
        DataSupport.deleteAll(Person.class);
        DataSupport.deleteAll(recording.class);
        Toast.makeText(this, "删除全部数据成功!", Toast.LENGTH_SHORT).show();
    }
    //处理一下系统获取联系人时字符串的-/空格
    public String formatInviteCode(String str1) {
        String str2 = "";
        for (int i = 0; i < str1.length(); i++) {
            if (Character.isDigit(str1.charAt(i))) {//判断被索引处的字符是不是数字
                str2 += str1.charAt(i);
            }
        }
        return str2;
    }
}

五、错误总结

1、错误:

no such column: userName

解决:格式错误,类型TEXT前面必须有一个空格!

UserInfoEntry.COLUMN_USER_NAME + " TEXT NOT NULL, " 

2、类型前面全部都添加了空格,仍旧报错:

no such column: userName

解决:数据库没有更新,更新版本号。在生产应用程序中,可能会修改此方法以更改表格,而不是删除它,以便不删除现有数据。
新手学习中,尚不知道如何修改。
//如果更改数据库架构,则必须增加数据库版本

private static final int DATABASE_VERSION = 4; 
   @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {
//        //在onUpgrade中,删除表(如果存在)
        sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + UserInfoEntry.TABLE_NAME);
//        //调用onCreate并传入SQLiteDatabase(传入onUpgrade)记得更新版本号
        onCreate(sqLiteDatabase);
    }

3、错误:

android.database.CursorIndexOutOfBoundsException: Index -1 requested,
with a size of 1

解决:下标越界,cursor下标从-1开始,而不是0,需要移动,添加if语句。其实还是不太明白,为什么移动到第一个就可以了。

if (cursor.moveToFirst()){
queryPassword=cursor.getString(cursor.getColumnIndex(UserInfoContract.UserInfoEntry.COLUMN_USER_PASSWORD));
}

4、错误:

android.database.sqlite.SQLiteException: no such column:

错误例子:

return mDb.update(DATABASE_TABLE, args, KEY_SSID + "=" + ssid , null) > 0;

原因:
在执行数据库的增删改查操作时,如:update、query等方法,传入的参数是字符串类型。
其实这些方法会将参数拼接成sql语句,而字符串类型需要用引号引上
所以上方错误的代码应改为:

return mDb.update(DATABASE_TABLE, args, KEY_SSID + "='" + ssid + "'", null) > 0;

六、个人心得体会

SQLite的基本数据类型:Byte,Long,Short,Integer,Float,Double,String,Boolean,byte[]
理论存储容量为140TB
SQLiteOpenHelper
既然是数据库的增删改查,我们首先需要一个数据库,而数据库要通过SQLiteOpenHelper的子类生成,所以首先需要建一个类来继承SQLiteOpenHelper。由于这个类是一个抽象类,我们需要实现他的构造方法和抽象方法。所以:

public class DBHelper extends SQLiteOpenHelper {
    // 数据库默认名字
    public static final String db_name = "test.db";
    public DBHelper(Context context, int version) {
        super(context, db_name, null, version);
    }
    @Override
    public void onCreate(SQLiteDatabase db) {
    }
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    }
}

需要重载的方法
onCreate:创建表和一些基本属性。
onUpgrade:数据库需要更新的时候使用,前提是已经存在了一个相同的数据库,需要新加表,或者原来的表字段要修改。
举例:现在创建一个名为table1的表:直接执行SQL语句

public class DBHelper extends SQLiteOpenHelper {
    public static final String db_name = "test.db";
    public DBHelper(Context context, int version) {
        super(context, db_name, null, version);
    }
    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("create table table1 (" +
                " _byte byte," +
                " _long long," +
                " _text text," +
                " _short short," +
                " _int int," +
                " _float float," +
                " _double double," +
                " _boolean boolean," +
                " _blob blob" +
                ")");
    }
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    }
}

表的增删改查

public class DBManger {
    private Context context;
    private static DBManger instance;
    // 操作表的对象,进行增删改查
    private SQLiteDatabase writableDatabase;
    private DBManger(Context context) {
        this.context = context;
        DBHelper dbHelper = new DBHelper(context, 1);
//通过DBHelper的getWritableDatabase方法得到SQLiteDatabase对象,SQLiteDatabase可以对数据库表进行操作
        writableDatabase = dbHelper.getWritableDatabase();
    }
    public static DBManger getInstance(Context context) {
        if (instance == null) {
            synchronized (DBManger.class) {
                if (instance == null) {
                    instance = new DBManger(context);
                }
            }
        }
        return instance;
    }
}

增加:

public void add() {
        ContentValues contentValues = new ContentValues();
        byte _byte = Byte.MAX_VALUE;
        contentValues.put("_byte", _byte);
        long _long = Long.MAX_VALUE;
        contentValues.put("_long", _long);
        String _text = "字符串";
        contentValues.put("_text", _text);
        short _short = Short.MAX_VALUE;
        contentValues.put("_short", _short);
        int _int = Integer.MAX_VALUE;
        contentValues.put("_int", _int);
        float _float = Float.MAX_VALUE;
        contentValues.put("_float", _float);
        double _double = Double.MAX_VALUE;
        contentValues.put("_double", _double);
        boolean _boolean = true;
        contentValues.put("_boolean", _boolean);
        byte[] _byteArr = {Byte.MIN_VALUE, Byte.MAX_VALUE};
        contentValues.put("_blob", _byteArr);
        writableDatabase.insert("table1", null, contentValues);
    }

删:删除_int = Integer.MAX_VALUE的值

public void del() {
        writableDatabase.delete("table1", "_int = ?", new String[]{Integer.MAX_VALUE + ""});
}

改:调用update方法,参数依次:表名、包裹、条件、条件的值

public void update() {
        ContentValues contentValues = new ContentValues();
        contentValues.put("_text", "修改后的字符串");
        writableDatabase.update("table1", contentValues, "_text = ?", new String[]{"字符串"});
 }

查:首先query方法返回了一个Cursor对象,用来定位。
Query的参数:
String table:表名
String[] columns:需要被查询的列名
String selection:代表只查多少条数据,比如只查10条数据,就直接传递一个10就行了。
String[] selectionArgs:代表只查多少条数据,比如只查10条数据,就直接传递一个10就行了。
String groupBy:将相同值划分为一组
String having:条件判断的参数,不过这个要跟groupby这个参数同时存在,也就是要同时使用。也就是说,在groupby筛选后的数据中,再使用这个所谓的having再筛选一次。
String orderBy:代表排序,可以传某个字段,比如_byte,这就代表按照这个字段排序,默认是升序,也就是从小到大排序,我们可以这样传递参数,让其降序排列_byte desc,如果是_byte asc就是升序,由于默认升序,所以这个asc也就省略了。
String limit:代表只查多少条数据,比如只查10条数据,就直接传递一个10就行了。

public String select() {
    Cursor cursor = writableDatabase.query("table1", null, null, null, null, null, null, null);
    int position = cursor.getPosition();
    Log.e(TAG, "select: 游标默认位置:" + position);
    String result = "";
    while (cursor.moveToNext()) {
        byte _byte = (byte) cursor.getShort(cursor.getColumnIndex("_byte"));
        long _long = cursor.getLong(cursor.getColumnIndex("_long"));
        String _text = cursor.getString(cursor.getColumnIndex("_text"));
        short _short = cursor.getShort(cursor.getColumnIndex("_short"));
        int _int = cursor.getInt(cursor.getColumnIndex("_int"));
        float _float = cursor.getFloat(cursor.getColumnIndex("_float"));
        double _double = cursor.getDouble(cursor.getColumnIndex("_double"));
        boolean _boolean = cursor.getInt(cursor.getColumnIndex("_boolean")) == 1 ? true : false;
        byte[] _byteArr = cursor.getBlob(cursor.getColumnIndex("_blob"));
        result += String.format("_byte = %s, _long = %s, _text = %s, _short = %s, _int = %s, _float = %s, _double = %s, _boolean = %s, _byteArr = %s",
                _byte, _long, _text, _short, _int, _float, _double, _boolean, _byteArr) + "\n";
    }
    return result;
}
  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
目 录 1 前言 1 2 系统的需求分析 2 2.1 需求分析 2 2.1.1 基本功能需求 2 2.1.2 系统用例分析 2 2.2 总体设计方案 5 2.2.1 系统模块关系与划分 5 3 系统的概要设计 6 3.1 通讯录需求分析 6 3.1.1 新建、编辑联系人 6 3.1.2 查找联系人 6 3.1.3 通讯功能 6 3.1.4 个人中心 7 3.1.5 还原与备份功能 7 3.2 系统界面设计 8 4 系统编码实现 14 前 言 随着移动通信与Internet向移动终端的普及,网络和用户对移动终端的要求越来越高 ,而Symbian,Windows Mobile,PalmOS等手机平台过于封闭,不能很好的满足用户的需求,因此市场迫切需要 一个开发性很强的平台。经过多年的发展,第三代数字通信(3G)技术活动了广泛的接 受,它为移动终端用户带来了更快的数据传输速率。随着3G网络的使用,移动终端不再 仅是通讯网络的终端,还将成为互联网的终端。因此,移动终端的应用软件和需要的服 务将会有很大的发展空间。Google为此与2007年11月推出了一个专为移动设备设计的软 件平台——AndroidAndroid 是一套真正意义上的开发性的移动设备综合平台,它包括操作系统、中间件和一些关键 的平台应用。Android 是由Linux+Java构成的开源软件,允许所有厂商和个人在其基础上进行开发。Android平 台的开放性等特点既能促进技术(包括平台本身)的创新,又有助于降低开发成本,还 可以是运营商能非常方便地制定自己的特色化的产品。因此,它具有很大的市场发展潜 力。 Android(Google公司)是Google开发的基于Linux平台的开源手机操作系统。它包括 操作系统、用户界面和应用程序 ——移动电话工作所需的全部软件,而且不存在任何以往阻碍移动产业创新的专有权障碍 。谷歌与开放手机联盟合作开发了 Android,这个联盟由包括中国移动、摩托罗拉、高通、宏达和 T-Mobile 在内的 30 多家技术和无线应用的领军企业组成。 1) 优点:具备触摸屏、高级图形显示和上网功能,界面强大,可以说是一种 融入全部Web应用的单一平台 2) 缺点:由于时时刻刻都需要和网络进行连接,因此在手机的能耗方面控制就较差, 导致待机能力不足;又由于其开源性,过分依赖开发商,缺少标准配置。 1. 需求分析 1. 基本功能需求 能要求:实现通信录的在线备份还原功能,能把系统的通信录一键导入导出。 实现要求:客户端基于Android平台实现,服务端技术自定 用例场景:小明丢了手机,只好去抢购了一个小米同时把手机卡补办回来,需要把之 前手机的200个联系人补上。好在小明之前把所有联系人都备份到服务器了,只需要下载 在线通信录后,登录平台,一键还原即可。 2. 系统用例分析 图1- 1显示了通话记录功能模块。包括了联系人详细信息查看,清空通话记录,在选择一个条 目后,可以对其进行拨打电话,发送短信功能的操作,也可以进行删除。 手机用户 图1-1 通话记录模块用例图 图1- 2显示了联系人功能模块的用例。包括了查看联系人详细信息,编辑联系人信息,新建联 系人,对选中的联系人,可以对其进行拨打电话、发送短信的操作。用户还可以进行联 系人搜索,这样方便用户快速找到想找的联系人信息。 图1-2 电话薄模块用例图 图1- 3为个人中心模块中设置个人详细信息子模块的用例。该模块的功能就是用户设置自己的 个人基本信息。 图1-3 设置个人信息模块用例图 图1-4显示了联系人还原与备份的用例图。该模块的功能就是联系人的还原与备份 图1-4 联系人导入导出 2. 总体设计方案 1. 系统模块关系与划分 一个好的系统设计的步骤决定了程序是否能按照设计者的目的按时完成,是否能在规定 的时间内按照设计者的要求高质量的完成程序必要的功能。并且按照标准的设计步骤对 程序进行调试,测试,以及后期的优化完善,使程序更加具有健壮性和可用性。通过对 通讯录功能、系统模块、用户需求方面进行全方位的分析制定开发流程。 采用标准的开发流程确定系统具有用户管理功能,联系人增删改功能,通讯功能,查找 功能,备份等功能。 图1-5 系统功能图 通过对系统的功能结构的分析,设计后系统运行流程是系统运行后用户将进入通讯录 主界面,可以看到联系人,增加联系人,。通过点击MENU界面的增加功能选项可以新增 联系人,通过查找按钮可以对联系人进行姓名、号码的操作。通过个人中心可以显示所 有联系人、还原所有联系人、并备份功能。在联系人详细信息界面点击MENU键弹出通讯 功能框选择拨打电话按钮或者发信息发邮件按键,系统的运行流程图如1-6所示。 图1-6 系统运行流程 2.1通讯录需求分析 根据手机功能调查显

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值