从头开始敲代码之《从BaseApplication/Activity开始(二)》

转载请注明出处:王亟亟的大牛之路

愿意花时间写东西不容易,人啊,都是有血有肉有思想的,借鉴是学习,纯Copy就不好了,谢谢

部分资料参考于网上。

《赠梁任父同年》黄遵宪

寸寸河山寸寸金,侉离分裂力谁任?

杜鹃再拜忧天泪,精卫无穷填海心。

上一篇我们讲到了简易的封装 对我们提高效率的好处,这一篇继续写下去,如果第一篇没看过的希望能看下,方便理解。链接亟亟在安卓的进阶实例

这一次我们利用最基本的Activity生命周期中的方法,来对用户蓝牙进行识别操作,并在过程中考虑用户层面的操作理解,顺便补充下安卓手机的蓝牙知识。

什么是蓝牙?

一种无线技术标准,可实现固定设备、移动设备和楼宇个人域网之间的短距离数据交换(使用2.4—2.485GHz的ISM波段的UHF无线电波)。

白话:安卓对各个版本的蓝牙其实都有一定的支持,从1.5的Cupcake就支持了蓝牙耳机,但是自从安卓4.3版本之后Google对蓝牙4.0的支持,又进一步的提升,所以对4.3前后的适配又成了我们的工作(现在已经普遍以5.0为开发环境低版本的手机已经不多,工作量其实已经不大了)

OK,简单介绍完了,开始今天的代码

写一个工具类BluetoothMgr,把蓝牙一些相关的操作,放在里面

/**
 * Created by Ezreal on 2015/9/14.
 */
public class BluetoothMgr {

    private static BluetoothMgr oneInstance = null;
    public static BluetoothAdapter mBluetoothAdapter = null;
    public boolean available = false;
    private static List<BluetoothDevice> devList = new ArrayList<BluetoothDevice>();

    private BluetoothMgr() { }

    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
    private BluetoothMgr(Context context) {

        int sdkInt = Build.VERSION.SDK_INT;

        if (sdkInt <= Build.VERSION_CODES.JELLY_BEAN_MR1) {

            mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

        } else {

            BluetoothManager manager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
            mBluetoothAdapter = manager.getAdapter();

        }

        available = (null != mBluetoothAdapter);
    }

    //判断BluetoothMgr是否可用
    public boolean available() {

        return available;

    }

    //获得实例
    public static BluetoothMgr getInstance(Context context) {

        if (null == oneInstance) {

            oneInstance = new BluetoothMgr(context);

        }

        return oneInstance;

    }

    //搜索设备
    public static boolean startDiscovery(){

        if (null == mBluetoothAdapter) {

            return false;

        }

        if (!mBluetoothAdapter.isEnabled()) {

            mBluetoothAdapter.enable();

            while (!mBluetoothAdapter.isEnabled()) {

                try {

                    Thread.sleep(1000);

                } catch (InterruptedException e) {

                    e.printStackTrace();

                }
            }
        }

        if (mBluetoothAdapter.isDiscovering()) {

            return true;

        }

        return mBluetoothAdapter.startDiscovery();

    }

    //取消搜索
    public static boolean cancelDiscovery() {

        if (mBluetoothAdapter == null) {

            return false;

        }

        if (mBluetoothAdapter.isDiscovering()){

            return mBluetoothAdapter.cancelDiscovery();

        }

        return false;

    }

    //添加设备
    public static void addOne(BluetoothDevice device) {

        if (null == device) {

            return;

        }

        if (devList.contains(device)) {

            return;

        }

        devList.add(device);

    }

    //删除设备
    public static void deleteOne(String mac) {

        if (null == mac || mac.length()==0) {

            return;

        }

        for (int i = 0; i < devList.size(); ++i) {

            BluetoothDevice device = devList.get(i);
            if (device.getAddress().equalsIgnoreCase(mac)) {

                devList.remove(i);
                break;

            }

        }

    }

    //清空集合
    public static void clearAllDevices() {

        devList.clear();

    }

    public static BluetoothDevice findOne(int pos) {

        if (pos < 0 || pos >= devList.size()) {

            return null;

        }

        return devList.get(pos);

    }

    public static List<BluetoothDevice> getDevList() {

        return devList;

    }

    public static boolean isDevListEmpty() {

        return (null == devList || devList.isEmpty());

    }

    //获取状态
    public static int getState(){
        if(mBluetoothAdapter!=null){
            LogUtils.d("BluetoothMgr","mBluetoothAdapter.getState()"+mBluetoothAdapter.getState());
            return mBluetoothAdapter.getState();
        }else{
            return -1;
        }
    }
}

分析:对蓝牙的一些基本方法进行了封装,以及版本的判断,这边在例举下蓝牙相关的一些具体代码的内容

(这部分网上资料还算有,也可以找找)

在安卓要使用蓝牙,先要授权

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

不然你项目一运行就是异常。

要使用蓝牙必须声明一个BluetoothAdapter

在4.3之前

mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();获取系统默认蓝牙。

4.3之后

BluetoothManager manager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);

mBluetoothAdapter = manager.getAdapter();

列举一些常用的方法

disable()关闭蓝牙

enable()打开蓝牙(用户将不会收到提示)

下面是另一种打开蓝牙的方式,但是会提醒用户手动去打开

Intent enabler=new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);

startActivityForResult(enabler,reCode);//同startActivity(enabler);

cancelDiscovery() 取消搜索设备

startDiscovery() 开始搜索设备

getAddress()获取本地蓝牙地址

getName()获取本地蓝牙名称

getRemoteDevice(Stringaddress)根据蓝牙地址获取远程蓝牙设备

getState()获取本地蓝牙适配器当前状态

isDiscovering()判断当前是否正在查找设备,是返回true

isEnabled()判断蓝牙是否打开,已打开返回true,否则,返回false

再列举下蓝牙的状态值

BluetoothAdapter STATE 状态值

          int STATE_OFF        蓝牙已经关闭
          int STATE_ON        蓝牙已经打开
          int STATE_TURNING_OFF      蓝牙处于关闭过程中 ,关闭ing
          int STATE_TURNING_ON        蓝牙处于打开过程中 ,打开ing

BluetoothAdapter SCAN_MOD状态值=扫描状态

可以扫描其他设备的,当然它同时能被其他蓝牙设备扫码。

     int  SCAN_MODE_CONNECTABLE         表明该蓝牙可以扫描其他蓝牙设备
     int  SCAN_MODE_CONNECTABLE_DISCOVERABLE     可以扫描其他蓝牙设备,并且可以被其他蓝牙设备扫描到。
     int  SCAN_MODE_NONE : 该蓝牙不能扫描以及被扫描。

更多资料可参考BluetoothAdapter[蓝牙]

铺垫做的差不多了,我们开始今天的代码。

需求:我有一个Activity,我需要进入他的时候让用户开启手机蓝牙,然后对我们的另外一个蓝牙硬件进行操作,如果用户不愿意去开,那就停留在原有界面,如果用户去开蓝牙了并且成功了那么就进入下一步操作,如果没开成功,那么继续提示。

包结构:

代码的基类都是在我们之前的Demo中继续添加的,更有延续性。

直接贴 MainActivity

public class MainActivity extends BaseActivity implements View.OnClickListener{
    Button button;
    private MyPromptDlg btNotOpenDlg = null;
    BluetoothMgr bleMgr;

    @Override
    protected void findById() {
        button=(Button)findViewById(R.id.button);

        bleMgr=BluetoothMgr.getInstance(this);

    }

    @Override
    protected void setListener() {
        button.setOnClickListener(this);
    }

    @Override
    protected void logic() {

    }

    @Override
    protected int getLayout() {
        return R.layout.activity_main;
    }

    @Override
    public void onClick(View v) {
        if (v.getId()==R.id.button){
            Toast.makeText(MainActivity.this,"NFC是否可用?? "+NFCisAvailable(),Toast.LENGTH_SHORT).show();
            openBlueToothSetting();
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        LogUtils.d("------>onResume");

        if(bleMgr.isEnabled()){
            Toast.makeText(MainActivity.this,"蓝牙已经打开",Toast.LENGTH_SHORT).show();
        }else{
            OpenBlueTooth();
        }
    }

    //打开蓝牙
    private void OpenBlueTooth(){
        //判断Activity的状态
        if (this.isFinishing()) {

            return;

        }
        if (null == btNotOpenDlg) {

            MyPromptDlg.Builder builder = new MyPromptDlg.Builder(this);

            builder.setTitle(res.getString(R.string.prompt_dlg_title))
                    .setText(res.getString(R.string.bt_check_message))
                    .setPositiveButton(res.getString(R.string.common_ok),
                            new DialogInterface.OnClickListener() {

                                @Override
                                public void onClick(DialogInterface dialog,
                                                    int which) {
                                    dialog.dismiss();
                                    openBlueToothSetting();
                                }

                            })
                    .setNegativeButton(res.getString(R.string.common_cancel),
                            new DialogInterface.OnClickListener() {

                                @Override
                                public void onClick(DialogInterface dialog,
                                                    int which) {

                                    dialog.dismiss();
                                    //finish();

                                }

                            });

            btNotOpenDlg = builder.create();
            btNotOpenDlg.setCancelable(false);
            btNotOpenDlg.setCanceledOnTouchOutside(false);
        }

        if (!btNotOpenDlg.isShowing()) {

            btNotOpenDlg.show();

        }

    }

    //打开系统蓝牙设置菜单
    private void openBlueToothSetting(){
        Intent intent = new Intent(Settings.ACTION_BLUETOOTH_SETTINGS);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);
    }
}

分析:

首先我们在我们的onCreate方法中初始化一个BluetoothMgr并且让其获得了系统蓝牙的实例(包中的BluetoothMgr是一个Demo版的,具体更多的通用方法封装在JAR包中了)

用户进入App 依次调用onCreate–onStart–onResume–Activity进入运行状态。

我们在onCreate时并没有对用户的蓝牙状态进行判断,而是在onResume方法中判断,这是为什么?看下图

因为onResume会多次调用,而onCreate在不被回收过或者onStop的情况下永远就调用一次,我们需要每一次用户焦点在我们App中的时候都去判断蓝牙的状态,那就是为什么我们要这么做的原因。

为了提高我们App的友好度,在判断用户没有开启蓝牙的时候,我们弹出一个Dialog提示用户要不要去开蓝牙,如图

如果用户点击取消我们会回到界面,但是不会调用onResume方法,不然我们的用户 就一直在那里选啊选了,不符合逻辑。

点击是,调用openBlueToothSetting()方法去手动开启,当然如果你觉得你需要强势一些可以用enable()方法,直接就开启了,但是要记得做短暂的等待,因为开启蓝牙会有一定的异步操作。

因为你代码调用开启蓝牙所以用户回到界面之后不会再判断时候开启蓝牙,也符合我们的业务需求。

当用户点击确定的时候我们开启了蓝牙设置菜单界面(系统的)

回来之后又调用了onResume,弹出了我们的吐司

OK我们的业务就完成了,还有别的实现方法么?有!!

可以用Service,开一个现成一直在那里判断也能达到效果 但是不是最理想的实现方式

还有是BroadcastReceiver 去监听手机蓝牙的变化,实现如下

BroadcastReceiver bluetoothState = new BroadcastReceiver() {
    public void onReceive(Context context, Intent intent) {
    String stateExtra = BluetoothAdapter.EXTRA_STATE;
       int state = intent.getIntExtra(stateExtra, -1);
       switch(state) {
    case BluetoothAdapter.STATE_TURNING_ON:
        break;
    case BluetoothAdapter.STATE_ON:
        break;
    case BluetoothAdapter.STATE_TURNING_OFF:
        break;
    case BluetoothAdapter.STATE_OFF:
        break;
    }
    }
}

registerReceiver(bluetoothState,new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));

记得注销哦!!

午休午休!!源码地址:http://yunpan.cn/cmCaaRkzc2UV6 访问密码 4894

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-09 14:47:32

从头开始敲代码之《从BaseApplication/Activity开始(二)》的相关文章

从头开始敲代码之《从BaseApplication/Activity开始》

转载请注明出处王亟亟的大牛之路 其安易持,其未兆易谋:其脆易泮,其微易散.为之于未有,治之于未乱.合抱之木,生于毫末:九层之台,起于垒土:千里之行,始于足下.为者败之,执者失之.是以圣人无为故无败,无执故无失.民之从事,常于几成而败之.慎终如始,则无败事.是以圣人欲不欲,不贵难得之货,学不学,复众人之所过,以辅万物之自然而不敢为. 作为系列专题的第一篇,这一篇文章属于小难产,中间夹杂着一些工作上的事,一些蛋疼的事(学车之类的),说实在的,做了Coder之后发现业余时间还真不是太多....唉...

从头开始敲代码之《从BaseApplication/Activity开始(五)》(自定义控件,实现点击/滑动翻页)

转载请注明出处:王亟亟的大牛之路 开场白惯用鼓励诗句: 黑发不知勤学早,白首方悔读书迟. -- 颜真卿<劝学诗> 这一系列的博文这是第五篇了,感谢大家的支持以及陪伴,往后我也会继续努力写出高质量的内容,谢谢 今天上的是一个自定义View,新鲜出炉,先上下效果(是一张张截图拼接的Gif动画都看不出来了,大家理解就行可以下Demo跑) 样例分析(最简单的描述了) 黑色线条是我们的手机 红色是我们自定义的"TitleBar" 蓝色是我们的自定义布局 紫色是自定义布局填充的内容 我

从头开始敲代码之《从BaseApplication/Activity开始(四)》

转载请注明出处:王亟亟的大牛之路 早上无聊看以前下的一大堆资料,发现一个用JNI实现的模糊效果,效果都差不多,但是对JNI的不熟悉让我不太推荐这种办法(不了解的总不方便,调试,修改都是) 然后在Git上找到个不错的实现,还是分2种的,应对于各种需要. 这一篇文章会介绍什么 1.模糊视图处理 2.线程操作优化 1.Renderscript 2.FastBlur 效果图 布局: <?xml version="1.0" encoding="utf-8"?> &

每天下午5点半下班,但是我很少在晚上1点之前睡过觉。因为都在敲代码

有时候,并不是我不想睡觉,不想休息,我也想舒适,也很想舒舒服服的坐着不工作,但很难做到,一天不敲代码,一天不学习新知识现在就浑身难受,不知道我这股热情能坚持多久,但这样的强度已经连续坚持了7个多月了,我很充实也很充实,每天我的精神饱满,战斗力极强.在做项目的时候,有一些细节方面的东西,我总想做到最好,总想做到用户体验最优,代码封装最优.有时候睡觉的时候也在想.我对未来是充满信心和期待的,我并不着急,我还很年轻,永远都年轻~ 前几天,小杰来公司面试,被我公司面试官虐的不要不要的,我总以为他很厉害,

使用Alcatraz为Xcode安装XActivatePowerMode插件, 从此敲代码逼格大大滴~

Alcatraz 是一款 Xcode的插件管理工具,可以用来管理XCode的 插件.模版以及颜色配置的工具. 关于Alcatraz的安装,这里有一篇不错的博文,请参考安装:http://www.cnblogs.com/wendingding/p/4964661.html 最近有一款插件叫ActivatePowerMode,堪称装逼神器啊,敲代码的时候,炫彩的火花尾巴效果简直屌炸天~,详情可以看XActivatePowerMode在github中的介绍https://github.com/qfis

程序员不能只会敲代码还要会投资理财

程序员不能只会敲代码,还要会理财或者说投资. 当我们步入职场,随着我们工作经验的增长我们的薪资相应的也会快速提高,很多人可能思维上还没有改变过来,不知道如何利用自己的闲钱去保值或者增值.当然现在互联网理财发展已经比较的成熟了,大多数的人也知道用自己发的工资直接购买余额宝来赚取利息,余额宝可以说是开启了国人理财的意识.对于我们普通人来说可以有以下几种投资: XX宝比如余额宝(货币基金),收益比银行活期存款或者某些定期存款还高,风险低几乎不会损失你的本金,但是一年的收益还是不能抵抗通货膨胀: 互联网

iOS Sprite Kit教程之编敲代码以及Xcode的介绍

iOS Sprite Kit教程之编敲代码以及Xcode的介绍 Xcode界面介绍 一个Xcode项目由非常多的文件组成,比如代码文件.资源文件等.Xcode会帮助开发人员对这些文件进行管理.所以,Xcode的界面也比較复杂,如图1.40所看到的. watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" > 图

(016)给定一个有序数组(递增),敲代码构建一棵具有最小高度的二叉树(keep it up)

给定一个有序数组(递增),敲代码构建一棵具有最小高度的二叉树. 因为数组是递增有序的.每次都在中间创建结点,类似二分查找的方法来间最小树. struct TreeNode { int data; TreeNode* leftChild; TreeNode* rightChild; }; void newNode(TreeNode*& vNode, int vData) { vNode = new TreeNode; vNode->data = vData; vNode->leftChi

十年码农,过了十年他们依旧在敲代码

摘要:话说程序员也是一个吃青春饭的职业,经常需要加班.高强度工作.新技术学习需求等等,让青春不再来的从业者感觉吃力,但仍然有一大批人因为各种原因十年如一日的敲着代码,十年历程是怎样的一种经历,你会成为其中之一吗? 十年前的2004年,中国网民突破9000万可喜可贺,第三代互动式搜索引擎搜狗刚刚问世,新浪.搜狐.网易是中国顶级的互联网企业,2004互联网大事记里看不到BAT的影子,小编在读初中,当然,也有一批很平凡的程序员在敲代码. 来看看这十几位码农十年或平凡.或漂泊的历程(以下程序员信息主要来