继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

Android位置权限以及数组寻找索引的坑

牛魔王的故事
关注TA
已关注
手记 196
粉丝 111
获赞 628

填坑与求解惑来的。

一、Android 危险权限,来自官方文档的坑???

Android开发者都知道,Android 6.0 之前,权限申请只需要在 AndroidManifest.xml 文件中声明就可以。Android 6.0 开始,权限申请发生了变化,危险权限需要在应用中动态申请,之前写过一篇 Android 动态申请危险权限的笔记,详情参考: Android 6.0 动态申请危险权限
先截个图,看看Android官方的说明:
https://img3.mukewang.com/5b5d34a700015e5909240418.jpg

再看危险权限的分组情况:
https://img2.mukewang.com/5b5d34ae000172f008960870.jpg

意思是,对危险权限进行了分组,同一组中,只要有有一个权限被授权了,同组中其它权限也就默认授权了。比如,我授权应用有读存储卡的权限之后,应用也就有了写存储卡的权限,事实上也确实如此。
然而问题来了,利用 GPS 获取位置信息的代码:

LocationManager locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);if(locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)){    if(ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission
                (MainActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION)
                != PackageManager.PERMISSION_GRANTED){        // request permissions
        // ...
        // ...
    }else{         
        Location location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER;        if(location != null){  
            double latitude = location.getLatitude();  
            double longitude = location.getLongitude();  
        }  
    }
}

通过官方的危险权限组,我们也能看到:Location 权限组里包含:ACCESS_FINE_LOCATIONACCESS_COARSE_LOCATION 两个权限,按照上面的说明,两个权限只要有一个申请授权成功,即可成功获取经纬度。——然鹅,当成功申请了 ACCESS_COARSE_LOCATION 权限后,程序依然会崩,错误信息提示,需要获得 ACCESS_FINE_LOCATION 权限

二、Spinner 的 setSelection() 方法,源于自己想当然的坑!!!

Android 中的下拉列表控件 spinner 有一个方法 setSelection(int position) ,显示第几项。此方法可能没有效果???总是显示第一项???

------------------------------------分割线----------------------------------

当在做两个spinner联动时,spinner2依据spinner1的选择填充数据,然后使用setSeletion(2)来设置默认项。结果发现:spinner2显示的总是第一项,但是实际选择的确实已经是position 2的位置 。
解决方法:

旧代码:

  spinner.setAdapter(adapter);
  spinner.setSelection(2);

解决方案有二:

(1)

  spinner.setAdapter(adapter);
  spinner.setSelection(2,true);  //spinner会重新layout

(2) 推荐

    spinner.setAdapter(adapter);![](https://images2018.cnblogs.com/blog/758949/201807/758949-20180726224508174-131546620.jpg)  adapter.notifyDataSetChanged(); //通知spinner刷新数据
    spinner.setSelection(2);

那么,这到底是什么原因造成的?我认为这是一个bug 。这种情况通常发生在重新填充数据之后,除此之外,使用setSelection(int position)都能得到正确的显示。

setSelection(int position, boolean animate)和setSelection(int position) 实现机制有较大区别,当调用前者时重新layout,立即触发onItemSelected函数,作用相当于用手直接点击。而后者设置了下次选择位置:setNextSelectedPositionInt(position); 然后请求Layout;,而requestLayout并非立即执行,仅仅是一个schedule。但是后者可能在重新装载数据然后Layout时丢失了某些状态。

以上分割线中内容系转载:原文链接:https://www.xuebuyuan.com/672724.html

-------------------------------------分割线------------------------------------------

然鹅,我要说的坑不是这样,我没有两个 Spinner 联动,我出现的问题是这样的,上代码
布局文件:

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.sharpcj.helloworld.MainActivity">

    <Spinner
        android:id="@+id/sp_test"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true">

    </Spinner></RelativeLayout>

java 代码:

package com.example.sharpcj.helloworld;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.widget.ArrayAdapter;import android.widget.Spinner;import java.util.Arrays;

public class MainActivity extends AppCompatActivity {    private Spinner mSpTest;    @Override
    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);        String[] strs = new String[20];        for (int i = 0; i < strs.length; i++) {
            strs[i] = "第" + i + "项";
        }
        mSpTest = findViewById(R.id.sp_test);
        mSpTest.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, strs));

        int index = Arrays.binarySearch(strs, "第11项");
        mSpTest.setSelection(index);
    }
}

运行结果:
https://img1.mukewang.com/5b5d34b90001d9af03410572.jpg

what???
为什么会这样呢? spinner 表示这个锅它不背,其实这个坑怪我自己想当然了,原因在于错误地使用了 Arrays.binarySearch(Object[] a , Object key) 这个方法,想当然地认为了返回值为查找到数组的 index。代码中, index 的实际值是 -2 。

网上找了一下资料:
binarySearch(int[] a, int key) 此方法的规则是这样的:

  • 1、如果找到关键字,则返回值为关键字在数组中的位置索引,且索引从0开始

  • 2、如果没有找到关键字,返回值为负的插入点值,所谓插入点值就是第一个比关键字大的元素在数组中的位置索引,而且这个位置索引从1开始。

binarySearch(Object[] a, Object key) 最终调用方法的源码如下:

    // Like public version, but without range checks.
    private static int binarySearch0(Object[] a, int fromIndex, int toIndex,
                                     Object key) {        int low = fromIndex;        int high = toIndex - 1;        while (low <= high) {            int mid = (low + high) >>> 1;            @SuppressWarnings("rawtypes")
            Comparable midVal = (Comparable)a[mid];            @SuppressWarnings("unchecked")            int cmp = midVal.compareTo(key);            if (cmp < 0)
                low = mid + 1;            else if (cmp > 0)
                high = mid - 1;            else
                return mid; // key found
        }        return -(low + 1);  // key not found.
    }

关于 Object 类型,Oracle 大神写的这个二分法寻找索引的代码暂时没看懂。

作者:SharpCJ

    

作者博客:http://joy99.cnblogs.com/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。

原文出处:https://www.cnblogs.com/joy99/p/9374931.html

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP