admin管理员组

文章数量:1656251

1、首先设置好基本的布局和页面设置;

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2、建立SQLite数据库创建用户的信息表;完成用户的登录和注册功能;

  • 首先创建一个数据库类继承SQLiteOpenHelper
package com.example.myapplication.Database;

import android.database.sqlite.SQLiteOpenHelper;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
/**
 * ClassName:DatabaseHelper
 * Package:com.example.myapplication.Database
 * Description: meet 985&ta
 *创建一个数据库的类;
 * @Data:2021/11/08 16:47
 * @Author:灿灿睡醒了
 */
public class DatabaseHelper extends SQLiteOpenHelper {

    private static final int VERSION = 3;//数据库版本号
    private static String DB_NAME="user";//数据库名称
    private static String TAG="DatabaseHelper";//数据库名称

    public DatabaseHelper(Context context) {
        super(context, DB_NAME, null, VERSION);
    }

    //当第一次建库的时候,调用该方法
    @Override
    public void onCreate(SQLiteDatabase db) {
        //创建数据库的时候把用户表创建好
        String sql = "create table user(id int,password varchar(20))";
        db.execSQL(sql);

        Log.i(TAG, "创建数据库.....");
    }

    //当更新数据库版本号的时候就会执行该方法
    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {
        Log.i(TAG, "更新数据库.....");
    }
}

  • 创建UserDao.java,用来实现对数据库的增删改查;
    可以在activity的里面调用这个类实现对用户的增删改查(一种简单而直接的方法)
    利用SQliteDatabase  Android---实现SQLite数据库的增删改查_qiudonga的博客-CSDN博客
  • 用户类,用来实现账号和密码的获取以及设置
    package com.example.myapplication.Shixian;
    
    import java.io.Serializable;
    
    /**
     * ClassName:User
     * Package:com.example.myapplication.Shixian
     * Description: meet 985&ta
     * 在User文件中声明要用到的表列名的变量,并对其添加get&&set方法:
     * 完成QQ的注册功能;
     * @Data:2021/11/07 20:18
     * @Author:灿灿睡醒了
     */
    
    //用户表的设置;
    public class User implements Serializable {
    
        //用户的信息表只包括两个信息;
        private static String id;//用户的账号
        private static String password;//用户密码
    
        public User() {
            super();
            // TODO Auto-generated constructor stub
        }
    
        public User(String id,String password) {
            super();
            this.id = id;
            this.password = password;
        }
    
        public static String getId() {
            return id;
        }
    
        public void setId(String id) {
            this.id = id;
        }
    
    
    
        public static String getPassword() {
            return password;
        }
        public void setPassword(String password) {
            this.password = password;
        }
    
    
        @Override
        public String toString() {
            return "User [id=" + id + ", password=" + password + "]";
        }
    
    }
    
    

    增删改查UserDao.java
     

    package com.example.myapplication.Database;
    
    import android.content.ContentValues;
    import android.content.Context;
    import android.database.Cursor;
    import android.database.sqlite.SQLiteDatabase;
    import android.util.Log;
    import android.view.View;
    
    import com.example.myapplication.Shixian.User;
    
    /**
     * ClassName:Dao
     * Package:com.example.myapplication.Database
     * Description: meet 985&ta
     * 此类用来创建用户数据库以及增删改查;
     * @Data:2021/11/08 17:08
     * @Author:灿灿睡醒了
     */
    public class UserDao {
        private final DatabaseHelper databaseHelper;//设置为一个静态变量;
        private  SQLiteDatabase db;//外部全局变量;
    
        public UserDao(Context context) {
            //创建数据库;
            databaseHelper = new DatabaseHelper(context);
        }
    
        //往用户表添加数据
        public void insert( ) {
            //打开该数据库;
            db = databaseHelper.getWritableDatabase();
    
            //在这里引入表名;插入字段和数据;
            String sql = "insert into " + databaseHelper.TABLENAME + "(id,password)values(?,?)";
            Object obj[]= new Object[]{User.getId(), User.getPassword()};
            db.execSQL(sql, obj);
            db.close();
            Log.i("RegisterActivity", "添加了一个用户记录");
        }
    
    
    //往用户表删除数据
        public void delete( ) {
            //打开该数据库;
            db = databaseHelper.getWritableDatabase();
    
            String sql = "delete from " + databaseHelper.TABLENAME + "where id=?";
            Object obj[]= new Object[]{User.getId()};
            db.execSQL(sql,obj);
            db.close();
        }
    
        //更改数据;
        public void update(String id,String password){
            //打开该数据库;
            db = databaseHelper.getWritableDatabase();
    
            ContentValues contentValues = new ContentValues();
            contentValues.put("password", password);
            //参数1:表名 参数2:修改的值 参数三:查询条件 参数4:查询条件需要的参数
            //根据id来修改password;
            db.update("user", contentValues, "id=?", new String[]{id});
            db.close();
            Log.i("ForgetActivity","修改密码成功");
    
        }
    
       
    
        //判断数据库是否存在该账号
        public boolean find(String id){
            //打开该数据库;
            db = databaseHelper.getWritableDatabase();
            //默认没有该数据
            boolean flag=false;
            //查询所有号码(表名,查询账号,查询条件没有--null)
            Cursor cursor=db.query("users",new String[]{"id"},null,null,null,null,null);
            //如果游标能往下移动
            while (cursor.moveToNext()){
                //遍历Cursor对象,跟传入的id进行比较,如果相同就返回true,说明数据库存在该数据
                if(id.equals(cursor.getString(0))){
                    flag=true;
                }
            }
            /*
            一定要关闭游标,回收游标对象
            */
            cursor.close();
            db.close();
            return flag;
        }
    }
    
    DatabaseHelper.java类创建数据库实验对象:
    package com.example.myapplication.Database;
    
    import android.database.sqlite.SQLiteOpenHelper;
    import android.content.Context;
    import android.database.sqlite.SQLiteDatabase;
    import android.util.Log;
    /**
     * ClassName:DatabaseHelper
     * Package:com.example.myapplication.Database
     * Description: meet 985&ta
     *创建一个数据库的类;
     * @Data:2021/11/08 16:47
     * @Author:灿灿睡醒了
     */
    public class DatabaseHelper extends SQLiteOpenHelper {
    
        private static final int VERSION = 3;//数据库版本号
        private static String DB_NAME="USER";//数据库名称
        private static String TAG="DatabaseHelper";//数据库名称
        public static String TABLENAME="users";//表名称
    
        public DatabaseHelper(Context context) {
            super(context, DB_NAME, null, VERSION);
        }
    
        //当第一次建库的时候,调用该方法
        @Override
        public void onCreate(SQLiteDatabase db) {
            //创建数据库的时候把用户表创建好
            String sql = "create table "+TABLENAME+"(id varchar(20),password varchar(20))";
            db.execSQL(sql);
    
            Log.i(TAG, "创建数据库.....");
        }
    
        //当更新数据库版本号的时候就会执行该方法
        @Override
        public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {
            Log.i(TAG, "更新数据库.....");
            //先不使用此功能;
        }
    }

    测试数据库:可以自动生成测试类

  • 右键-->go to-->Test

    实现登录验证功能LoginActivity.java和UserDao.java:


  • 添加手机验证码功能时:

  • 注册页面:mob/mobService/sms

  • 具体验证码步骤的实现

  • Android中实现手机获取验证码登录的功能_季风__的博客-CSDN博客_android手机验证码登录

  • Android proguard文件路径 - 简书   混淆文件

  • 安卓 实现获取手机验证码登录功能_A赴野的博客-CSDN博客

  • 遇到的一些问题:
    ①显示你的NDK找不到,打开File->Project Structure->SDK Location 在Android NDK location一栏点击下载,下载完成后clean project再build project就可以了。
    解决方法:就是在settings里面找到AndroidSDK-->SDKTools自动下载相应的版本
    ②在注册应用时找不到MD5密钥

  • C:\WINDOWS\system32>L:
    
    L:\>cd L:\Androidexe\jre\bin
    
    L:\Androidexe\jre\bin>keytool -list -v -keystore debug.keystore
    keytool 错误: java.lang.Exception: 密钥库文件不存在: debug.keystore
    java.lang.Exception: 密钥库文件不存在: debug.keystore
            at sun.security.tools.keytool.Main.doCommands(Main.java:768)
            at sun.security.tools.keytool.Main.run(Main.java:366)
            at sun.security.tools.keytool.Main.main(Main.java:359)
    
    
    L:\Androidexe\jre\bin>cd L:\Androidexe\jre\jre\bin\
    
    L:\Androidexe\jre\jre\bin>keytool -list -v -keystore debug.keystore
    keytool 错误: java.lang.Exception: 密钥库文件不存在: debug.keystore
    java.lang.Exception: 密钥库文件不存在: debug.keystore
            at sun.security.tools.keytool.Main.doCommands(Main.java:768)
            at sun.security.tools.keytool.Main.run(Main.java:366)
            at sun.security.tools.keytool.Main.main(Main.java:359)

  • 我根据这篇文章注册的密钥:android中关于keytool 错误:java.lang.Exception:密钥库文件不存在: 解决步骤_ALazyPerson的博客-CSDN博客

    别名: androiddebugkey
    创建日期: 2021-11-11
    条目类型: PrivateKeyEntry
    证书链长度: 1
    证书[1]:
    所有者: CN=wu, OU=hnust, O=hnust, L=hunan, ST=hunan, C=china
    发布者: CN=wu, OU=hnust, O=hnust, L=hunan, ST=hunan, C=china
    序列号: 2d563662
    有效期为 Thu Nov 11 09:32:14 CST 2021 至 Mon Mar 29 09:32:14 CST 2049
    证书指纹:
             MD5:  CC:C5:0C:B1:69:E2:0D:A1:4C:90:3F:02:2A:7B:05:74
             SHA1: 8F:E7:F7:06:20:57:3D:EA:09:99:B3:35:6D:FC:8C:EB:5F:A3:27:CD
             SHA256: AC:8A:47:6A:B5:DC:14:AC:65:DD:86:26:7D:6B:9B:72:CB:F0:E7:D7:7F:82:35:D4:AB:83:24:E7:3E:CC:CF:83
    签名算法名称: SHA256withRSA
    主体公共密钥算法: 2048 位 RSA 密钥
    版本: 3
    
    扩展:
    
    #1: ObjectId: 2.5.29.14 Criticality=false
    SubjectKeyIdentifier [
    KeyIdentifier [
    0000: 01 76 DB 69 19 C6 33 22   D2 B5 B2 5E 08 A4 A1 99  .v.i..3"...^....
    0010: A1 4F 4B 9B                                        .OK.
    ]
    ]

  • 验证码功能代码段1 

    package com.example.myapplication.widget;
    import android.content.Intent;
    import android.os.Handler;
    import android.os.Message;
    import android.os.Bundle;
    import android.text.TextUtils;
    import android.util.Log;
    import android.view.Gravity;
    import android.view.View;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.FrameLayout;
    import android.widget.ProgressBar;
    import android.widget.Toast;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import com.example.myapplication.R;
    import com.mob.MobSDK;
    
    import cn.smssdk.EventHandler;
    import cn.smssdk.SMSSDK;
    
    public class PhoneActivity extends AppCompatActivity implements View.OnClickListener {
        String APPKEY = "34afc2be232e8";
        String APPSECRETE = "09dc75fb83ae9d913ac3b5b8156ffc7d";
    
        // 手机号输入框
        private EditText inputPhoneEt;
    
        // 验证码输入框
        private EditText inputCodeEt;
    
        // 获取验证码按钮
        private Button requestCodeBtn;
    
        // 验证按钮
        private Button commitBtn;
    
        //倒计时
        int i = 30;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_phone);
            init();        //初始化控件
        }
    
        private void init() {
            inputPhoneEt = (EditText) findViewById(R.id.phone);
            inputCodeEt = (EditText) findViewById(R.id.et_yanzheng);
            requestCodeBtn = (Button) findViewById(R.id.but_yanzheng);
            commitBtn = (Button) findViewById(R.id.check);
            requestCodeBtn.setOnClickListener(this);
            commitBtn.setOnClickListener(this);
    
            // 启动短信验证sdk
            MobSDK.init(this, APPKEY, APPSECRETE);
            EventHandler eventHandler = new EventHandler() {
                @Override
                public void afterEvent(int event, int result, Object data) {
                    Message msg = new Message();
                    msg.arg1 = event;
                    msg.arg2 = result;
                    msg.obj = data;
                    handler.sendMessage(msg);
                }
            };
            //注册回调监听接口
            SMSSDK.registerEventHandler(eventHandler);
        }
    
    
        @Override
        public void onClick(View v) {
            String phone = inputPhoneEt.getText().toString();
            switch (v.getId()) {
                case R.id.phone:
                    // 1. 通过规则判断手机号
                    if (!judgePhoneNums(phone)) {
                        return;
                    } // 2. 通过sdk发送短信验证
                    SMSSDK.getVerificationCode("86", phone);
    
                    // 3. 把按钮变成不可点击,并且显示倒计时(正在获取)
                    requestCodeBtn.setClickable(false);
                    requestCodeBtn.setText("重新发送(" + i + ")");
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            for (; i > 0; i--) {
                                handler.sendEmptyMessage(-9);
                                if (i <= 0) {
                                    break;
                                }
                                try {
                                    Thread.sleep(1000);
                                } catch (InterruptedException e) {
                                    e.printStackTrace();
                                }
                            }
                            handler.sendEmptyMessage(-8);
                        }
                    }).start();
                    break;
    
                case R.id.check:
                    //将收到的验证码和手机号提交再次核对
                    SMSSDK.submitVerificationCode("86", phone, inputCodeEt
                            .getText().toString());
                    createProgressBar();
                    break;
            }
        }
    
        Handler handler = new Handler() {
            public void handleMessage(Message msg) {
                if (msg.what == -9) {
                    requestCodeBtn.setText("重新发送(" + i + ")");
                } else if (msg.what == -8) {
                    requestCodeBtn.setText("获取验证码");
                    requestCodeBtn.setClickable(true);
                    i = 30;
                } else {
                    int event = msg.arg1;
                    int result = msg.arg2;
                    Object data = msg.obj;
                    Log.e("event", "event=" + event);
                    if (result == SMSSDK.RESULT_COMPLETE) {
                        // 短信注册成功后,返回MainActivity,然后提示
                        if (event == SMSSDK.EVENT_SUBMIT_VERIFICATION_CODE) {// 提交验证码成功
                            Toast.makeText(getApplicationContext(), "提交验证码成功",
                                    Toast.LENGTH_SHORT).show();
                            Intent intent = new Intent(PhoneActivity.this,
                                    LoginActivity.class);
                            startActivity(intent);
                        } else if (event == SMSSDK.EVENT_GET_VERIFICATION_CODE) {
                            Toast.makeText(getApplicationContext(), "正在获取验证码",
                                    Toast.LENGTH_SHORT).show();
                        } else {
                            ((Throwable) data).printStackTrace();
                        }
                    }
                }
            }
        };
    
        private boolean judgePhoneNums(String phoneNums) {
            if (isMatchLength(phoneNums, 11)
                    && isMobileNO(phoneNums)) {
                return true;
            }
            Toast.makeText(this, "手机号码输入有误!", Toast.LENGTH_SHORT).show();
            return false;
        }
    
        public static boolean isMatchLength(String str, int length) {
            if (str.isEmpty()) {
                return false;
            } else {
                return str.length() == length ? true : false;
            }
        }
    
        public static boolean isMobileNO(String mobileNums) {
            /*
             * 移动:134、135、136、137、138、139、150、151、157(TD)、158、159、187、188
             * 联通:130、131、132、152、155、156、185、186 电信:133、153、180、189、(1349卫通)
             * 总结起来就是第一位必定为1,第二位必定为3或5或8,其他位置的可以为0-9
             */
            String telRegex = "[1][356]\\d{9}";// "[1]"代表第1位为数字1,"[358]"代表第二位可以为3、5、8中的一个,"\\d{9}"代表后面是可以是0~9的数字,有9位。
            if (TextUtils.isEmpty(mobileNums))
                return false;
            else
                return mobileNums.matches(telRegex);
        }
    
        private void createProgressBar() {
            FrameLayout layout = (FrameLayout) findViewById(android.R.id.content);
            FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
                    FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
            layoutParams.gravity = Gravity.CENTER;
            ProgressBar mProBar = new ProgressBar(this);
            mProBar.setLayoutParams(layoutParams);
            mProBar.setVisibility(View.VISIBLE);
            layout.addView(mProBar);
        }
    
        @Override
        protected void onDestroy() {
            SMSSDK.unregisterAllEventHandler();
            super.onDestroy();
        }
    }

    上面这串代码为啥作用不起来,奇怪了呢

  • 验证码功能代码段2:显示有网络问题
     

    package com.example.myapplication.widget;
    
    import android.content.Intent;
    import android.os.Bundle;
    import android.text.TextUtils;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.Toast;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import com.example.myapplication.R;
    import com.example.myapplication.Shixian.Utils;
    
    import org.json.JSONException;
    import org.json.JSONObject;
    
    import cn.smssdk.EventHandler;
    import cn.smssdk.SMSSDK;
    
    public class PhoneActivity extends AppCompatActivity {
    
        private Button buttonCode,buttonLogin;
        private EditText editTextPhoneNum,editTextCode;
        private String phoneNum,code;
        private EventHandler eh;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_phone);
            buttonCode = findViewById(R.id.but_yanzheng);
            buttonLogin = findViewById(R.id.check);
            editTextCode = findViewById(R.id.et_yanzheng);
            editTextPhoneNum = findViewById(R.id.phone);
    
            eh = new EventHandler() {
                @Override
                public void afterEvent(int event, int result, Object data) {
                    if (result == SMSSDK.RESULT_COMPLETE){
                        //回调完成
                        if (event == SMSSDK.EVENT_SUBMIT_VERIFICATION_CODE) {
                            //提交验证码成功
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    Toast.makeText(PhoneActivity.this,"登录成功",Toast.LENGTH_SHORT).show();
                                    //如果需要跳转可在这里进行跳转页面
                                    //登录成功跳转到软件首页页面
                                    Intent intent=new Intent(PhoneActivity.this,RegisterActivity.class);
                                    startActivity(intent);
                                }
                            });
                        }else if (event == SMSSDK.EVENT_GET_VOICE_VERIFICATION_CODE){
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    Toast.makeText(PhoneActivity.this,"语音验证发送",Toast.LENGTH_SHORT).show();
                                }
                            });
                        }
                        else if (event == SMSSDK.EVENT_GET_VERIFICATION_CODE){
                            //获取验证码成功
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    Toast.makeText(PhoneActivity.this,"验证码已发送",Toast.LENGTH_SHORT).show();
                                }
                            });
                        }else if (event == SMSSDK.EVENT_GET_SUPPORTED_COUNTRIES){
                            Log.i("test","test");
                        }
                    }else{
                        ((Throwable)data).printStackTrace();
                        Throwable throwable = (Throwable) data;
                        throwable.printStackTrace();
                        Log.i("1234",throwable.toString());
                        try {
                            JSONObject obj = new JSONObject(throwable.getMessage());
                            final String des = obj.optString("detail");
                            if (!TextUtils.isEmpty(des)){
                                runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        Toast.makeText(PhoneActivity.this,des,Toast.LENGTH_SHORT).show();
                                    }
                                });
                            }
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    }
                }
            };
    
            //注册一个事件回调监听,用于处理SMSSDK接口请求的结果
            SMSSDK.registerEventHandler(eh);
            buttonCode.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    phoneNum = editTextPhoneNum.getText().toString();
                    if(!phoneNum.isEmpty()){
                        if(Utils.checkTel(phoneNum)){ //利用正则表达式获取检验手机号
                            // 获取验证码
                            SMSSDK.getVerificationCode("86", phoneNum);
                        }else{
                            Toast.makeText(getApplicationContext(),"请输入有效的手机号",Toast.LENGTH_LONG).show();
                        }
                    }else {
                        Toast.makeText(getApplicationContext(),"请输入手机号",Toast.LENGTH_LONG).show();
                        return;
                    }
                    phoneNum = editTextPhoneNum.getText().toString();
                }
            });
            buttonLogin.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    code = editTextCode.getText().toString();
                    if(!code.isEmpty()){
                        //提交验证码
                        SMSSDK.submitVerificationCode("86", phoneNum, code);
                    }else{
                        Toast.makeText(getApplicationContext(),"请输入验证码",Toast.LENGTH_LONG).show();
                        return;
                    }
                }
            });
        }
        // 使用完EventHandler需注销,否则可能出现内存泄漏
        @Override
        protected void onDestroy() {
            super.onDestroy();
            SMSSDK.unregisterEventHandler(eh);
        }
    }
    
    package com.example.myapplication.Shixian;
    
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    /**
     * ClassName:Utils
     * Package:com.example.myapplication.Shixian
     * Description: meet 985&ta
     *
     * @Data:2021/11/11 9:54
     * @Author:灿灿睡醒了
     */
    public class Utils {
        /**
         * 正则匹配手机号码:
         */
        public static boolean checkTel(String tel) {
            Pattern p = Patternpile("^[1][3,4,5,6,7,8,9][0-9]{9}$");
            Matcher matcher = p.matcher(tel);
            return matcher.matches();
        }
    }
    


    不知道为啥。。。


  • 学习SharedPreferences的用法:https://blog.csdn/baidu_31093133/article/details/51476726

    使用步骤:

  • 概述

    SharedPreferences是一种轻量级的数据存储方式,采用键值对的存储方式。

    SharedPreferences只能存储少量数据,大量数据不能使用该方式存储,支持存储的数据类型有booleans, floats, ints, longs, and strings

    SharedPreferences存储到一个XML文件中的/data/data/<packagename>/shared_prefs/
     

  • 基本用法
    1.获取SharedPreferences对象

    mContextSp = this.getSharedPreferences( "testContextSp", Context.MODE_PRIVATE );
    ---创建的文件名是,testContextSp.xml
    ---第一个参数指定了SharedPreferences存储的文件的文件名,第二个参数mode指定了操作的模式
    mActivitySp = this.getPreferences( Context.MODE_PRIVATE );
    ---创建的文件名是MainActivity.xml(该Activity叫MainActivity)

    2.数据更新

    SharedPreferences mContextSp = this.getSharedPreferences( "testContextSp", Context.MODE_PRIVATE );
    SharedPreferences.Editor editor = mContextSp.edit();
    editor.putInt( "age", 28);
    editor.putBoolean( "isStudent", false );
    editor.putString( "job", "it" );
    editormit();
    //SharedPreferences添加或更新数据,操作文件数据,最后通过commit()或apply()提交修改。

    3.操作后,在对应应用路径下有创建testContextSp.xml。具体手机里的数据如下
     

    <?xml version='1.0' encoding='utf-8' standalone='yes' ?>
    <map>
        <string name="job">it</string>
        <int name="age" value="28" />
        <boolean name="isStudent" value="false" />
    </map>
  • 数据获取
     

    //SharedPreferences提供的getInt(),getString()等获取文件中的数据,若数据不存在,则返回一个默认值
    
    mContextSp = this.getSharedPreferences( "testContextSp", Context.MODE_PRIVATE );
    String name = mContextSp.getString( "name", "bbb" );
    int age = mContextSp.getInt( "age", 0 );
    boolean isStudent = mContextSp.getBoolean( "isStudent", false );

  • 实例(可以用于记住密码选项)
     

    public class MainActivity extends Activity {
        SharedPreferences mContextSp;
        SharedPreferences mActivitySp;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate( savedInstanceState );
            setContentView( R.layout.activity_main );
    
            mContextSp = this.getSharedPreferences( "testContextSp", Context.MODE_PRIVATE );
            mActivitySp = this.getPreferences( Context.MODE_PRIVATE );
            mActivitySp.edit()mit();//only create file
    
            //插入数据
            Button addBtn = findViewById( R.id.add_data_btn );
            addBtn.setOnClickListener( new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    SharedPreferences.Editor editor = mContextSp.edit();
                    editor.putString( "name", "aaa" );
                    editor.putInt( "age", 18);
                    editor.putBoolean( "isStudent", true );
                    editormit();
                }
            } );
            //更新数据
            Button updateBtn = findViewById( R.id.update_data_btn );
            updateBtn.setOnClickListener( new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    SharedPreferences.Editor editor = mContextSp.edit();
                    editor.putInt( "age", 28);
                    editor.putBoolean( "isStudent", false );
                    editor.putString( "job", "it" );
                    editormit();
                }
            } );
            //获取数据
            Button getDataBtn = findViewById( R.id.get_data_btn );
            getDataBtn.setOnClickListener( new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    String name = mContextSp.getString( "name", "bbb" );
                    int age = mContextSp.getInt( "age", 0 );
                    boolean isStudent = mContextSp.getBoolean( "isStudent", false );
                    Log.d( "sp_test", "name="+name+";age="+age+";isStudent="+isStudent);
                }
            } );
        }
    }

    但是这样的方法有一些弊端:

    (1)在存放一些集合信息,存储ArrayList就不合适

    (2)如果针对用户,新增加了很多熟悉,比如性别,头像等信息,那么需要一个一个的添加put和get方法,非常的繁琐。

  • 序列化方法保存对象

    
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.io.StreamCorruptedException;
    import java.util.List;
     
    import android.util.Base64;
     
    public class SerializableUtil {
         
        public static <E> String list2String(List<E> list) throws IOException{
            //实例化一个ByteArrayOutputStream对象,用来装载压缩后的字节文件
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            //然后将得到的字符数据装载到ObjectOutputStream
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            //writeObject 方法负责写入特定类的对象的状态,以便相应的readObject可以还原它
            oos.writeObject(list);
            //最后,用Base64.encode将字节文件转换成Base64编码,并以String形式保存
            String listString = new String(Base64.encode(baos.toByteArray(),Base64.DEFAULT));
            //关闭oos
            oos.close();
            return listString;
            }
         
        public static  String obj2Str(Object obj)throws IOException
        {
            if(obj == null) {
                return "";
            }
                  //实例化一个ByteArrayOutputStream对象,用来装载压缩后的字节文件
                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
                    //然后将得到的字符数据装载到ObjectOutputStream
                    ObjectOutputStream oos = new ObjectOutputStream(baos);
                    //writeObject 方法负责写入特定类的对象的状态,以便相应的readObject可以还原它
                    oos.writeObject(obj);
                    //最后,用Base64.encode将字节文件转换成Base64编码,并以String形式保存
                    String listString = new String(Base64.encode(baos.toByteArray(),Base64.DEFAULT));
                    //关闭oos
                    oos.close();
                    return listString;
        }
         
        //将序列化的数据还原成Object
        public static Object str2Obj(String str) throws StreamCorruptedException,IOException{
            byte[] mByte = Base64.decode(str.getBytes(),Base64.DEFAULT);
            ByteArrayInputStream bais = new ByteArrayInputStream(mByte);
            ObjectInputStream ois = new ObjectInputStream(bais);
             
            try {
                return ois.readObject();
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return null;
         
        }
         
    
    //将序列化的数据还原成List
        public static <E> List<E> string2List(String str) throws StreamCorruptedException,IOException{
            byte[] mByte = Base64.decode(str.getBytes(),Base64.DEFAULT);
            ByteArrayInputStream bais = new ByteArrayInputStream(mByte);
            ObjectInputStream ois = new ObjectInputStream(bais);
            List<E> stringList = null;
            try {
                stringList = (List<E>) ois.readObject();
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return stringList;
            }
     
    }
  • 编写SharedPreUtil ,实现对对象的读取和保存

    import java.io.IOException;
    import java.io.StreamCorruptedException;
     
    import android.content.Context;
    import android.content.Intent;
    import android.content.SharedPreferences;
    import android.content.SharedPreferences.Editor;
     
    public class SharedPreUtil
    {
         
        // 用户名key
        public final static String KEY_NAME = "KEY_NAME";
     
        public final static String KEY_LEVEL = "KEY_LEVEL";
         
         
        private static SharedPreUtil s_SharedPreUtil;
         
        private static UserEntity s_User = null;
     
        private SharedPreferences msp;
         
        // 初始化,一般在应用启动之后就要初始化
        public static synchronized void initSharedPreference(Context context)
        {
            if (s_SharedPreUtil == null)
            {
                s_SharedPreUtil = new SharedPreUtil(context);
            }
        }
         
        /**
         * 获取唯一的instance
         *
         * @return
         */
        public static synchronized SharedPreUtil getInstance()
        {
            return s_SharedPreUtil;
        }
         
        public SharedPreUtil(Context context)
        {
            msp = context.getSharedPreferences("SharedPreUtil",
                    Context.MODE_PRIVATE | Context.MODE_APPEND);
        }
         
        public SharedPreferences getSharedPref()
        {
            return msp;
        }
     
         
        public synchronized void putUser(UserEntity user)
        {
             
            Editor editor = msp.edit();
             
            String str="";
            try {
                str = SerializableUtil.obj2Str(user);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            editor.putString(KEY_NAME,str);
            editormit();
             
            s_User = user;
        }
         
        public synchronized UserEntity getUser()
        {
             
            if (s_User == null)
            {
                s_User = new UserEntity();
         
                 
                //获取序列化的数据
                String str = msp.getString(SharedPreUtil.KEY_NAME, "");
                 
                try {
                    Object obj = SerializableUtil.str2Obj(str);
                    if(obj != null){
                        s_User = (UserEntity)obj;
                    }
                     
                } catch (StreamCorruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
             
            return s_User;
        }
         
        public synchronized void DeleteUser()
        {
            Editor editor = msp.edit();
            editor.putString(KEY_NAME,"");
         
            editormit();
            s_User = null;
        }
         
    }
  •  调用Activity代码

    import android.app.Activity;
    import android.os.Bundle;
    import android.text.TextUtils;
    import android.view.Menu;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.EditText;
     
    public class ActivityMain extends Activity
    {
         
        EditText edit_pwd;
        EditText edit_name;
        Button button;
         
        @Override
        protected void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
             
            SharedPreUtil.initSharedPreference(getApplicationContext());
             
         
             
            edit_pwd = (EditText)findViewById(R.id.pwd);
            edit_name = (EditText)findViewById(R.id.name);
             
            button = (Button)findViewById(R.id.btn);
             
             
         //保存到本地
            button.setOnClickListener(new OnClickListener()
            {
                 
                @Override
                public void onClick(View v)
                {
                     
                     String name  = edit_name.getText().toString();
                     String pwd = edit_pwd.getText().toString();
                      
                     UserEntity user = new UserEntity();
                     user.setPassword(pwd);
                     user.setUserName(name);
                      
                     //用户名,密码保存在SharedPreferences
                     SharedPreUtil.getInstance().putUser(user);            
                }
            });
            Button delBtn = (Button)findViewById(R.id.btn_del);
            delBtn.setOnClickListener(new OnClickListener()
                {
                     
                    @Override
                    public void onClick(View v)
                    {  
                         SharedPreUtil.getInstance().DeleteUser();     
                           edit_name.setText("");
                           edit_pwd.setText("");
                    }
                });
             
            UserEntity user = SharedPreUtil.getInstance().getUser();
            if(!TextUtils.isEmpty(user.getPassword()) && !TextUtils.isEmpty( user.getUserName() ) ){
                edit_name.setText(user.getUserName());
                edit_pwd.setText(user.getPassword());
            }
             
        }
         
        @Override
        public boolean onCreateOptionsMenu(Menu menu)
        {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.activity_main, menu);
            return true;
        }
         
    }

  • 找了半天问题出现在这里:
    Couldn't read row 0, col 1 from CursorWindow.  Make sure the Cursor is initialized correctly before accessing data from it.


  • 实现单聊、群聊、发语音以及语音聊天和视频聊天功能
    根据MVC架构来构建项目:
     

  • 控制层controller
  • 应用界面activity
  • fragment
  • 适配器adapter
     
  • 环信创建的应用的key:1128211114111196#wcfapp

    基于环信来设置单聊、群聊、发语音以及视频聊天的功能:

  • 遇到一点点问题,不知道是直接使用通讯云,还是去搜索socket,socket聊天代码实现比较复杂,底层实现比较繁琐,但是通讯云的实现也是极其复杂的。和我之前所学习的页面等都不太一样。。socket没有找到合适的学习视频。。。(目前还在导入文件阶段)
  • 简单了解了一下socket的通信过程​​​​​​简单实现一个微信QQ聊天(客户端发送消息,服务端接收,bio)_HustleLeox的博客-CSDN博客

跟视频做的过程:

  1. IMApplication文件的作用,集成环信SDK
    又出现了一系列的问题:显示没有下载NDK....
    NDK Resolution Outcome: Project settings: Gradle model version=XXX, NDK version is UNKNOWN_宓雷的博客-CSDN博客

    ​​​​学习socket的使用方法:
  2. socket不是一种协议而是一种编程调用接口,socket的使用类型,主要有两种,使用的步骤主要有:
     
    // 步骤1:创建客户端 & 服务器的连接
    
        // 创建Socket对象 & 指定服务端的IP及端口号 
        Socket socket = new Socket("192.168.1.32", 1989);  
    
        // 判断客户端和服务器是否连接成功  
        socket.isConnected());
    
                         
    // 步骤2:客户端 & 服务器 通信
    // 通信包括:客户端 接收服务器的数据 & 发送数据 到 服务器
    
        <-- 操作1:接收服务器的数据 -->
            
                // 步骤1:创建输入流对象InputStream
                InputStream is = socket.getInputStream() 
    
                // 步骤2:创建输入流读取器对象 并传入输入流对象
                // 该对象作用:获取服务器返回的数据
                InputStreamReader isr = new InputStreamReader(is);
                BufferedReader br = new BufferedReader(isr);
    
                // 步骤3:通过输入流读取器对象 接收服务器发送过来的数据
                br.readLine();
    
    
        <-- 操作2:发送数据 到 服务器 -->                  
    
                // 步骤1:从Socket 获得输出流对象OutputStream
                // 该对象作用:发送数据
                OutputStream outputStream = socket.getOutputStream(); 
    
                // 步骤2:写入需要发送的数据到输出流对象中
                outputStream.write(("Carson_Ho"+"\n").getBytes("utf-8"));
                // 特别注意:数据的结尾加上换行符才可让服务器端的readline()停止阻塞
    
                // 步骤3:发送数据到服务端 
                outputStream.flush();  
    
    
    // 步骤3:断开客户端 & 服务器 连接
    
                 os.close();
                // 断开 客户端发送到服务器 的连接,即关闭输出流对象OutputStream
    
                br.close();
                // 断开 服务器发送到客户端 的连接,即关闭输入流读取器对象BufferedReader
    
                socket.close();
                // 最终关闭整个Socket连接
  3. MainActivity.java
    在主页面实现数据客户端和服务端的数据传递:
    package scut.carson_ho.socket_carson;
    
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
    import android.support.v7.app.AppCompatActivity;
    import android.view.View;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.TextView;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.Socket;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class MainActivity extends AppCompatActivity {
    
      
        // 主线程Handler
        // 用于将从服务器获取的消息显示出来
        private Handler mMainHandler;
    
        // Socket变量
        private Socket socket;
    
        // 线程池
        // 为了方便展示,此处直接采用线程池进行线程管理,而没有一个个开线程
        private ExecutorService mThreadPool;
    
        /**
         * 接收服务器消息 变量
         */
        // 输入流对象
        InputStream is;
    
        // 输入流读取器对象
        InputStreamReader isr ;
        BufferedReader br ;
    
        // 接收服务器发送过来的消息
        String response;
    
    
        /**
         * 发送消息到服务器 变量
         */
        // 输出流对象
        OutputStream outputStream;
    
        /**
         * 按钮 变量
         */
    
        // 连接 断开连接 发送数据到服务器 的按钮变量
        private Button btnConnect, btnDisconnect, btnSend;
    
        // 显示接收服务器消息 按钮
        private TextView Receive,receive_message;
    
        // 输入需要发送的消息 输入框
        private EditText mEdit;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            /**
             * 初始化操作
             */
    
            // 初始化所有按钮
            btnConnect = (Button) findViewById(R.id.connect);
            btnDisconnect = (Button) findViewById(R.id.disconnect);
            btnSend = (Button) findViewById(R.id.send);
            mEdit = (EditText) findViewById(R.id.edit);
            receive_message = (TextView) findViewById(R.id.receive_message);
            Receive = (Button) findViewById(R.id.Receive);
    
            // 初始化线程池
            mThreadPool = Executors.newCachedThreadPool();
    
    
            // 实例化主线程,用于更新接收过来的消息
            mMainHandler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    switch (msg.what) {
                        case 0:
                            receive_message.setText(response);
                            break;
                    }
                }
            };
    
    
            /**
             * 创建客户端 & 服务器的连接
             */
            btnConnect.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
    
                    // 利用线程池直接开启一个线程 & 执行该线程
                    mThreadPool.execute(new Runnable() {
                        @Override
                        public void run() {
    
                            try {
    
                                // 创建Socket对象 & 指定服务端的IP 及 端口号
                                socket = new Socket("192.168.1.172", 8989);
    
                                // 判断客户端和服务器是否连接成功
                                System.out.println(socket.isConnected());
    
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
    
                        }
                    });
    
                }
            });
    
            /**
             * 接收 服务器消息
             */
            Receive.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
    
                    // 利用线程池直接开启一个线程 & 执行该线程
                    mThreadPool.execute(new Runnable() {
                        @Override
                        public void run() {
    
                              try {
                                // 步骤1:创建输入流对象InputStream
                                is = socket.getInputStream();
    
                                  // 步骤2:创建输入流读取器对象 并传入输入流对象
                                  // 该对象作用:获取服务器返回的数据
                                  isr = new InputStreamReader(is);
                                  br = new BufferedReader(isr);
    
                                  // 步骤3:通过输入流读取器对象 接收服务器发送过来的数据
                                  response = br.readLine();
    
                                  // 步骤4:通知主线程,将接收的消息显示到界面
                                  Message msg = Message.obtain();
                                  msg.what = 0;
                                  mMainHandler.sendMessage(msg);
    
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
    
                        }
                    });
    
                }
            });
    
    
            /**
             * 发送消息 给 服务器
             */
            btnSend.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
    
                    // 利用线程池直接开启一个线程 & 执行该线程
                    mThreadPool.execute(new Runnable() {
                        @Override
                        public void run() {
    
                            try {
                                // 步骤1:从Socket 获得输出流对象OutputStream
                                // 该对象作用:发送数据
                                outputStream = socket.getOutputStream();
    
                                // 步骤2:写入需要发送的数据到输出流对象中
                                outputStream.write((mEdit.getText().toString()+"\n").getBytes("utf-8"));
                                // 特别注意:数据的结尾加上换行符才可让服务器端的readline()停止阻塞
    
                                // 步骤3:发送数据到服务端
                                outputStream.flush();
    
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
    
                        }
                    });
    
                }
            });
    
    
            /**
             * 断开客户端 & 服务器的连接
             */
            btnDisconnect.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
    
                    try {
                        // 断开 客户端发送到服务器 的连接,即关闭输出流对象OutputStream
                        outputStream.close();
    
                        // 断开 服务器发送到客户端 的连接,即关闭输入流读取器对象BufferedReader
                        br.close();
    
                        // 最终关闭整个Socket连接
                        socket.close();
    
                        // 判断客户端和服务器是否已经断开连接
                        System.out.println(socket.isConnected());
    
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
    
                }
            });
    
    
        }
    }
    
    
    创建服务器的线程:
    package mina;
    
    import java.io.IOException;
    import java.InetSocketAddress;
    
    import org.apache.mina.filter.codec.ProtocolCodecFilter;
    import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
    import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
    
    public class TestServer {
        public static void main(String[] args) {
            NioSocketAcceptor acceptor = null;
            try {
                acceptor = new NioSocketAcceptor();
                acceptor.setHandler(new TestHandler());
                acceptor.getFilterChain().addLast("mFilter", new ProtocolCodecFilter(new TextLineCodecFactory()));
                acceptor.setReuseAddress(true);
                acceptor.bind(new InetSocketAddress(8989));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

本文标签: androidqq