Android code wiki

 

Android code wiki

Tip1:

类的全局静态变量的使用,这样可以静态变量只分配一次内存,可以不通过类的对象也就是可以通过类名直接使用该变量。(使用场景:Request_Code ,Result_Code,Log Tag,权限名字,Activity之间传递参数Name eg:bundle,公用参数名字,接受回调的参数( eg: getIntent() ),可以防止分配内存 etc)

 

/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.android.cts.permissionapp;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;

import java.lang.Override;

/**
* A simple activity that requests permissions and returns the result.
*/
public class PermissionActivity extends Activity {
private static final String TAG = "PermissionActivity";

private static final String ACTION_CHECK_HAS_PERMISSION
= "com.android.cts.permission.action.CHECK_HAS_PERMISSION";
private static final String ACTION_REQUEST_PERMISSION
= "com.android.cts.permission.action.REQUEST_PERMISSION";
private static final String ACTION_PERMISSION_RESULT
= "com.android.cts.permission.action.PERMISSION_RESULT";
private static final String EXTRA_PERMISSION
= "com.android.cts.permission.extra.PERMISSION";
private static final String EXTRA_GRANT_STATE
= "com.android.cts.permission.extra.GRANT_STATE";
private static final int PERMISSION_ERROR = -2;
private static final int PERMISSIONS_REQUEST_CODE = 100;

private String mPermission;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

final Intent received = getIntent();
Log.d(TAG, "Started with " + received);

final String action = received.getAction();
mPermission = received.getStringExtra(EXTRA_PERMISSION);
if (ACTION_REQUEST_PERMISSION.equals(action)) {
Log.d(TAG, "Requesting permission " + mPermission);
requestPermissions(new String[] {mPermission}, PERMISSIONS_REQUEST_CODE);
} else if (ACTION_CHECK_HAS_PERMISSION.equals(action)) {
Log.d(TAG, "Checking permission " + mPermission);
sendResultBroadcast(checkSelfPermission(mPermission));
} else {
Log.w(TAG, "Unknown intent received: " + received);
finish();
}
}

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions,
int[] grantResults) {
if (requestCode != PERMISSIONS_REQUEST_CODE ||
permissions.length != 1 ||
!permissions[0].equals(mPermission)) {
Log.d(TAG, "Received wrong permissions result");
sendResultBroadcast(PERMISSION_ERROR);
} else {
Log.d(TAG, "Received valid permission result: " + grantResults[0]);
sendResultBroadcast(grantResults[0]);
}
}

private void sendResultBroadcast(int result) {
Log.d(TAG, "Sending result broadcast: " + result);
Intent broadcast = new Intent(ACTION_PERMISSION_RESULT);
broadcast.putExtra(EXTRA_GRANT_STATE, result);
sendBroadcast(broadcast);
finish();
}
}

 

Tip 2:

namespace的小技巧,在Android 中最常用到的namespace 就是在XML里面的android:***,这样的写法非常方便,现在要说的不是android 这个namespace,是另外一个namespace tools.它非常有用。

 

tools的URI的全称是”http://schemas.android.com/tools”,常用的方式是声明整个URI以后用前缀 tools 来在XML文件里面使用。tools有关的所有属性不会影响应用的运行和应用的大小,所有的tools属性会被gradle 过滤掉的当编译打包的时候。

 

快速添加tools的步骤:

在XML的根里面添加,只要敲出 toolsNS 和 TAB (Android Studio)就会自动添加tools这个namespace的全URI.

 

 

tools使用方法:

Android Studio的XML里面现在还不提供对tools所有属性的自动补全,最简单的办法 就是 复制android:**,然后换一下namespace,把android 换成tools即可。

 

有时候为了开发方便而不影响用户的体验可以使用它,在XML里面声明一个TextView,但是为了预览更方便会设置android:text=“我是预览的文字,我一直在,不管是否编译”,这样就会预览到文字的效果,但是,如果只是在XML预览的时候能看到,编译运行以后就看不到,怎么实现呢?这时候就用到了tools这个神奇的工具,可以这样写tools:text="我是预览的文字,我不是一直在,编译我就消失啦” 来代替 android:text=“我是预览的文字,我一直在,不管是否编译”。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="我是预览的文字,编译我就消失啦" />

</LinearLayout>

 

同理,为了预览方便而编译以后不需要的时候任何场景都可以使用tools来实现。有时候为了预览的时候某些属性enable,但是运行的时候unenable。可以进行android namespace所有属性覆盖的,除了自定义View的属性。

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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">

<ListView
android:id="@+id/listView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fastScrollAlwaysVisible="true"
tools:fastScrollAlwaysVisible="false" />

</LinearLayout>

 

 

关于@TargetApi,在代码里面,经常会遇见的一个注解,用tools也是在XML里面可以实现的,比如:tools:targetApi,可以用integer 或者版本的名字 来声明版本信息。

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:layout_height="match_parent"
tools:targetApi="M"
tools:text="Mastering ToolsNs" />

</LinearLayout>

 

 

当Lint检查 string resources是否正确的时候,经常会有警告信息,如果有强迫症并且应用没有走国际化,那么你可以这样来。

 

<resources xmlns:tools="http://schemas.android.com/tools"
tools:locale="es">

 

 

关于预览fragment或者自定义view。可以在一个布局文件里面这样写。下面是预览Booksfragment,不需要编译运行,也不需要模拟器就可以看到预览的效果啦。

 

<LinearLayout 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"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity">

<fragment
android:name="com.alexsimo.mastertoolsnamespace.BooksFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:layout="@layout/fragment_books" />

</LinearLayout>

 

更复杂的多层级预览,也是可以达到的。比如预览一个Activity里面的一个fragment的一个ListView对应的每个Item,如果,不编译运行在模拟器或者自己的设备上,应该是看不到效果的,但是,有了tools,一切都变得简单了。

 

activity_main:

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity">

<fragment
android:name="com.alexsimo.mastertoolsnamespace.BooksFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:layout="@layout/fragment_book" />

</LinearLayout>

 

 

fragment_book:

 

tools:listitem=“” tools:listheader,tools:listfooter,预览ListView是非常有用的,但是对于RecyclerView 没有header和footer)

 

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/list"
android:name="com.alexsimo.mastertoolsnamespace.BooksFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
app:layoutManager="LinearLayoutManager"
tools:context="com.alexsimo.mastertoolsnamespace.BooksFragment"
tools:listitem="@layout/fragment_book_list_item" />

 

fragment_book_list_item:

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">

<ImageView
android:id="@+id/imageView"
android:layout_width="150dp"
android:layout_height="150dp"
tools:src="@android:drawable/ic_media_play" />

<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<TextView
android:id="@+id/id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/text_margin"
android:textAppearance="?attr/textAppearanceListItem"
tools:text="My book title" />

<TextView
android:id="@+id/content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/text_margin"
android:textAppearance="?attr/textAppearanceListItem"
tools:text="My book description" />
</LinearLayout>

</LinearLayout>

 

这时候预览activity_main,如下:

 

 

关于预览layout 的 menus ,一般在Activity中定义 Activity.onCreateOptionsMenu(),为了预览可以用 tools:menu="comma separated menu IDs” ,设置Toolbar navigation mode,可以这样,tools:actionBarNavMode="standard|list|tabs”。

 

 

From: http://tools.android.com/tips/layout-designtime-attributes

 

Tip3:

 

关于软键盘的问题,常用的软键盘各种模式,比如,为了适应页面大小,可以android:windowSoftInputMode="adjustResize"

如果不喜欢XML配置,喜欢代码设置,那么你可以这样来:

activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)

 

自定义View展示PDF文件,PDF文件可以编辑,那么view点击编辑状态,软键盘弹出,这时候设置adjustResize就无效了,因为这个页面是全屏的,关于Fullscreen mode,g官方解释是这样的:

 

If the window's layout parameter flags include FLAG_FULLSCREEN, this value for softInputMode will be ignored; the window will not resize, but will stay fullscreen.

 

总而言之和键盘的adjustResize冲突了,这时候键盘就出问题了。

 

这时候可以监听键盘,然后手动计算设置高度了。

 

 

// Threshold for minimal keyboard height.

final int MIN_KEYBOARD_HEIGHT_PX = 150;

 

// Top-level window decor view.

final View decorView = activity.getWindow().getDecorView();

 

// Register global layout listener.

decorView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {

private final Rect windowVisibleDisplayFrame = new Rect();

private int lastVisibleDecorViewHeight;

 

@Override

public void onGlobalLayout() {

// Retrieve visible rectangle inside window.

decorView.getWindowVisibleDisplayFrame(windowVisibleDisplayFrame);

final int visibleDecorViewHeight = windowVisibleDisplayFrame.height();

 

// Decide whether keyboard is visible from changing decor view height.

if (lastVisibleDecorViewHeight != 0) {

if (lastVisibleDecorViewHeight > visibleDecorViewHeight + MIN_KEYBOARD_HEIGHT_PX) {

// Calculate current keyboard height (this includes also navigation bar height when in fullscreen mode).

int currentKeyboardHeight = decorView.getHeight() - windowVisibleDisplayFrame.bottom;

// Notify listener about keyboard being shown.

listener.onKeyboardShown(currentKeyboardHeight);

} else if (lastVisibleDecorViewHeight + MIN_KEYBOARD_HEIGHT_PX < visibleDecorViewHeight) {

// Notify listener about keyboard being hidden.

listener.onKeyboardHidden();

}

}

// Save current decor view height for the next call.

lastVisibleDecorViewHeight = visibleDecorViewHeight;

}

});

 

 

From:https://pspdfkit.com/blog/2016/keyboard-handling-on-android/

 

 

Tip4: 关于遍历

 

在开发中,遍历集合,搜集信息,是最常见的代码块,遍历中,如果中间出现异常,是不是遍历就终止了,但是如果遍历出现异常还要能继续执行剩下的条目,怎么办呢,这时候就用到了异常处理机制,如下:

 

 

String routes = intent.getStringExtra(packageName + ".routes");

if (routes != null) {

String[] routeArray = routes.split(",");

for (int i = 0; i < routeArray.length; i++) {

String[] prefixAndMask = routeArray[i].split("/");

try {

InetAddress address = InetAddress.getByName(prefixAndMask[0]);

int prefixLength = Integer.parseInt(prefixAndMask[1]);

builder.addRoute(address, prefixLength);

} catch (UnknownHostException|NumberFormatException|

ArrayIndexOutOfBoundsException e) {

continue;

}

}

}

 

建议上面这种写法,catch捕获以后,continue;同时,关于异常的另外一个用处,当return用,可以直接返回,如下:

 

 

 

@Override

public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {

throw new RuntimeException("Operation not supported");

}

 

 

 

Tip5: 关于调用ShareCompat Intent,代码如下:

 

 

// Create share intent

Intent shareIntent = ShareCompat.IntentBuilder.from(this)

.setText(getShareText(coupon))

.setType("image/jpeg")

.setStream(coupon.mImageUri)

.setChooserTitle(getString(R.string.redeem_using))

.createChooserIntent();

startActivity(shareIntent);

 

 

关于格式化展示信息的时候,一般都是用String的format来进行,这里介绍另外一种:

 

 

if (TextUtils.isEmpty(SENDER_NAME)) {

return getString(R.string.message_format_without_sender,

coupon.mTitle, coupon.mSubtitle);

} else {

// Otherwise, use the other string template and pass in the {@link #SENDER_NAME} too

return getString(R.string.message_format_with_sender, SENDER_NAME,

coupon.mTitle, coupon.mSubtitle);

}

 

这里会调用Context里面的getString()方法来实现,前面的格式化的format如下,然后传入对于需要格式化的标题和子标题就OK了

 

 

<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">

<!--

Template string with coupon title, subtitle, and sender name for the text to use

when the coupon is shared with other apps. [CHAR LIMIT=NONE]

-->

<string name="message_format_without_sender">Excited to redeem my coupon! <xliff:g id="coupon_title">%s</xliff:g> - <xliff:g id="coupon_subtitle">%s</xliff:g> #justforus</string>

 

<!--

Template string with coupon title, subtitle, and sender name for the text to use

when the coupon is shared with other apps. [CHAR LIMIT=NONE] 写注释是个好习惯

-->

<string name="message_format_with_sender">Excited to redeem my coupon with <xliff:g id="coupon_title">%s</xliff:g>! <xliff:g id="coupon_title">%s</xliff:g> - <xliff:g id="coupon_subtitle">%s</xliff:g> #justforus</string>

 

</resources>

 

 

 

Tip5: 关于Adapter

 

/**

* Adapter for grid of coupons.

*/

private static class CouponAdapter extends BaseAdapter {

 

private LayoutInflater mInflater;

private List<Coupon> mAllCoupons;

 

/**

* Constructs a new {@link CouponAdapter}.

*

* @param inflater to create new views

* @param allCoupons for list of all coupons to be displayed

*/

public CouponAdapter(LayoutInflater inflater, List<Coupon> allCoupons) {

if (allCoupons == null) {

throw new IllegalStateException("Can't have null list of coupons");

}

mAllCoupons = allCoupons;

mInflater = inflater;

}

 

@Override

public int getCount() {

return mAllCoupons.size();

}

 

@Override

public Coupon getItem(int position) {

return mAllCoupons.get(position);

}

 

@Override

public long getItemId(int position) {

return position;

}

 

@Override

public View getView(int position, View convertView, ViewGroup parent) {

 

//缓存策略的另外一种写法

 

View result = convertView;

if (result == null) {

//注意mInflater的来源,是在Activity的setContextView中这样写的:

// Fetch the {@link LayoutInflater} service so that new views can be created

// LayoutInflater inflater = (LayoutInflater) getSystemService(

// Context.LAYOUT_INFLATER_SERVICE);

result = mInflater.inflate(R.layout.grid_item, parent, false);

}

 

// Try to get view cache or create a new one if needed

ViewCache viewCache = (ViewCache) result.getTag();

if (viewCache == null) {

viewCache = new ViewCache(result);

result.setTag(viewCache);

}

 

// Fetch item

Coupon coupon = getItem(position);

 

// Bind the data

viewCache.mTitleView.setText(coupon.mTitle);

viewCache.mSubtitleView.setText(coupon.mSubtitle);

viewCache.mImageView.setImageURI(coupon.mImageUri);

 

return result;

}

}

 

/**

* Cache of views in the grid item view to make recycling of views quicker. This avoids

* additional {@link View#findViewById(int)} calls after the {@link ViewCache} is first

* created for a view. See

* {@link CouponAdapter#getView(int position, View convertView, ViewGroup parent)}.

*/

private static class ViewCache {

 

/** View that displays the title of the coupon */

private final TextView mTitleView;

 

/** View that displays the subtitle of the coupon */

private final TextView mSubtitleView;

 

/** View that displays the image associated with the coupon */

private final ImageView mImageView;

 

/**

* Constructs a new {@link ViewCache}.

*

* @param view which contains children views that should be cached.

*/

private ViewCache(View view) {

mTitleView = (TextView) view.findViewById(R.id.title);

mSubtitleView = (TextView) view.findViewById(R.id.subtitle);

mImageView = (ImageView) view.findViewById(R.id.image);

}

}

 

/**

* 关于适配器里面数据bean对象问题,如果只是纯粹展示,而不需要改变bean对象的属性,那么推荐下面这种方式,如果需要改变

* bean对象的属性,那么还是用常见的get set方法实现.

*/

private static class Coupon {

 

/** Title of the coupon. */

private final String mTitle;

 

/** Description of the coupon. */

private final String mSubtitle;

 

/** Content URI of the image for the coupon. */

private final Uri mImageUri;

 

/**

* Constructs a new {@link Coupon}.

*

* @param titleString is the title

* @param subtitleString is the description

* @param imageAssetFilePath is the file path from the application's assets folder for

* the image associated with this coupon

*/

private Coupon(String titleString, String subtitleString, String imageAssetFilePath) {

mTitle = titleString;

mSubtitle = subtitleString;

mImageUri = Uri.parse("content://" + AssetProvider.CONTENT_URI + "/" +

imageAssetFilePath);

}

}

 

 

Tip6: 关于应用的全局常量

 

 

package com.example.android.apprestrictionenforcer;

 

public interface Constants {

 

/**

* Package name of the AppRestrictionSchema sample.

*/

public static final String PACKAGE_NAME_APP_RESTRICTION_SCHEMA

= "com.example.android.apprestrictionschema";

 

}

 

为什么以接口的形式定义,而不用class定义呢,这里要说明一下用接口的好处,因为Java语言中要求,接口中定义的变量默认是public static final型,且必须给其初始值,所以实现类中不能重新定义,也不能改变其值,如果用到全局常量的定义的时候,这时候定义Constants,就限制了常量的类型,static final,多了一步校验。

 

题外话:接口更多的是在系统架构设计方法发挥作用,主要用于定义模块化之间的通信契约。(符合这种理念)

而抽象类在代码实现方面发挥作用,可以实现代码的重用。

 

 

Tip7: 关于网络

 

检查网络状态代码片:

 

 

/**

* Check whether the device is connected, and if so, whether the connection

* is wifi or mobile (it could be something else).

*/

private void checkNetworkConnection() {

// BEGIN_INCLUDE(connect)

ConnectivityManager connMgr =

(ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);

NetworkInfo activeInfo = connMgr.getActiveNetworkInfo();

if (activeInfo != null && activeInfo.isConnected()) {

wifiConnected = activeInfo.getType() == ConnectivityManager.TYPE_WIFI;

mobileConnected = activeInfo.getType() == ConnectivityManager.TYPE_MOBILE;

if(wifiConnected) {

Log.i(TAG, getString(R.string.wifi_connection));

} else if (mobileConnected){

Log.i(TAG, getString(R.string.mobile_connection));

}

} else {

Log.i(TAG, getString(R.string.no_wifi_or_mobile));

}

// END_INCLUDE(connect)

}

 

 

获取屏幕的一切信息,来自这个类:

 

getResources().getDisplayMetrics() 得到

DisplayMetrics 这个类,就可以获取到一切有关设备屏幕大小,密度等信息了...

 

// eg: Calculate radiuses in px from dp based on screen density
float density = getResources().getDisplayMetrics().density;

 

关于自定义View中随机颜色的写法:

 

定义十六进制的颜色

 

public final int[] COLORS = {
0xFF33B5E5, 0xFFAA66CC, 0xFF99CC00, 0xFFFFBB33, 0xFFFF4444,
0xFF0099CC, 0xFF9933CC, 0xFF669900, 0xFFFF8800, 0xFFCC0000

};

 

这样就可以根据id动态获取到颜色了

 

int color = COLORS[id % COLORS.length];

 

 

设置背景

 

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
setBackground(states);
else
setBackgroundDrawable(states);

 

 

Tip7: 关于Build


apply plugin: 'com.android.application'

def getGitVersion() {
try {
return 'git rev-parse --short HEAD'.execute().text.trim()
} catch (Throwable th) {
return "";
}
}

android {
compileSdkVersion 23
buildToolsVersion buildToolsVer
useLibrary 'org.apache.http.legacy'

defaultConfig {
minSdkVersion 9
targetSdkVersion 23
buildConfigField "String", "GIT_REVISION", "\"${getGitVersion()}\""
buildConfigField "String", "BUILD_DATE", "\"${new Date().toLocaleString()}\"";
}

signingConfigs {
debug { storeFile file("debug.keystore") }

release {
storeFile file('release.keystore')
storePassword 'thisiskeystorepassword'
keyAlias 'nim_demo'
keyPassword 'thisiskeypassword'
}
}

buildTypes {
debug {
signingConfig signingConfigs.debug
manifestPlaceholders = [ AMAP_KEY:"09fd4efd3e28e9bf1f449ecec7d34bfe" ]
}

release {
minifyEnabled true
zipAlignEnabled true
proguardFile('proguard.cfg')
signingConfig signingConfigs.release
manifestPlaceholders = [ AMAP_KEY:"ee20324fba1c7f4ad7a4a207e7f08e8d" ]
}
}
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = ['src']
resources.srcDirs = ['src']
aidl.srcDirs = ['src']
renderscript.srcDirs = ['src']
res.srcDirs = ['res', 'res-avchat', 'res-chatroom']
assets.srcDirs = ['assets']
jniLibs.srcDirs = ['libs', 'libs-sdk']

}

}

lintOptions {
checkReleaseBuilds false
abortOnError false
}
dexOptions {
incremental true
preDexLibraries false
jumboMode true
}
packagingOptions {
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/NOTICE.txt'
}

}

dependencies {
compile fileTree(dir: 'libs', include: '*.jar', exclude: ['android-support-*.jar'])
compile project(path: ':uikit')
}

 


在Activity中引用build中定义的变量:

 

在AndroidMainfest.xml中引用配置的key:

 

 

 

 

 

时间: 2024-10-13 15:10:01

Android code wiki的相关文章

我的Android进阶之旅------&amp;gt;经典的大牛博客推荐(排名不分先后)!!

今天看到一篇文章,收藏了很多大牛的博客,在这里分享一下 谦虚的天下 柳志超博客 Android中文Wiki AndroidStudio-NDK开发-移动开发团队 谦虚的天下 - 博客园 gundumw100博客 - android进阶分类文章列表 - ITeye技术网站 CSDN博文精选:Android系列开发博客资源汇总 - CSDN.NET - CSDN资讯 Android笔记本--半年来的研究笔记,导航. - 思想实践地 - CSDN博客 [魏祝林]Android中级教程 - Androi

eclipse无法导入Android工程的问题和解决办法

最近在新导入一个Android工程时遇见了已有工程无法导入的情况.具体的现象就是每次导入时的导入窗口很快消失,而在eclipse的package explorer中却没有增加新导入的工程文件夹,没有其他的错误提示. eclipse工程导入的常见方法 1. File->Import->Existing Android Code into Workspace,弹出导入工程窗口,选择导入工程所在目录. 2.在package explorer窗口中单击右键->New->Project...

Android 开源库——侧滑菜单栏(SlidingMenu)的导入和使用

   一:前言     在今天的学习之前:     首先看看我手机中应用了侧滑菜单栏应用:     知乎:                                                                      知乎日报:                                                  Google音乐:                                                               

Android应用开发提高系列(4)——Android动态加载(上)——加载未安装APK中的类

前言 近期做换肤功能,由于换肤程度较高,受限于平台本身,实现起来较复杂,暂时搁置了该功能,但也积累了一些经验,将分两篇文章来写这部分的内容,欢迎交流! 关键字:Android动态加载   声明 欢迎转载,但请保留文章原始出处:)  博客园:http://www.cnblogs.com 农民伯伯: http://over140.cnblogs.com  Android中文Wiki:http://wikidroid.sinaapp.com   正文 一.前提 目的:动态加载SD卡中Apk的类. 注意

在Eclipse添加Android兼容包( v4、v7 appcompat )

昨天添加Android兼容包,碰到了很多问题,在这里记录一下,让后面的路好走. 如何选择兼容包, 请参考Android Support Library Features(二) 一.下载Support Library 方法1:右击项目→选择Android Tools→Add Support Library- 方法2: 通过SDK Manager获取Support Library: 1.打开Android SDK Manager 2.在SDK Manager窗口,滚动到Package List的末尾

android和ios流媒体库推荐

1基本信息编辑 Vitamio是一款 Android 与 iOS 平台上的全能多媒体开发框架,全面支持硬件解码与 GPU 渲染.从2011年8月上线到2014年1月,Vitamio 凭借其简洁易用的 API 接口赢得了全球众多开发者的青睐,全球已经有超过3000 种应用在使用Vitamio,覆盖用户超过5亿. 2功能特性编辑 Vitamio能够流畅播放720P甚至1080P高清MKV,FLV,MP4,MOV,TS,RMVB等常见格式的视频,还可以在Android 与 iOS 上跨平台支持 MMS

android图片加载库Glide

什么是Glide? Glide是一个加载图片的库,作者是bumptech,它是在泰国举行的google 开发者论坛上google为我们介绍的,这个库被广泛的运用在google的开源项目中. Glide解决什么问题? Glide是一个非常成熟的图片加载库,他可以从多个源加载图片,如:网路,本地,Uri等,更重要的是他内部封装了非常好的缓存机制并且在处理图片的时候能保持一个低的内存消耗. Glide怎么使用? 在Glide的使用方面,它和Picasso的使用方法是比较相似的,并且他们的运行机制也有很

Ubuntu搭建Android环境,Ubuntu下An…

Download the Android SDK Platform Package Size MD5 Checksum Windows android-sdk_r13-windows.zip 36487911 bytes de8a039891e5e65b7742f188f07b992d installer_r13-windows.exe (Recommended) 36533357 bytes cd3a76fe2b8ed62b2d03cf1851692e2d Mac OS X (intel) a

Android代码混淆技术总结(一)

Android代码混淆技术总结(一)       一.前言 最近一直在学习Android加固方面的知识,看了不少论文.技术博客以及一些github上的源代码,下面总结一下混淆方面的技术,也算是给想学习加固的同学做一些科普,在文中讲到的论文.资料以及源码,我都会给出相应的链接,供大家进一步去深入学习.后面我会弄成一个系列的文章,如有一些混淆技术没讲到,还希望大家指点,当做是交流学习. 二.Android混淆技术介绍 2.1 控制流平坦化 2.1.1 概念和思路 控制流平坦化,就是在不改变源代码的功