A. android app开发中常用到哪些开源框架
在前面的课程中,随着对Android体系的了解,已经可以进行正常的Android应用开发了。在Android开发中,同其他工程开发一样,也经常使用一些提高效率的框架,本文我们做一个对比。这些框架,既包括:网络请求框架、也包括图片加载库框架、还包括数据库操作等一些框架,总之,了解和熟悉这些框架,会对自己的开发效率有很大的提升和帮助。
网络请求框架
1、okHttp
在前文的学习中,我们已经了解过okHttp,是一个常用的网络加载库。
2、Retrofit
介绍
Retrofit是一个很不错的网络请求库,该库是square开源的另外一个库,之前的okhttp也是该公司开源的。
Retrofit是基于OkHttp封装的RESTful网络请求框架,使用注解的方式配置请求。优点是速度快,使用注解,callback函数返回结果自动包装成java对象。官方自己的介绍说:
A type-safe REST client for Android and Java
该网络框架在github上的地址如下:https://square.github.io/retrofit/
要求
Retrofit支持的http方式方式包括 GET/POST/PUT/DELETE/HEAD/PATCH,Retrofit要求Java的版本是1.8+,Android应用的API版本应该在21+。
依赖
使用Retrofit库,和其他库一样,首先需要设置依赖,依然是在build.gradle文件中设置依赖:
//添加retrofit库依赖
implementation ‘com.squareup.retrofit2:retrofit:2.1.0’
//添加gson转换器
implementation ‘com.squareup.retrofit2:converter-gson:2.1.0’
使用
通过一个例子,我们可以来演示该框架的使用步骤:
1、定义请求接口,即程序中都需要什么请求操作
public interface HttpServices {
/**
获取头条新闻
@param type 新闻类型
@param key apiKey
@return
*/
@GET(“toutiao/index”)
Call getNewsList(@Query(“type”) String type, @Query(“key”) String key);
}
2、实例化Retrofit对象,使用的Builder的模式创建,如下代码所示:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Constants.BASE_API)
.addConverterFactory(GsonConverterFactory.create())
.build();
注意,这里设置结构体转换器,是可以直接把网络请求回来的数据转换为Java结构体,这里设置的Gson解析器,因此要引入相应的转换器支持库。
3、得到接口对象,自己创建的全局的接口对象,并调用相应的接口,得到一个类似于请求Call对象。如下所示:
HttpServices httpServices = retrofit.create(HttpServices.class);
Call newsListCall = httpServices.getNewsList(“top”, Constants.API_KEY);
4、加入到请求队列中,并设置回调方法:
newsListCall.enqueue(new Callback() {
@Override
public void onResponse(Call call, Response response) {
//网络请求成功的回调方法
List list = Arrays.asList(response.body().result.data);
Log.i(“TAG”, “请求成功:” + String.valueOf(list.size()));
NewListAdapter adapter = new NewListAdapter(RetrofitActivity.this);
adapter.setmData(list);
mRecyclerView.setAdapter(adapter);
}
@Override
public void onFailure(Call call, Throwable throwable) {
//网络请求失败的回调方法
Log.i(“TAG”, “请求失败:” + throwable.getMessage());
}
});
其他界面操作和之前的Android中的内容一致。
3、RxJava
简单来说,用来处理事件和异步任务,在很多语言上都有实现,RxJava是Rx在Java上的实现。
原理
RxJava最基本的原理是基于观察者模式来实现的。通过Obserable和Observer的机制,实现所谓响应式的编程体验。
特点
RxJava在编程中的实现就是一种链式调用,做了哪些操作,谁在前谁在后非常直观,逻辑清晰,代码维护起来非常轻松。
RxJava也是一个在github上的库,githubhttp://www.xingkongmj.com/news/id/62.html地址如下:https://github.com/ReactiveX/RxJava
基于此,还有一个RxAndroid,github地址如下:https://github.com/ReactiveX/RxAndroid
RxJava和RxAndroid的关系
RxAndroid是RxJava的一个针对Android平台的扩展,主要用于 Android 开发。
基本概念
RxJava 有四个基本概念:
Observable:可观察者,即被观察者Observer:观察者subscribe:订阅事件
这四个概念之间的逻辑关系是:Observable和Observer通过subscribe方法实现订阅关系,从而Observable可以在需要的时候发出事件来通知Observer。
事件
RxJava 的事件回调方法主要包含以下几个:
onNext:普通的事件onCompletedhttp://dachang.net/432717.html:事件队列完结。RxJava 不仅把每个事件单独处理,还会把它们看做一个队列。RxJava 规定,当不会再有新的 onNext 发出时,需要触发 onCompleted 方法作为标志。:事件队列异常。在事件处理过程中出异常时, 会被触发,同时队列自动终止,不再允许再有事件发出。在一个正确运行的事件序列中, onCompleted和 有且只有一个,并且是事件序列中的最后一个。需要注意的是,onCompleted() 和 () 二者也是互斥的,即在队列中调用了其中一个,就不应该再调用另一个。
数据库操作框架
在开发时,本地数据库可以起到缓存数据和存储业务数据的作用,随着技术的成熟,不断推出了有很多关于数据库的操作框架。比较常见的数据库操作框架有诸如:GreenDao,OrmLite 和 ActiveAndroid,DBFlow等。
GreenDAO
GreenDAO是一个开源的 Android ORM(“对象/关系映射”),通过 ORM(称为“对象/关系映射”),在我们数据库开发过程中节省了开发时间!
GreenDao的官方文档地址如下:http://www.xingkongmj.com/news/id/63.html
GreenDao的作用
通过 GreenDao,我们可以更快速的操作数据库,我们可以使用简单的面相对象的API来存储,更新,删除和查询 Java 对象。这款数据库操作框架的特点是:
高性能,在官方的统计数据中,GreenDao在GreenDao,OrmLite 和 ActiveAndroid三个框架中,读、写、更新操作效率均表现第一。易于使用的强大 API,涵盖关系和连接。内存消耗较小。安全:greenDAO 支持 SQLCipherhttp://www.xingkongmj.com/news/id/64.html,以确保用户的数据安全;
核心概念
GreenDao 的核心类有三个:分别是:
DaoMaster:保存数据库对象(SQLiteDatabase)并管理特定模式的 DAO 类(而不是对象)。它有静态方法来创建表或删除它们。它的内部类 OpenHelper 和DevOpenHelper 是 SQLiteOpenHelper 实现,它们在 SQLite 数据库中创建模式。DaoSession:管理特定模式的所有可用 DAO 对象,您可以使用其中一个getter方法获取该对象。DaoSession 还提供了一些通用的持久性方法,如实体的插入,加载,更新,刷新和删除。XXXDao:数据访问对象(DAO)持久存在并查询实体。对于每个实体,greenDAO 生成DAO。它具有比 DaoSession 更多的持久性方法。Entities:可持久化对象。通常, 实体对象代表一个数据库行使用标准 Java 属性(如一个POJO 或 JavaBean )。
使用
按照官方的文档和github上的说明可以实现green的使用。
首先进行的是依赖,对于greenDao,有两个地方需要设置,分别是项目根目录中的 build.gradle,还有mole中的build.gradle。
classpath ‘org.greenrobot:green-gradle-plugin:3.3.0’ // add plugin
在项目根目录中的build.gradle目录中写这句话的意思是添加greenDao的插件。
在项目mole中的build.gradle中也需要进行配置,有两个地方需要设置,如下图所示:
apply plugin: ‘org.greenrobot.greenhttp://www.xingkongmj.com/news/id/66.html’ //开头加入该代码
dependences{
implementation ‘org.greenrobot:green:3.2.0’
}
然后就可以使用了。
bean实体
可以在项目中创建自己业务需要的实体类,并通过注解来设置是实体类,字段约束等内容。然后点击Android Studio中的Make mole,即可自动生成XXXDao代码,以此来方便开发者的操作。生成的XXXDao类,不可修改和编辑,是自动生成的。
ORMLite
ORMLite框架是另外一款Android开发中可以使用的数据库操作框架。该框架的文档地址如下:https://ormlite.com/sqlite_java_android_orm.shtml
该框架的文档准备的不是特别友好,此处不再赘述。
总结,所有的框架原理几乎都相差不大,只是操作有所差异。
视图注入框架
在Android项目开发过程中,有太多的页面需要布局完成,同时在代码中需要些大量的findviewbyid的操作,来实现控件的解析。于是就有人想能否轻松一些,解放双手节省时间,干一些其他有意义的事情,于是ButterKnife就来了。
ButterKnife是一个专注于Android系统的View注入框架,可以减少大量的findViewById以及setOnClickListener代码,可视化一键生成。
该项目在github上的地址如下:http://www.xingkongmj.com/news/id/65.html
这个框架的优势也非常明显:
强大的View绑定和Click事件处理功能,简化代码,提升开发效率方便的处理Adapter里的ViewHolder绑定问题运行时不会影响APP效率,使用配置方便代码清晰,可读性强
使用
首先是设置依赖,在build.gradlehttp://dachang.net/432714.html中进行依赖设置:
implementation ‘com.jakewharton:butterknife:10.2.1’
annotationProcessor ‘com.jakewharton:butterknife-compiler:10.2.1’
需要注意,该框架要求Java环境1.8版本以上,SDK版本在26以上,因此在使用到的mole中的build.graldle文件中,还必须添加如下代码配置:
apply plugin: ‘com.jakewharton.butterknife’
android{
//…
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
//…
}
另外,还必须在项目根目录中的build.gradle文件中,添加该框架的插件,如下图所示:
dependences{
classpath ‘com.jakewharton:butterknife-gradle-plugin:10.2.1’
}
然后即可在代码中进行使用了。
在使用该框架的页面进行绑定诸如,如下所示代码:
ButterKnife.bind( this) ;
主要的功能
@BindView():控件id 注解,解放双手,不用再每个控件都写一遍findviewById@BindViews():多个控件id 的注解,括号内使用花括号包括多个id即可,中间用,分割开在Fragment中使用,绑定Fragment。@BindString():绑定字符串@BindArray:绑定数组@BindBitmap:绑定bitmap资源@OnClick、@OnLongClick:绑定点击事件和长按事件…还有很多
插件安装
如果是页面很复杂,一个一个写BindView也很费劲,在Android Studio中,可以安装一个ButterKnife的插件,安装该插件后,可以在Studio中直接将对应的布局中的所有控件均给自动生成。
注意,在进行自动生成时,鼠标要放在布局文件上。
注意事项
ButterKnife框架在使用时,要求的版本比较高,包括Java的版本也有限制。因此,如果计划在项目中使用,要提前做好预备工作,以防止对已有项目和业务带来不必要的麻烦,反而影响工作进度。
B. android中一些代码的名称比如上,左,右...
top left right...你要这些吗?
C. android 代码
public class ApkClientActivity extends Activity {
static final String TAG = "ApkClientActivity";
Context mContext;
DownloadManager manager ;
DownloadCompleteReceiver receiver;
Button downBtn ;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mContext = this;
//获取下载服务
manager =(DownloadManager)getSystemService(DOWNLOAD_SERVICE);
receiver = new DownloadCompleteReceiver();
downBtn = (Button)findViewById(R.id.downBtn);
downBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//创建下载请求
DownloadManager.Request down=new DownloadManager.Request (Uri.parse("http://192.168.0.66:8080/qqinput.apk"));
//设置允许使用的网络类型,这里是移动网络和wifi都可以
down.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE|DownloadManager.Request.NETWORK_WIFI);
//禁止发出通知,既后台下载
down.setShowRunningNotification(false);
//不显示下载界面
down.setVisibleInDownloadsUi(false);
//设置下载后文件存放的位置
down.(mContext, null, "qqinput.apk");
//将下载请求放入队列
manager.enqueue(down);
}
});
}
//接受下载完成后的intent
class DownloadCompleteReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(DownloadManager.ACTION_DOWNLOAD_COMPLETE)){
long downId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
Log.v(TAG," download complete! id : "+downId);
Toast.makeText(context, intent.getAction()+"id : "+downId, Toast.LENGTH_SHORT).show();
}
}
}
@Override
protected void onResume() {
registerReceiver(receiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
super.onResume();
}
@Override
protected void onDestroy() {
if(receiver != null)unregisterReceiver(receiver);
super.onDestroy();
}
}
其中在设置 down.setShowRunningNotification(false);时,需要添加相应的权限:
<uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
否则,会报错!
AndroidManifest.xml文件内容如下:
Xml代码
<strong><uses-sdk android:minSdkVersion="9" /></strong>
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:label="@string/app_name"
android:name=".ApkClientActivity" >
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
D. 怎么用android编写代码
一、用RelativeLayout进行纯代码布局的理论基础
1、RelativeLayout,顾名思义,就是以“相对”位置/对齐 为基础的布局方式。
2、android.widget.RelativeLayout 有个继承自android.view.ViewGroup.LayoutParams 的内嵌类 LayoutParams,使用这个类的实例
调用RelativeLayout.addView 就可以实现“相对布局”。 android.widget.RelativeLayout.LayoutParams 有一个构造函数:
RelativeLayout.LayoutParams(int w, int h),参数指定了子 View 的宽度和高度,这一点和其父类是一样的。而实现相对布局的关
键在它的 两个 addRule 方法上。anchor 参数指定可以是View 的 id(“相对于谁”)、RelativeLayout.TRUE(启用某种对齐方式) 或者
是-1(应用于某些不需要 anchor 的 verb);AddRule 方法的 verb 参数指定相对的“动作”(以下常量均定义于
android.widget.RelativeLayout中,为了简便不给出其全名):
3、ALIGN_BOTTOM、ALIGN_LEFT、 ALIGN_RIGHT、 ALIGN_TOP: 本 View 的 底边/左边/右边/顶边 和 anchor 指定的 View 的
底边/左边/右边/顶边 对齐。
ALIGN_WITH_PARENT_BOTTOM 、ALIGN_WITH_PARENT_LEFT 、 ALIGN_WITH_PARENT_RIGHT 、
ALIGN_WITH_PARENT_TOP : 和上面一组常量类似,只不过不需要再指定 anchor, 其 anchor 自动为 Parent View。
CENTER_HORIZONTAL、CENTER_IN_PARENT 、CENTER_VERTICAL : 如果 anchor 为 TRUE,在 Parent 中 水平居中/水平
和垂直均居中/垂直居中。
POSITION_ABOVE 、POSITION_BELOW 、 POSITION_TO_LEFT 、POSITION_TO_RIGHT : 本 View 位于 anchor 指定的 View
的上边/下边/左边/右边。
二、案例
1、布局文件如下
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FFFFFF" >
<com..mapapi.map.MapView
android:id="@+id/_map_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="true" >
</com..mapapi.map.MapView>
<RelativeLayout
android:id="@+id/anquan_map_l1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginRight="5dp"
android:layout_marginTop="10dp" >
<ImageButton
android:id="@+id/but_of_lukuang"
android:layout_width="38.0dip"
android:layout_height="38.0dip"
android:background="@drawable/main_map_button_bg"
android:src="@drawable/maptraffic_icon_off" />
<ImageButton
android:id="@+id/btn_of_bobao"
android:layout_width="38.0dip"
android:layout_height="38.0dip"
android:layout_below="@id/but_of_lukuang"
android:layout_marginTop="5dp"
android:visibility="gone"
android:background="@drawable/main_map_button_bg"
android:src="@drawable/netfriend_bobao_n" />
<ImageButton
android:id="@+id/btn_of_layer"
android:layout_width="38.0dip"
android:layout_height="38.0dip"
android:layout_below="@+id/btn_of_bobao"
android:layout_marginTop="5dp"
android:background="@drawable/main_map_button_bg"
android:src="@drawable/main_map_icon_layer" />
</RelativeLayout>
</RelativeLayout>
2、代码如下
//得到
mapButtonRL = (RelativeLayout) findViewById(R.id.anquan_map_l1);
RelativeLayout.LayoutParams lp1 = new RelativeLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
lp1.addRule(RelativeLayout.BELOW, R.id.btn_of_layer);
showModeButton = new Button(this);
showModeButton.setText("全部显示");
showModeButton.setId(SHOW_MODE);
showModeButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
}
});
mapButtonRL.addView(showModeButton, lp1);
RelativeLayout.LayoutParams lp2 = new RelativeLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
lp2.addRule(RelativeLayout.BELOW, SHOW_MODE);
positionButton = new Button(this);
positionButton.setText("位置");
positionButton.setId(POSITION);
positionButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
}
});
mapButtonRL.addView(positionButton, lp2);
E. android代码求解释
这个其实完全可以归结为java代码,Map<String, String> params 这个是申明一个Map对象,里面存放键值对,key-value 分别是String类型 ,后面的三句put代码,分别往里面存放了三个键值对而已
F. Android 中代码定义颜色的几种方式
Android开发中颜色的自定义方法
1、使用Color类的常量,如:
int color = Color.BLUE; // 创建一个蓝色 是使用Android提供的颜色 int color = Color.RED; int color = Color.WHITE; 2、通过ARGB构建,如:
int color = Color.argb ( 127, 255, 0, 255 ); // 半透明的紫色
其中第一个参数表示透明,0表示完全透明,255(ff)表示完全不透明;后三位分别代表RGB的值了。 3、使用XML资源文件来定义颜色
该方法扩展性好,便于修改和共享,如在values目录下创建一个color.xml: <?xml version=” 1.0” encoding=”utf -8”> <resources>
<color name=”mycolor”> #7fff00ff</color> </resources>
定义了一个名为mycolor的颜色,在别的地方就可以通过引用mycolor来获取该颜色值,如textView定义中:
android:textColor= "@drawable/mycolor"
Java代码中可以使用ResourceManager类中的getColor来获取该颜色: int color = getResources().getColor(R.color.mycolor);
这与第二种方法得到的值是一样的,getResources()方法返回当前活动Activity的ResourceManager类实例。
说明:XML定义方法接受6位和8位两种表示法,而且开头必须是#,8位定义时前两位表示透明。 4、直接定义色值,如: int color = 0xff00ff00;
这种方法必须使用0x开头,而不是用我们常用的#。与方法3不一样,值也必须用8位表示 ,不接受6位的颜色表示。分组一下0x|ff|ff00ff,0x是代表颜色整数的标记,ff是表示透明度,ff00ff表示RGB颜色值。
=======================
补充一点Android布局中背景图片的设置(编辑LinearLayout):
* 可以使用纯色:android:background="@drawable/mycolor" (XML资源文件中定义的颜色)
* 也可使用图片:android:background="@drawable/bg" (需要将一个名为bg.jpg或png的图片拷贝到res/drawable-hdpi目录下)。
G. 这段android代码什么意思
这个代码是为了给Android里的一个ListView填充具体的Item行用的。
首先你要搞清楚,getView()是谁会调用, 这个方法是UI系统会调用。
它会询问你列表的每一行怎么样布局或者说渲染,于是你在getView里画出你的视图,然后系统UI帮你填到列表里面去。
convertView = mInflater.inflate(R.layout.itemrow, null);
这行代码可以清楚地看到,你己经为列表的行定义了一个布局在你的资源文件夹里,名字叫itemrow.xml. 你打开看看就明白什么意思了,
里面至少定义了一个文字行取名叫“ ITEMNAME”
里面至少还定义了一个多选框按钮名叫“ CHECKED”
所以你下面的代码:holder.cb.setOnClickListener(new View.OnClickListener() {
就是为这个多选框设置了点击事件,一旦用户点击了多选框,则记录下来以备后用。最后你可以知道哪些行被用户选中了。
切记切记!getView是UI系统为主体,是它来get你绘制的某一行View。
所以你的任务就是给他一行View,至于是哪一行int position参数 己经告诉你了。
根据position参数你可以在你的数组或者map中得到相应的对象。根据相应的对象你又可以得到相应的文字信息去绘制你的那一行VIEW
H. Android的一段常用动画效果代码(如何让点击的图片控件加速飞入到指定位置)
首相要new一个这个图片image对象
然后用TranslateAnimation animation = new TranslateAnimation(fromXDelta, toXDelta, fromYDelta, toYDelta)函数,将现在的的坐标和要移到的坐标写进去,然后用animation.setFillAfter(true);让图片停留在那。最后image.startAnimation(animation )就可以了,我是看见QQ 2011以前用过这个移动的动画做了一下,就是这么实现的
I. Android中如何使用代码打开各种类型的文件
在安卓中打开音乐、视频、图片、文档等文件是需要有读取SD卡权限的,如果是6.0以下的系统,则直接在清单文件中声明SD卡读取权限即可;如果是6.0或以上,则需要动态申请权限。
在7.0以下中打开文件时,通过intent调用系统安装得人软件打开文件就好了,但是在android7.0及以上的机子上这么做会报android.os.FileUriExposedException错误,
1)读取SD卡
2)动态申请权限
//设备API大于6.0时,主动申请权限(读取文件的权限)
public static void requestPermission(Activity context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(context, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE}, 0);
}
}
}
3)读取文件
intent = OpenFileUtil.openFile(filePath+"/"+FileName+"."+end);
使用OpenFileUtil这个。链接: https://www.jianshu.com/p/1414101858c1
为了兼容Android7.0,获取文件Uri需要使用到FileProvider。
1)首先是AndroidManifest文件里面注册FileProvider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" /> //需要自己编写xml文件
2)provider_paths.xml文件的编写
// .表示根目录
3)打开文档方式为
intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
File txtFile = new File(filePath+"/"+FileName+"."+end);
Uri contentUri = FileProvider.getUriForFile(MyApplication.getContext(), BuildConfig.APPLICATION_ID+".provider", txtFile);
intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
grantUriPermission(context, contentUri, intent);
startActivity(intent);
4)grantUriPermission方法添加权限
private static void grantUriPermission (Context context, Uri fileUri, Intent intent) {
List resInfoList = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo resolveInfo : resInfoList) {
String packageName = resolveInfo.activityInfo.packageName;
context.grantUriPermission(packageName, fileUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
}
综合两种情况:
//判断是否是AndroidN以及更高的版本,Build.VERSION_CODES.N是Android 7.0
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
File txtFile = new File(filePath+"/"+FileName+"."+end);
Uri contentUri = FileProvider.getUriForFile(MyApplication.getContext(), BuildConfig.APPLICATION_ID+".provider", txtFile);
Log.i("文件地址:",contentUri.toString());
intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
grantUriPermission(MyApplication.getContext(), contentUri, intent);
} else {
//7.0以下的可以打开文件了
intent = OpenFileUtil.openFile(filePath+"/"+FileName+"."+end);
}
MyApplication.getContext().startActivity(intent);
J. 关于android一段代码
layout_x:指定这个控件的左上角点的x轴坐标
layout_y:指定这个控件的左上角点的y轴坐标
这2个只有用在AbsoluteLayout(绝对布局)中才会看到效果
一般系统生成的布局文件默认用LinearLayout(线性布局)