代码分为两部分:

Part One 将预置的联系人插入到数据库中;

Part Two 保证预置联系人仅仅读,无法被编辑删除(在三个地方屏蔽对预置联系人进行编辑处理:联系人详情界面、联系人多选界面、新建联系人选择合并联系人时)。

【注意】假设您不须要限制预置联系人的删除/编辑操作,增加Part One部分代码就可以,并去掉第三步”新增函数“  中的语句:contactvalues.put(RawContacts.IS_SDN_CONTACT, -1);

 

Part One:

File:AbstractStartSIMService.java

Path: alps\packages\apps\Contacts\src\com\mediatek\contacts\simcontact

 

1.引入包

import android.provider.ContactsContract.PhoneLookup;

 

2.添加变量

private static boolean sIsRunningNumberCheck = false;

private static final int INSERT_PRESET_NUMBER_COUNT = xxx;           //预置联系人的个数

private static final String  INSERT_PRESET_NAME[]    = {"xxx1","xxx2",...};  //各预置联系人的姓名 

private static final String  INSERT_PRESET_NUMBER[] = {"xxx1","xxx2",...};  //各预置联系人的号码

 

3.添加函数(将预置联系人信息写入数据库中):

  private void importDefaultReadonlyContact() {

      new Thread(new Runnable() {

 

          @Override

          public void run() {

              Log.i(TAG, "isRunningNumberCheck before: " + sIsRunningNumberCheck);

              if (sIsRunningNumberCheck) {

                   return;

              }

              sIsRunningNumberCheck = true;

              for(int i = 0;i < INSERT_PRESET_NUMBER_COUNT; i++)

              {

                Log.i(TAG, "isRunningNumberCheck after: " + sIsRunningNumberCheck);

                Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri

                        .encode(INSERT_PRESET_NUMBER[i]));

                Log.i(TAG, "getContactInfoByPhoneNumbers(), uri = " + uri);

 

                Cursor contactCursor = getContentResolver().query(uri, new String[] {

                        PhoneLookup.DISPLAY_NAME, PhoneLookup.PHOTO_ID

                }, null, null, null);

                try {

                    if (contactCursor != null && contactCursor.getCount() > 0) {

                        return;

                    } else {

                        final ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>();

                        ContentProviderOperation.Builder builder = ContentProviderOperation

                                .newInsert(RawContacts.CONTENT_URI);

                        ContentValues contactvalues = new ContentValues();

                        contactvalues.put(RawContacts.ACCOUNT_NAME,

                                AccountType.ACCOUNT_NAME_LOCAL_PHONE);

                        contactvalues.put(RawContacts.ACCOUNT_TYPE,

                                AccountType.ACCOUNT_TYPE_LOCAL_PHONE);

                        contactvalues.put(RawContacts.INDICATE_PHONE_SIM,

                                ContactsContract.RawContacts.INDICATE_PHONE);

                        contactvalues.put(RawContacts.IS_SDN_CONTACT, -1);

                        builder.withValues(contactvalues);

                        builder.withValue(RawContacts.AGGREGATION_MODE,

                                RawContacts.AGGREGATION_MODE_DISABLED);

                        operationList.add(builder.build());

 

                        builder = ContentProviderOperation.newInsert(Data.CONTENT_URI);

                        builder.withValueBackReference(Phone.RAW_CONTACT_ID, 0);

                        builder.withValue(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);

                        builder.withValue(Phone.TYPE, Phone.TYPE_MOBILE);

                        builder.withValue(Phone.NUMBER, INSERT_PRESET_NUMBER[i]);

                        builder.withValue(Data.IS_PRIMARY, 1);

                        operationList.add(builder.build());

 

                        builder = ContentProviderOperation.newInsert(Data.CONTENT_URI);

                        builder.withValueBackReference(StructuredName.RAW_CONTACT_ID, 0);

                        builder.withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);

                        builder.withValue(StructuredName.DISPLAY_NAME, INSERT_PRESET_NAME[i]);

                        operationList.add(builder.build());

 

                        try {

                            getContentResolver().applyBatch(

                                    ContactsContract.AUTHORITY, operationList);

                        } catch (RemoteException e) {

                            Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage()));

                        } catch (OperationApplicationException e) {

                            Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage()));

                        }

 

                    }

                } finally {

                    // when this service start,but the contactsprovider has not been started yet.

                    // the contactCursor perhaps null, but not always.(first load will weekup the provider)

                    // so add null block to avoid nullpointerexception

                    if (contactCursor != null) {

                        contactCursor.close();

                    }

                }

              }//for

              Log.i(TAG, "isRunningNumberCheck insert: " + sIsRunningNumberCheck);

              sIsRunningNumberCheck = false;

          }

      }).start();

 

  }

   

4.onStart中调用这个函数:

 

    public void onStart(Intent intent, int startId) {

        .....           

        //add by MTK---Preset Contacts

        importDefaultReadonlyContact();

           

        log("[onStart]" + intent + ", startId " + startId);

        if (intent == null) {

            return;

        }

        .....

}

 

Part Two

1.File:DefaultContactListAdapter.java  Path:alps\packages\apps\contacts\src\com\android\contacts\list

(1)configureSelection函数中有五处 RawContacts.IS_SDN_CONTACT + " = 0",都改为:RawContacts.IS_SDN_CONTACT + " < 1"

 

(2)configureOnlyShowPhoneContactsSelection函数中例如以下语句:

selection.append(Contacts.INDICATE_PHONE_SIM + "= ?");

        selectionArgs.add("-1");

之后添加以下的代码

selection.append(" AND " + RawContacts.IS_SDN_CONTACT + " > -1");

 

 

2.File:ProfileAndContactsLoader.java  Path:alps\packages\apps\contacts\src\com\android\contacts\list 

loadSDN函数中有两处 RawContacts.IS_SDN_CONTACT + " = 0",都改为:RawContacts.IS_SDN_CONTACT + " < 1"

 

3. File:Contact.java  Path:alps\packages\apps\contacts\src\com\android\contacts\model 

添加例如以下函数:

    //add by MTK---Preset Contacts

    public boolean isReadOnlyContact() {

             return mIsSdnContact == -1;

     }

 

4. File:ContactLoaderFragment.java Path:alps\packages\apps\contacts\src\com\android\contacts\detail 

将isContactEditable函数改动为:

   public boolean isContactEditable() {

        return mContactData != null && !mContactData.isDirectoryEntry()

                && !mContactData.isSdnContacts() &&  !mContactData.isReadOnlyContact() ;

    }

 

5. File:ContactEntryListAdapter.java Path:alps\packages\apps\contacts\src\com\android\contacts\list  

在文件最后添加下面代码:

    public boolean showReadOnlyContact = true;

    public void setShowReadOnlyContact(boolean canDelete) {

        showReadOnlyContact = canDelete;

    }

 

6. File:ContactEntryListFragment.java  Path:alps\packages\apps\contacts\src\com\android\contacts\list

引入例如以下包:

import com.mediatek.contacts.list.ContactsMultiDeletionFragment;

 

在onCreateLoader函数中。倒数第二句mAdapter.configureLoader(loader, directoryId);之前添加语句:   

            mAdapter.setShowReadOnlyContact((this instanceof ContactsMultiDeletionFragment) ?

false : true);

 

8 7.File:MultiContactsBasePickerAdapter.java Path:alps\packages\apps\contacts\src\com\mediatek\contacts\list  在configureSelection函数最后的语句 loader.setSelection(selection.toString());之前添加语句:

        if (!showReadOnlyContact ) {

            selection.append(" AND " + Contacts.IS_SDN_CONTACT + "=0");

        }

      

 

8.File:AggregationSuggestionEngine.java Path:alps\packages\apps\contacts\src\com\android\contacts\editor

在configureSelection函数最后的语句 

在语句:   sb.append(" AND " + Contacts.INDICATE_PHONE_SIM + "=-1");

之后加入: sb.append(" AND " + Contacts.IS_SDN_CONTACT + "!=-1");

9.File:JoinContactListAdapter.java

Path:packages\apps\contacts\src\com\android\contacts\list   

函数:public void configureLoader(CursorLoader cursorLoader, long directoryId) 

将: loader.setSelection(Contacts._ID + "!=?"+" AND " + Contacts.INDICATE_PHONE_SIM + "=-1");‘

改动为:

    loader.setSelection(Contacts._ID + "!=?"+" AND " + Contacts.INDICATE_PHONE_SIM + "=-1" + " AND " + Contacts.IS_SDN_CONTACT + "!=-1");

 

【After JB5】

实现预置联系人(包括姓名、号码信息)至手机中;并保证该联系人是仅仅读的。无法被删除/编辑。

代码分为两部分:

Part One 将预置的联系人插入到数据库中;

Part Two 保证预置联系人仅仅读,无法被编辑删除(在三个地方屏蔽对预置联系人进行编辑处理:联系人详情界面、联系人多选界面、新建联系人选择合并联系人时)。

【注意】假设您不须要限制预置联系人的删除/编辑操作,增加Part One部分代码就可以。并去掉第一步”新增函数“  中的语句:contactvalues.put(RawContacts.IS_SDN_CONTACT, -2);

 

Part One:

1.新建PresetContactsImportProcessor.java

Path: alps\packages\apps\Contacts\src\com\mediatek\contacts\simservice

package com.mediatek.contacts.simservice;

 

import com.mediatek.contacts.simservice.SIMProcessorManager.ProcessorCompleteListener;

 

import android.content.Context;

import android.content.Intent;

import android.util.Log;

import android.content.ContentProviderOperation;

import android.content.ContentValues;

import android.content.OperationApplicationException;

import android.database.Cursor;

import android.net.Uri;

 

import android.provider.ContactsContract;

import android.provider.ContactsContract.CommonDataKinds.Email;//for usim

import android.provider.ContactsContract.CommonDataKinds.GroupMembership;

import android.provider.ContactsContract.CommonDataKinds.Phone;

import android.provider.ContactsContract.CommonDataKinds.StructuredName;

import android.provider.ContactsContract.Data;

import android.provider.ContactsContract.Groups;

import android.provider.ContactsContract.RawContacts;

 

 

import com.android.contacts.common.model.account.AccountType;

import android.os.RemoteException;

 

import java.util.ArrayList;

import com.mediatek.contacts.simservice.SIMProcessorManager.ProcessorCompleteListener;

import com.mediatek.contacts.simservice.SIMServiceUtils;

import com.mediatek.contacts.simservice.SIMServiceUtils.ServiceWorkData;

import com.mediatek.contacts.simcontact.SimCardUtils;

import com.mediatek.contacts.util.LogUtils;

import android.provider.ContactsContract.PhoneLookup;

 

public class PresetContactsImportProcessor extends SIMProcessorBase {

    private static final String TAG = "PresetContactsImportProcessor";

   

    private static boolean sIsRunningNumberCheck = false;

    private static final int INSERT_PRESET_NUMBER_COUNT = xxx;           //预置联系人的个数

    private static final String  INSERT_PRESET_NAME[]    = {"xxx1","xxx2",...};  //各预置联系人的姓名

    private static final String  INSERT_PRESET_NUMBER[] = {"xxx1","xxx2",...};  //各预置联系人的号码

   

    private int mSlotId;

    private Context mContext;

 

    public PresetContactsImportProcessor(Context context, int slotId, Intent intent,

            ProcessorCompleteListener listener) {

        super(intent, listener);

        mContext = context;

        mSlotId = slotId;

    }

 

    @Override

    public int getType() {

        return SIMServiceUtils.SERVICE_WORK_IMPORT_PRESET_CONTACTS;

    }

 

    @Override

    public void doWork() {

        if (isCancelled()) {

            LogUtils.d(TAG, "[doWork]cancel import preset contacts work. Thread id=" + Thread.currentThread().getId());

            return;

        }

        importDefaultReadonlyContact();

    }

   

    private void importDefaultReadonlyContact(){

         Log.i(TAG, "isRunningNumberCheck before: " + sIsRunningNumberCheck);

         if (sIsRunningNumberCheck) {

            return;

         }

         sIsRunningNumberCheck = true;

         for(int i = 0;i < INSERT_PRESET_NUMBER_COUNT; i++)

         {

             Log.i(TAG, "isRunningNumberCheck after: " + sIsRunningNumberCheck);

             Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri

                      .encode(INSERT_PRESET_NUMBER[i]));

             Log.i(TAG, "getContactInfoByPhoneNumbers(), uri = " + uri);

 

             Cursor contactCursor = mContext.getContentResolver().query(uri, new String[] {

                      PhoneLookup.DISPLAY_NAME, PhoneLookup.PHOTO_ID

         }, null, null, null);

         try {

             if (contactCursor != null && contactCursor.getCount() > 0) {

                  return;

             } else {

                  final ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>();

                  ContentProviderOperation.Builder builder = ContentProviderOperation

                          .newInsert(RawContacts.CONTENT_URI);

                  ContentValues contactvalues = new ContentValues();

                  contactvalues.put(RawContacts.ACCOUNT_NAME,

                          AccountType.ACCOUNT_NAME_LOCAL_PHONE);

                  contactvalues.put(RawContacts.ACCOUNT_TYPE,

                          AccountType.ACCOUNT_TYPE_LOCAL_PHONE);

                  contactvalues.put(RawContacts.INDICATE_PHONE_SIM,

                          ContactsContract.RawContacts.INDICATE_PHONE);

                  contactvalues.put(RawContacts.IS_SDN_CONTACT, -2);

                  builder.withValues(contactvalues);

                  builder.withValue(RawContacts.AGGREGATION_MODE,

                          RawContacts.AGGREGATION_MODE_DISABLED);

                  operationList.add(builder.build());

 

                  builder = ContentProviderOperation.newInsert(Data.CONTENT_URI);

                  builder.withValueBackReference(Phone.RAW_CONTACT_ID, 0);

                  builder.withValue(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);

                  builder.withValue(Phone.TYPE, Phone.TYPE_MOBILE);

                  builder.withValue(Phone.NUMBER, INSERT_PRESET_NUMBER[i]);

                  builder.withValue(Data.IS_PRIMARY, 1);

                  operationList.add(builder.build());

 

                  builder = ContentProviderOperation.newInsert(Data.CONTENT_URI);

                  builder.withValueBackReference(StructuredName.RAW_CONTACT_ID, 0);

                  builder.withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);

                  builder.withValue(StructuredName.DISPLAY_NAME, INSERT_PRESET_NAME[i]);

                  operationList.add(builder.build());

 

                  try {

                      mContext.getContentResolver().applyBatch(

                               ContactsContract.AUTHORITY, operationList);

                  } catch (RemoteException e) {

                      Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage()));

                  } catch (OperationApplicationException e) {

                      Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage()));

                  }

 

             }

         } finally {

             // when this service start,but the contactsprovider has not been started yet.

             // the contactCursor perhaps null, but not always.(first load will weekup the provider)

             // so add null block to avoid nullpointerexception

             if (contactCursor != null) {

                  contactCursor.close();

             }

         }//for

         Log.i(TAG, "isRunningNumberCheck insert: " + sIsRunningNumberCheck);

         sIsRunningNumberCheck = false;

         }

    }

}

 

2. 改动SIMServiceUtils.java

Path:alps\packages\apps\ContactsCommon\src\com\mediatek\contacts\simservice  

加入

public static final int SERVICE_WORK_IMPORT_PRESET_CONTACTS = 5;

3. 改动SIMProcessorManager.java

Path:alps\packages\apps\Contacts\src\com\mediatek\contacts\simservice

在SIMProcessorManager.java中createProcessor函数里加入

else if (workType == SIMServiceUtils.SERVICE_WORK_IMPORT_PRESET_CONTACTS) {

            processor = new PresetContactsImportProcessor(context, slotId, intent, listener);

        }

4. 改动BootCmpReceiver.java

Path:alps\packages\apps\Contacts\src\com\mediatek\contacts\simcontact

在BootCmpReceiver.java中processBootComplete()方法最后加入代码

startSimService(-1, SIMServiceUtils.SERVICE_WORK_IMPORT_PRESET_CONTACTS);

Part Two

1.  File:DefaultContactListAdapter.java 

Path: alps\packages\apps\ContactsCommon\src\com\android\contacts\common\list

(1)configureOnlyShowPhoneContactsSelection函数中例如以下语句:

selection.append(Contacts.INDICATE_PHONE_SIM + "= ?

");

        selectionArgs.add("-1");

之后添加以下的代码

selection.append(" AND " + RawContacts.IS_SDN_CONTACT + " > -2");

2.  File:Contact.java 

Path: alps\packages\apps\ContactsCommon\src\com\android\contacts\common\model 

添加例如以下函数:

    //add by MTK---Preset Contacts

    public boolean isReadOnlyContact() {

             return mIsSdnContact == -2;

     }

3.  File:ContactLoaderFragment.java

Path:alps\packages\apps\contacts\src\com\android\contacts\detail 

将isContactEditable函数改动为:

   public boolean isContactEditable() {

        return mContactData != null && !mContactData.isDirectoryEntry()&& !mContactData.isSdnContacts()&&  !mContactData.is InternationalDialNumber()&&  !mContactData.isReadOnlyContact() ;

    }

 

4.  File:ContactEntryListAdapter.java 

Path:alps\packages\apps\contactscommon\src\com\android\contacts\common\list  

在文件最后添加下面代码:

    public boolean showReadOnlyContact = true;

    public void setShowReadOnlyContact(boolean canDelete) {

        showReadOnlyContact = canDelete;

    }

 

5.  File:ContactEntryListFragment.java  

Path:alps\packages\apps\contactscommon\src\com\android\contacts\common\list

加入代码:

    protected boolean isInstanceOfContactsMultiDeletionFragment(){

    return false;

    }

在onCreateLoader函数中,倒数第二句mAdapter.configureLoader(loader, directoryId);之前添加语句:   

            mAdapter.setShowReadOnlyContact(isInstanceOfContactsMultiDeletionFragment() ? false : true);

6.  File: ContactsMultiDeletionFragment.java

Path:alps\packages\apps\Contacts\src\com\mediatek\contacts\list

加入代码:

    protected boolean isInstanceOfContactsMultiDeletionFragment(){

    return true;

    }

7.File:MultiContactsBasePickerAdapter.java

Path:alps\packages\apps\contacts\src\com\mediatek\contacts\list 

在configureSelection函数最后的语句 loader.setSelection(selection.toString());之前添加语句:

        if (!showReadOnlyContact ) {

            selection.append(" AND " + Contacts.IS_SDN_CONTACT + "=0");

}

8.File:AggregationSuggestionEngine.java

Path:alps\packages\apps\contacts\src\com\android\contacts\editor

在loadAggregationSuggestions函数最后的语句 

在语句:   sb.append(" AND " + Contacts.INDICATE_PHONE_SIM + "=-1");

之后加入: sb.append(" AND " + Contacts.IS_SDN_CONTACT + "!=-2");

9.File:JoinContactListAdapter.java

Path:packages\apps\contacts\src\com\android\contacts\list   

函数:public void configureLoader(CursorLoader cursorLoader, long directoryId) 

将: loader.setSelection(Contacts._ID + "!=?

"+" AND " + Contacts.INDICATE_PHONE_SIM + "=-1");

改动为:

    loader.setSelection(Contacts._ID + "!=?"+" AND " + Contacts.INDICATE_PHONE_SIM + "=-1" + " AND " + Contacts.IS_SDN_CONTACT + "!=-2");

在手机中预置联系人/Service Number的更多相关文章

  1. 读取手机中的联系人信息(android.provider.ContactsContract)

    本篇开始讲如何从Android中得到本机联系人的信息.由于Android较快的版本升级,部分API已经发生了变化.本篇探究的通过ContentProvider机制获取联系人的API从Android2. ...

  2. Android向手机通讯录中的所有的联系人(包括SIM卡),向手机通讯录中插入联系人

    package com.example.myapi.phonepersion; import java.util.ArrayList; import java.util.List; import an ...

  3. Android-->发送短信页面实现(短信发送以及群发和从电话本中选择联系人)-----------》2

    分析下怎么写 首先,我们需要一个输入框,可以手动的输入手机号码, 其次,很少有人愿意手动输入,那么我们需要提供一个按钮来给我们的用户选择自己电话本中的联系人(一次可以选择多个即群发) 然后,我们需要一 ...

  4. [UWP]UWP中获取联系人/邮件发送/SMS消息发送操作

    这篇博客将介绍如何在UWP程序中获取联系人/邮件发送/SMS发送的基础操作. 1. 获取联系人 UWP中联系人获取需要引入Windows.ApplicationModel.Contacts名称空间. ...

  5. 【转】Android 增,删,改,查 通讯录中的联系人

    一.权限 操作通讯录必须在AndroidManifest.xml中先添加2个权限, <uses-permission android:name="android.permission. ...

  6. 微软BI 之SSIS 系列 - 在 SSIS 中使用 Web Service 以及 XML 解析

    开篇介绍 Web Service 的用途非常广几乎无处不在,像各大门户网站上的天气预报使用到的第三方 Web Service API,像手机客户端和服务器端的交互等都可以通过事先设计好的 Web Se ...

  7. Android 增,删,改,查 通讯录中的联系人

    一.权限 操作通讯录必须在AndroidManifest.xml中先添加2个权限, <uses-permission android:name="android.permission. ...

  8. 从Android手机中取出已安装的app包,导出apk

    从Android手机中取出已安装的app包,导出apk TAG:Android,提取,apk,adb,pm,root,导出apk 假设有这样一个场景,A君看到你手机上一个实用APP,想要安装到自己手机 ...

  9. 【Java EE 学习 24 下】【注解在数据库开发中的使用】【反射+注解+动态代理在事务中的应用service层】

    一.使用注解可以解决JavaBean和数据库中表名不一致.字段名不一致.字段数量不一致的问题. 1.Sun公司给jdbc提供的注解 @Table.@Column.@Id.@OneToMany.@One ...

随机推荐

  1. Installation from source on Windows 7 with Visual C++2012

    在这部分说明里,你将会学习到在配备有Visual C++的Windows平台下从源码安装ViSP.下面的这些安装步骤已经在32位Windows系统,CMake3.1和Visual Studio 201 ...

  2. Oracle数据库IP访问限制(IP白名单黑名单)

    1.编辑sqlnet.ora 内容为: #允许访问的IP(白名单) TCP.INVITED_NODES=(127.0.0.1,192.168.56.109,ip2,ip3,..,..本地IP..)若使 ...

  3. tensorflow学习之路-----MNIST数据

    ''' 神经网络的过程:1.准备相应的数据库 2.定义输入成 3.定义输出层 4.定义隐藏层 5.训练(根据误差进行训练) 6.对结果进行精确度评估 ''' import tensorflow as ...

  4. <QT之Bug制造机>QT中串口类“QSerialPort”的学习笔记

    QT5中已经增加了串口类QSrialPort,可以直接调用API函数进行快速开发. 1. 获取串口信息 Dialog::Dialog(QWidget *parent) : QDialog(parent ...

  5. jvm vmthread

    http://www.360doc.com/content/15/0615/16/15758456_478311946.shtml http://www.51testing.com/html/95/1 ...

  6. thinkphp3.2.3 隐藏url上home模块以及index.php文件

    1.去掉Home index.php 添加如下代码 define('BIND_MODULE', 'Home'); 这时就隐藏了url中的Home 2.去掉index.php thinkphp3.2.3 ...

  7. leetcode第一刷_Rotate List

    我提交了好多次,错误莫名其妙的,到后来才明确过来.原来我把题目给理解错了. 这个题的意思不是说让你把最后的那k个位置的元素移到前面来,这样的问题的做法就是用两个指针,先让一个走.走到一定的长度之后两个 ...

  8. 【v2.x OGE教程 12】 关卡编辑器帮助文档

    ] 关卡编辑器帮助文档 一.简单介绍 关卡编辑器用于游戏关卡界面元素的可视化编辑,包含元素的位置.尺寸以及其他自己定义属性.通过解析生成的数据文件就可以获取关卡信息,并能随时调整.以降低开发工作量,提 ...

  9. QT就是别人好心帮你做一些枯燥,并且很重复的代码编写工作,让你更好的把精力投入到你界面的逻辑和功能的实现的功能库(否则写了上万行代码了,才写出个BUG一大堆的毛坯)

    好了,现在开始记录我学习QT的学习历程 . 本人也不是计算机专业出来的,自学了一点,但还是不好找工作,于是参加了培训,虽然感觉没多学到什么 编程的学习生涯就是不断的看别人的源码,然后自己参考着写写自己 ...

  10. SQL Server字符串分割函数