Android开发中Gradle配置使用

Android开发中Gradle配置使用 前言 每次创建私有项目都需要配置gradle文件,没什么技术含量,还要多劳动(程序员就是懒),为了能方便使用,才有了本仓库的诞生。 欢迎各位小伙伴们来砸场,喜欢请star下… 私有仓库使用 在下载config.properties文件放到工厂根目录(和gradle.properties同级) 如果使用Artifactory仓库配置工程build.gradle文件请看详细文件 在项目build.gradle文件中使用 apply from:'https://coding.net/u/zdl_411437734/p/gradle/git/raw/master/nexusBintry.gradle' 或者 apply from:'https://coding.net/u/zdl_411437734/p/gradle/git/raw/master/artifactBintry.gradle' 执行相关命令即可 gradle uploadArchives (nexus仓库) 或者 gradle assembleRelease artifactoryPublish (artifactory仓库) 详细使用文档 Sonarqube使用 详细使用文档 pack(打包)使用 经常打包apk,有一个困扰,怎么修改打包后的名称,怎么区分打包的是release版本还是debug版本,想了解请继续看 在项目的buil.gradle文件配置打包的版本和输出的名称 //打包APK根据不同的环境打包不同的名称 ext{ productName = project.name versionName = "1.0.1" } //productName 打包出来的名称 //versionName 打包显示版本号 2 . 引入packe.gradle文件下载packe.gradle apply from:"./pack.gradle" 或者 apply from:"https://coding.net/u/zdl_411437734/p/gradle/git/raw/master/pack.gradle" 3 . 打包即可(~~) sign(签名)使用 有时候,在集成第三方时候,需要我们输入签名,在开发中和发布中一般默认都是2个keystroe,在这种情况下,开发很不方便,不断要打包成正式包才能测试,为了解决这个问题,我们配置gradle在开发时就使用正式签名开发,想了解请继续看 在项目的buil.gradle文件配置打包的版本和输出的名称 //打包APK根据不同的环境打包不同的名称 ext{ productName = "CommonProject" versionName = "2.0.1" keyPassword = "android" keyFilePath = "/Users/jason/Documents/keystore/android.keystore" storePassword = "android" keyAlias = "android" } //productName 打包出来的名称 //versionName 打包显示版本号 //keyPassword 密码 //keyFilePath 正式全路径 //storePassword 密码 //keyAlias 别名 2 . 引入sign.gradle文件下载sign.gradle ...

2017年6月7日 · 1 分钟 · 天边的星星

自定义ImageView 宽度自适应屏幕,高度等比缩放

实现方法很简单,根据图片文件的宽度与ImageView的宽度比例关系算出ImageView的高度。 package com.etongwl.commonlibs.view; import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.NinePatchDrawable; import android.util.AttributeSet; import android.view.ViewGroup; import android.widget.ImageView; /* * @Override public void setImageDrawable(final Drawable drawable) { super.setImageDrawable(drawable); if (drawable != null) { post(new Runnable() { @Override public void run() { float mWidth = getWidth(); float pWidth = drawable.getBounds().width(); float pHeight = drawable.getBounds().height(); int mHeight = (int) ((mWidth / pWidth) * pHeight); LayoutParams params = getLayoutParams(); params.height = mHeight; params.width = (int) mWidth; setLayoutParams(params); } }); } } 首先, 如果drawable不为空, 则通过drawable.getBounds()去获取drawable边界的宽和高. 在根据ImageView的宽与drawable的宽的比例去计算高度, 最后通过LayoutParams设置ImageView的高度 * */ /* <com.etongwl.commonlibs.view.AdaptiveImageView android:id="@+id/detail_image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_marginTop="15dp" android:scaleType="centerCrop" android:background="@drawable/diandianxinwen" android:visibility="visible" /> */ /** * 按比例缩放 */ @SuppressLint("AppCompatCustomView") public class AdaptiveImageView extends ImageView { // 控件默认长、宽 private int defaultWidth = 0; private int defaultHeight = 0; // 比例 private float scale = 0; public AdaptiveImageView(Context context) { super(context); } public AdaptiveImageView(Context context, AttributeSet attrs) { super(context, attrs); } public AdaptiveImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override protected void onDraw(Canvas canvas) { Drawable drawable = getDrawable(); if (drawable == null) { return; } if (getWidth() == 0 || getHeight() == 0) { return; } this.measure(0, 0); if (drawable.getClass() == NinePatchDrawable.class) return; Bitmap b = ((BitmapDrawable) drawable).getBitmap(); Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true); if (bitmap.getWidth() == 0 || bitmap.getHeight() == 0) { return; } if (defaultWidth == 0) { defaultWidth = getWidth(); } if (defaultHeight == 0) { defaultHeight = getHeight(); } scale = (float) defaultWidth / (float) bitmap.getWidth(); defaultHeight = Math.round(bitmap.getHeight() * scale); ViewGroup.LayoutParams params = this.getLayoutParams(); params.width = defaultWidth; params.height = defaultHeight; this.setLayoutParams(params); super.onDraw(canvas); } } 简单实现ImageView宽度填满屏幕,高度自适应的两种方式 两种方式 1.重写View的onMeasure方法参考这里easion_zms的专栏 核心代码 ...

2017年5月2日 · 4 分钟 · 天边的星星

Android 中的CreatePackageContext()

/** * Return a new Context object for the given application name. This * Context is the same as what the named application gets when it is * launched, containing the same resources and class loader. Each call to * this method returns a new instance of a Context object; Context objects * are not shared, however they share common state (Resources, ClassLoader, * etc) so the Context instance itself is fairly lightweight. ...

2017年4月25日 · 3 分钟 · 天边的星星

Android动态加载基础 ClassLoader工作机制

类加载器ClassLoader 早期使用过Eclipse等Java编写的软件的同学可能比较熟悉,Eclipse可以加载许多第三方的插件(或者叫扩展),这就是动态加载。这些插件大多是一些Jar包,而使用插件其实就是动态加载Jar包里的Class进行工作。这其实非常好理解,Java代码都是写在Class里面的,程序运行在虚拟机上时,虚拟机需要把需要的Class加载进来才能创建实例对象并工作,而完成这一个加载工作的角色就是ClassLoader。 对于Java程序来说,编写程序就是编写类,运行程序也就是运行类(编译得到的class文件),其中起到关键作用的就是类加载器ClassLoader。 Android的Dalvik/ART虚拟机如同标准JAVA的JVM虚拟机一样,在运行程序时首先需要将对应的类加载到内存中。因此,我们可以利用这一点,在程序运行时手动加载Class,从而达到代码动态加载可执行文件的目的。Android的Dalvik/ART虚拟机虽然与标准Java的JVM虚拟机不一样,ClassLoader具体的加载细节不一样,但是工作机制是类似的,也就是说在Android中同样可以采用类似的动态加载插件的功能,只是在Android应用中动态加载一个插件的工作要比Eclipse加载一个插件复杂许多(这点后面在解释说明)。 有几个ClassLoader实例? 动态加载的基础是ClassLoader,从名字也可以看出,ClassLoader就是专门用来处理类加载工作的,所以这货也叫类加载器,而且一个运行中的APP 不仅只有一个类加载器。 其实,在Android系统启动的时候会创建一个Boot类型的ClassLoader实例,用于加载一些系统Framework层级需要的类,我们的Android应用里也需要用到一些系统的类,所以APP启动的时候也会把这个Boot类型的ClassLoader传进来。 此外,APP也有自己的类,这些类保存在APK的dex文件里面,所以APP启动的时候,也会创建一个自己的ClassLoader实例,用于加载自己dex文件中的类。下面我们在项目里验证看看 ` <span class="hljs-annotation">@Override</span> <span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onCreate</span><span class="hljs-params">(Bundle savedInstanceState)</span> </span>{ <span class="hljs-keyword">super</span>.onCreate(savedInstanceState); ClassLoader classLoader = getClassLoader(); <span class="hljs-keyword">if</span> (classLoader != <span class="hljs-keyword">null</span>){ Log.i(TAG, <span class="hljs-string">"[onCreate] classLoader "</span> + i + <span class="hljs-string">" : "</span> + classLoader.toString()); <span class="hljs-keyword">while</span> (classLoader.getParent()!=<span class="hljs-keyword">null</span>){ classLoader = classLoader.getParent(); Log.i(TAG,<span class="hljs-string">"[onCreate] classLoader "</span> + i + <span class="hljs-string">" : "</span> + classLoader.toString()); } } }` 输出结果为 ...

2017年4月25日 · 7 分钟 · 天边的星星

使用Artifactory搭建本地maven仓库

引言 前段日子,公司为了提高产品出产效率,想把公司每个产品各个小功能抽取出来,这样再做一个新产品的时候,重复的功能就可以直接使用之前写好的模块就行了。想法是不错的,但一开始实践起来很麻烦,同事A就将自己的模块做成module,为了图方便,将整个module项目直接发送给同事B和同事C,代码第一次写成以后一般都会有一些小bug的,这样,同事A在自己电脑上修改代码,然后再次修改代码分别传给B和C。B和C需要替换之前的module,重新运行。这相当的麻烦,如果还有同事D,E,F..做起来真是噩梦,可能有有人想问,为什么不用svn或者git,用版本控制工具当然会好非常多,但每次pull其实也比较麻烦。还有另一种方法,使用本地maven仓库,使用过android studio的开发者都应该体会过其中的好处,当需要依赖一个新的模块(或者叫library)时,只需要这样 填写需要的模块及对应的版本号,同步一下就行了,很方便。本篇文章就教各位如何使用Artifactory来搭建本地仓库,来完成上图的效果 什么是Artifactory? 一句话,开源的Maven仓库管理者 搭建Artifactory 1.检测你的jdk版本是否为1.8及以上 打开cmd,输入java -version,如果输出结果如下所示即可,如果是1.6或者1.7,去官网下载最新版本替换 `java -version java version "1.8.0_31" Java(TM) SE Runtime Environment (build 1.8.0_31-b13) Java HotSpot(TM) 64-Bit Server VM (build 25.31-b07, mixed mode)" data-snippet-id="ext.437a4825669d574acb250e72155a8b81" data-snippet-saved="false" data-codota-status="done">C:\Users\Administrator>java -version<br /> java version "1.8.0_31"<br /> Java(TM) SE Runtime Environment (build 1.8.0_31-b13)<br /> Java HotSpot(TM) 64-Bit Server VM (build 25.31-b07, mixed mode)` 2.下载Artifactory,解压下载好的安装包,打开解压后文件夹下的bin文件夹,运行artifactory.bat,大概等待1分钟左右就安装完成了 3.打开http://localhost:8081/artifactory将会看到管理界面,如果看到此界面,就表示artifactory已经安装成功了.如果不是该界面,则需要等待安装完成 上传library到maven 创建自己的library project(注意你的 module是apply plugin: ‘com.android.library’),写好自己模块的代码后,准备上传 1.添加相关插件引用 在你library 项目中顶级的build.gradle文件中,添加一条新的classpath引用 **[plain]** [view plain](http://blog.csdn.net/level_26/article/details/53483444#)<span class="tracking-ad" data-mod="popu_168"> [copy](http://blog.csdn.net/level_26/article/details/53483444#)</span> <div> <embed id="ZeroClipboardMovie_1" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="16" height="16" align="middle" name="ZeroClipboardMovie_1" data-mce-fragment="1"> </embed> </div> </div> - <span style=&#8221;font-family:Microsoft YaHei;font-size:14px;&#8221;>buildscript { - dependencies { - classpath &#8220;org.jfrog.buildinfo:build-info-extractor-gradle:4.4.0&#8221; - } - }</span> 然后在你的library module的build.gradle中,添加两条语句 ...

2017年3月21日 · 3 分钟 · 天边的星星

AndroidStudio 多层级 Module 对 aar 引用

问题:有个arr文件被放到Module A中引用,现在Module B又依赖了Module A,则在编译过程中会发生错误,Module B找不到aar文件。(同时如果又有Module C 依赖了Module B,C也会出同样的问题) ![](data:image/png;base64,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) 解法: 1、正常给一个module加入aar文件的步骤是: - 把aar文件放入module文件夹下libs包下 - 然后在项目的build.gradle文件的android节点下加入 - <table> <tr> <td> <div class="top-box hide"> </div> <div class="top-box hide"> </div> ``` repositories { flatDir { dirs ’libs' } } </td> </tr> </table> - 然后继续在dependencies节点中加入:compile(name: &#8216;xxxxxxx&#8217;, ext: &#8216;aar&#8217;) </div> <div> </div> <div> 2、就是这样会引发上面的问题,所以你要做的是,给所有依赖或间接依赖Module A 的Module的build.gradle的android节点下加入 </div> <div> repositories { </div> <div> <div class="top-box hide"> flatDir { dirs &#8216;../模块名称/libs&#8217;,&#8217;libs&#8217; } } </div> 其中dirs前面一段路径是Module A的文件夹 </div> <div> </div> <div> 问题原因: </div> <div> 对于Module B和Module C来说,他们依赖了Module A,不管用不用,他们都会去把Module A的依赖走一遍,当走到你添加的aar本地依赖时,他们去找aar的路径也需要你给出,而且给的方式如果是libs这样的路径,它会去找自己包下的libs,里边自然没有,所以你要给出另一个相对路径:../模块名称/libs这样才能找到,而为了不影响自己这个Module对自己Module下的libs的引用,就使用逗号再添加一个路径 </div>

2017年3月3日 · 1 分钟 · 天边的星星

android Home键监听

监听工具类 import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.util.Log; public class HomeWatcher { static final String TAG = “HomeWatcher”; private Context mContext; private IntentFilter mFilter; private OnHomePressedListener mListener; private InnerRecevier mRecevier; // 回调接口 public interface OnHomePressedListener { public void onHomePressed(); public void onHomeLongPressed(); } public HomeWatcher(Context context) { mContext = context; mRecevier = new InnerRecevier(); mFilter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); } /** 设置监听 @param listener */ public void setOnHomePressedListener(OnHomePressedListener listener) { mListener = listener; } /** ...

2017年2月26日 · 2 分钟 · 天边的星星

Android 蓝牙4.0 BLE 理解

转载自:http://blog.csdn.net/chaoyue0071/article/details/43450183/ 本文简单结合两篇文章 http://blog.csdn.net/hellogv/article/details/24267685 http://blog.csdn.net/jimoduwu/article/details/21604215 在BLE协议中,有两个角色,周边(Periphery)和中央(Central),一个中央可以同时连接多个周边,但是一个周边某一时刻只能连接一个中央。但是不管是Periphery还是Central都是可以实现 GATT server 和 GATT client去传输数据,但是无法同时都是。 大概了解了概念后,看看Android BLE SDK的四个关键类(class): a) BluetoothGattServer作为周边来提供数据; BluetoothGattServerCallback返回周边的状态。 b) BluetoothGatt作为中央来使用和处理数据;BluetoothGattCallback返回中央的状态和周边提供的数据。 因为我们讨论的是Android的BLE SDK,下面所有的BluetoothGattServer代表周边,BluetoothGatt代表中央。 一.创建一个周边(虽然目前周边API在Android手机上不工作,但还是看看) a)先看看周边用到的class,蓝色椭圆 b)说明: 每一个周边BluetoothGattServer,包含多个服务Service,每一个Service包含多个特征Characteristic。 1.new一个特征:character = new BluetoothGattCharacteristic( UUID.fromString(characteristicUUID), BluetoothGattCharacteristic.PROPERTY_NOTIFY, BluetoothGattCharacteristic.PERMISSION_READ); 2.new一个服务:service = new BluetoothGattService(UUID.fromString(serviceUUID), BluetoothGattService.SERVICE_TYPE_PRIMARY); 3.把特征添加到服务:service.addCharacteristic(character); 4.获取BluetoothManager:manager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); 5.获取/打开周边:BluetoothGattServer server = manager.openGattServer(this, new BluetoothGattServerCallback(){…}); 6.把service添加到周边:server.addService(service); 7.开始广播service:Google还没有广播Service的API,等吧!!!!!所以目前我们还不能让一个Android手机作为周边来提供数据。 二.创建一个中央(这次不会让你失望,可以成功创建并且连接到周边的) a)先看看中央用到的class,蓝色椭圆 b)说明: 为了拿到中央BluetoothGatt,可要爬山涉水十八弯: 1.先拿到BluetoothManager:bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); 2.再拿到BluetoothAdapt:btAdapter = bluetoothManager.getAdapter(); 3.开始扫描:btAdapter.startLeScan( BluetoothAdapter.LeScanCallback); 4.从LeScanCallback中得到BluetoothDevice:public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {…..} 5.用BluetoothDevice得到BluetoothGatt:gatt = device.connectGatt(this, true, gattCallback); 终于拿到中央BluetoothGatt了,它有一堆方法(查API吧),调用这些方法,你就可以通过BluetoothGattCallback和周边BluetoothGattServer交互了。 官方有给出BLE 通信的sample ,下面是牛人简化了代码,简化得简单明了 本文来自http://blog.csdn.net/hellogv/ ,引用必须注明出处! 最近穿戴设备发展得很火,把相关技术也带旺了,其中一项是BLE(Bluetooth Low Energy)。BLE是蓝牙4.0的核心Profile,主打功能是快速搜索,快速连接,超低功耗保持连接和传输数据,弱点是数据传输速率低,由于BLE的低功耗特点,因此普遍用于穿戴设备。Android 4.3才开始支持BLE API,所以请各位客官把本文代码运行在蓝牙4.0和Android 4.3及其以上的系统,另外本文所用的BLE终端是一个蓝牙4.0的串口蓝牙模块。 PS:我的i9100刷了4.4系统后,竟然也能跟BLE蓝牙模块通信。 ...

2017年2月25日 · 6 分钟 · 天边的星星

Android 6.0 – 动态权限管理的解决方案

这里以单个存储权限为例: · 在 Manifest 中添加访问权限:(只需设置可写,因为可写必定可读) 动态申请权限的过程: = Build.VERSION_CODES.M) { // 检查该权限是否已经获取 int i = ContextCompat.checkSelfPermission(this, permissions[0]); // 权限是否已经 授权 GRANTED—授权 DINIED—拒绝 if (i != PackageManager.PERMISSION_GRANTED) { // 如果没有授予该权限,就去提示用户请求 showDialogTipUserRequestPermission(); } } } // 提示用户该请求权限的弹出框 private void showDialogTipUserRequestPermission() { new AlertDialog.Builder(this) .setTitle(“存储权限不可用”) .setMessage(“由于支付宝需要获取存储空间,为你存储个人信息;\n否则,您将无法正常使用支付宝”) .setPositiveButton(“立即开启”, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { startRequestPermission(); } }) .setNegativeButton(“取消”, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { finish(); } }).setCancelable(false).show(); } ...

2017年2月25日 · 3 分钟 · 天边的星星

Android 中gitWindow可以做的事情

View view = getWindow().getDecorView().findViewById(R.id.activity_main); if (view == null) return; ViewParent viewParent = view.getParent(); if (viewParent instanceof FrameLayout) { final FrameLayout frameParent = (FrameLayout) viewParent;//整个父布局 final LinearLayout linearLayout = new LinearLayout(this);//新建一个LinearLayout linearLayout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); linearLayout.setOrientation(LinearLayout.VERTICAL); linearLayout.setBackgroundResource(#88000000);//背景设置灰色透明 linearLayout.setGravity(Gravity.CENTER_HORIZONTAL); linearLayout.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { frameParent.removeView(linearLayout); } }); Rect rect = new Rect(); Point point = new Point(); nearby.getGlobalVisibleRect(rect, point);//获得nearby这个控件的宽高以及XY坐标 nearby这个控件对应就是需要高亮显示的地方 ImageView topGuideview = new ImageView(this); topGuideview.setLayoutParams(new ViewGroup.LayoutParams(rect.width(), rect.height())); topGuideview.setBackgroundResource(R.drawable.iv_topguide); ...

2017年2月20日 · 1 分钟 · 天边的星星