1.如何调用外部图片选择器,选择图片并返回结果
//获取照片
Intent in = new Intent(Intent.ACTION_GET_CONTENT);
in.setType("image/*");
startActivityForResult(in, 0);
然后Activity中还要加上一个结果返回接收
@Override
protected void onActivityResult(int requestCode, int resultCode,
Intent intent)
{
super.onActivityResult(requestCode, resultCode, intent);
System.out.println(intent.getDataString());
ImageView view = new ImageView(this);
view.setImageURI(intent.getData());
((LinearLayout)findViewById(R.id.layout)).addView(view);
System.out.println(requestCode);
}
2.如何调用Google Web Search?
其实android提供了一个很方便的调用方式,就是用Intent去调用系统的Activity,代码如下:
//搜索
Intent search = new Intent(Intent.ACTION_WEB_SEARCH);
search.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
search.putExtra(SearchManager.QUERY, "tigertian");
final Bundle appData = getIntent().getBundleExtra(SearchManager.APP_DATA);
if (appData != null) {
search.putExtra(SearchManager.APP_DATA, appData);
}
startActivity(search);
执行这段代码之后,就会跳转到google的网站并自动搜索与tigertian相关的记录
3.为什么WebView在进行loadUrl的时候,有时候会弹出Android的自带浏览器进行浏览?
被访问页面如果不带跳转(Redirect)是不会弹出自带浏览器的。但如果带跳转(Redirect)的话WebView是做不到的,所以他会调用相应的浏览器进行跳转访问。
4.有按钮的列表项为可以点击吗?
可以,但是需要将按钮的Focusable属性置为false,Checkbox等控件同理。
5.android:layout_weight何时有效果?
<AutoCompleteTextView android:layout_height="wrap_content" android:layout_weight="2"
android:layout_width="wrap_content" android:completionThreshold="1"
android:id="@+id/AutoCompleteSearchGame"></AutoCompleteTextView>
当layout_height和layout_width都未wrap_content的时候有效果。
6、如果调用浏览器?
使用startActivity传递这个intent就可以调用浏览器了new Intent(Intent.ACTION_VIEW, Uri.parse(url))
读取所有电话号码:
一、PhoneLookup.CONTENT_FILTER_URI的一般用法
Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber));
resolver.query(uri, new String[]{PhoneLookup.DISPLAY_NAME,...
API见这里。如果直接如下使用PhoneLookup.CONTENT_FILTER_URI会报IllegalArgument Exception错
getContentResolver().query(PhoneLookup.CONTENT_FILTER_URI,...
二、 技巧用法
Cursor c = getContentResolver().query(Uri.withAppendedPath(
PhoneLookup.CONTENT_FILTER_URI, "*"), new String[] {
PhoneLookup._ID,
PhoneLookup.NUMBER,
PhoneLookup.DISPLAY_NAME,
PhoneLookup.TYPE, PhoneLookup.LABEL }, null, null, sortOrder);
关键是这个"*",这样就能取到所有的号码以及相关的联系人的姓名以及其他相关字段,比通过联系人再查找其号码要方便很多。
Android ListView item中有按钮(Button)不能点击或者条目不能点击的问题:
增加了按钮之后,列表条目不能点击的原因是:需要把Button的相关属性设置成这样
android:focusable="false"
不过在开发过程中,我有个动态获取图片并刷新列表的机制,发现每次调用完notifyDataSetChanged()方法之后Button都不能点击了,后来发现如果有图片动态加载那么每次都要重新inflate整个列表的条目,所以我干脆重载了notifyDataSetChanged()方法。
/**
* Recycle bitmap resources
*/
public void recycleBitmapRes() {
if (mConvertViews != null && !mConvertViews.isEmpty()) {
Collection<View> views = mConvertViews.values();
mConvertViews.clear();
for (View view : views) {
ImageView icon = (ImageView) view.findViewById(R.id.imgIcon);
if (icon != null) {
if (icon.getDrawable() != null && icon.getDrawable() instanceof BitmapDrawable) {
Bitmap bitmap = ((BitmapDrawable) icon.getDrawable()).getBitmap();
if (bitmap != null && !bitmap.isRecycled()) {
bitmap.recycle();
}
}
}
}
}
}
@Override
public void notifyDataSetChanged(){
//Avoiding that buttons cannot be pressed
Utils.LogI("GameListAdapter", "notifyDataSetChanged");
recycleBitmapRes();
super.notifyDataSetChanged();
}
Android弹出拨号界面和拨打电话实现:
需要使用反射机制将ITelephony反射出来进行操作。
private void dial(String number) {
Class<TelephonyManager> c = TelephonyManager.class;
Method getITelephonyMethod = null;
try {
getITelephonyMethod = c.getDeclaredMethod("getITelephony",
(Class[]) null);
getITelephonyMethod.setAccessible(true);
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
TelephonyManager tManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
Object iTelephony;
iTelephony = (Object) getITelephonyMethod.invoke(tManager,(Object[]) null);
Method dial = iTelephony.getClass().getDeclaredMethod("dial", String.class);
dial.invoke(iTelephony, number);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void call(String number) {
Class<TelephonyManager> c = TelephonyManager.class;
Method getITelephonyMethod = null;
try {
getITelephonyMethod = c.getDeclaredMethod("getITelephony",
(Class[]) null);
getITelephonyMethod.setAccessible(true);
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
TelephonyManager tManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
Object iTelephony;
iTelephony = (Object) getITelephonyMethod.invoke(tManager,(Object[]) null);
Method dial = iTelephony.getClass().getDeclaredMethod("call", String.class);
dial.invoke(iTelephony, number);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Android中短信拦截解决方案
经过测试,Android中是可以拦截短信的,解决方案如下:
package com.tigertian.sms;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsMessage;
public class SMSReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
System.out.println("SMSReceiver, isOrderedBroadcast()="
+ isOrderedBroadcast());
Bundle bundle = intent.getExtras();
Object messages[] = (Object[]) bundle.get("pdus");
SmsMessage smsMessage[] = new SmsMessage[messages.length];
for (int n = 0; n < messages.length; n++) {
smsMessage[n] = SmsMessage.createFromPdu((byte[]) messages[n]);
if(smsMessage[n].getMessageBody().contains("hahaha")){
this.abortBroadcast();
}
System.out.println(smsMessage[n].getOriginatingAddress()+" "+smsMessage[n].getMessageBody()+" "+smsMessage[n].getIndexOnIcc());
}
}}
<receiver android:name=".SMSReceiver">
<intent-filter android:priority="10000">
<action android:name="android.provider.Telephony.SMS_RECEIVED"></action>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
上面的代码是一个消息监听,监听接收短信的消息。我们可以从控制台打印信息里面看到,他是一个OrderedBroadcast,根据这一点我们就可以对短信机制进行拦截。如何拦截呢?首先要声明一个消息监听器,同时根据上面的配置文件需要在AndroidManifest.xml中配置好,注意它的优先级是10000,这一点很关键,因为OrderedBroadcast是根据优先级来传递消息的,优先级越高越先获取到消息,待处理完后才会传递给下一个监听器,如果当前监听器退出广播,那么后面的所有监听器都将无法收到消息。其次我们需要实现onReceive方法,根据上面的代码,我们可以从bundle中拿到短信内容并还原成SmsMessage,这样我们可以根据特定条件来判断哪些是需要我们拦截并且不要让用户知道的,哪些是我们可以放行的。需要我们拦截的短信,我们可以在收到后直接abortBroadcast()(上面的代码中是判断当短信内容包含hahaha的时候直接拦截),这样系统收件箱将无法接收到该条短信,继而也就不会有notification去通知用户。至此,应用编写好之后,短信拦截功能就完成了,当然基于此还可以做一些其他功能,这方面就看需求了。注意,优先级相同,则根据包名依次传递广播。想删除收件箱中已存在的短信,请参考Android源码SmsProvider类,可以在你的应用中使用ContentProvider机制进行操作。
Application保存全局变量
class MyApp extends Application {
private String myState;
public String getState(){
return myState;
}
public void setState(String s){
myState = s;
}
}
class Blah extends Activity {
@Override
public void onCreate(Bundle b){
MyApp appState = ((MyApp)getApplicationContext());
String state = appState.getState();
}
}
<application android:name=".MyApp"
android:icon="@drawable/icon"
android:label="@string/app_name">
android异步图片加载中的图片缓存:
读取大文件流的问题:缓存
开多线程把图片从网络上荡下来以后,首先缓存至本地文件夹 //android.content.ContextWrapper.getCacheDir() android系统提供的一个存放和得到缓存文件夹的方法
然后对文件全路径截取后缀之前的内容进行MD5加密并与后缀拼成一个文件名,根据这个文件名和传入的路径构建一个文件 写一个缓存方法 判断是否存在缓存文件
如果是则返回加密后文件的Uri,如果不是则从网上下载文件并返回文件的Uri.做缓存的目的是用缓存的文件,而Uri就可以唯一标识一个文件。
public static Uri cacheFile(String path,File saveDir)throws Exception{
File file = new File(saveDir, MD5.getMD5(path)+ path.substring(path.lastIndexOf('.')));
if(file.exists()){
return Uri.fromFile(file);
}else{
FileOutputStream outStream = new FileOutputStream(file);
HttpURLConnection conn = (HttpURLConnection)new URL(path).openConnection();
conn.setConnectTimeout(5 * 1000);
conn.setRequestMethod("GET");
if(conn.getResponseCode()==200){
InputStream inStream = conn.getInputStream();
byte[] buffer = new byte[1024];
int len = 0;
while( (len = inStream.read(buffer)) !=-1 ){
outStream.write(buffer, 0, len);
}
outStream.close();
inStream.close();
return Uri.fromFile(file);
}else{
throw new Exception("文件下载失败!");
}
}
}
视频格式的压缩
l source=source.avi
l ffmpeg -t 600 -i $source -acodec libfaac -ab 128k -ac 2 -vcodec libx264 \
l -vpre hq -crf 22 -threads 0 tmp.mp4 && \
l /usr/bin/MP4Box -3gp -mtu 1450 -hint tmp.mp4 -out target.mp4
插入删除图片MediaScanner缓存问题
插入图片
当你打算在删掉时 : ContentValues values = new ContentValues();
values.put(Images.Media.TITLE, filename);
values.put(Images.Media.DATE_ADDED, System.currentTimeMillis());
values.put(Images.Media.MIME_TYPE, "image/jpeg");
Uri uri = this.getContentResolver().insert(Images.Media.EXTERNAL_CONTENT_URI, values);
File f = new File(imageURI);
f.delete();
在gallery中就会出现占位符 主要是因为MediaScanner有一个缓存
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStorageDirectory())));
AndroidManifest.xml:
<intent-filter>
<action android:name="android.intent.action.MEDIA_MOUNTED" />
<data android:scheme="file" />
</intent-filter>
屏幕旋转的设置:
1. @Override
2. public void onConfigurationChanged(Configuration newConfig) {
3. super.onConfigurationChanged(newConfig);
4. ImageView header = (ImageView) this.findViewById(R.id.header);
5. if ( newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE ) {
6. header.setImageResource(R.drawable.header480);
7. }
8. else if ( newConfig.orientation == Configuration.ORIENTATION_PORTRAIT ) {
9. header.setImageResource(R.drawable.header320);
10. }
11. }
ListView适配器getView()优化
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.list_item_icon_text, null);
holder = new ViewHolder();
holder.text = (TextView) convertView.findViewById(R.id.text);
holder.icon = (ImageView) convertView.findViewById(R.id.icon);
convertView.setTag(holder); //设置标记
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.text.setText(DATA[position]);
holder.icon.setImageBitmap((position & 1) == 1 ? mIcon1 : mIcon2);
return convertView;
}
static class ViewHolder {
TextView text;
ImageView icon;
}
android ListView几个比较特别的属性:
首先是stackFromBottom属性,这只该属性之后你做好的列表就会显示你列表的最下面,值为true和false
android:stackFromBottom="true"
第二是transciptMode属性,需要用ListView或者其它显示大量Items的控件实时跟踪或者查看信息,并且希望最新的条目可以自动滚动到可视范围内。通过设置的控件transcriptMode属性可以将Android平台的控件(支持ScrollBar)自动滑动到最底部。
android:transcriptMode="alwaysScroll"
第三cacheColorHint属性,很多人希望能够改变一下它的背景,使他能够符合整体的UI设计,改变背景背很简单只需要准备一张图片然后指定属性 android:background="@drawable/bg",不过不要高兴地太早,当你这么做以后,发现背景是变了,但是当你拖动,或者点击list空白位置的时候发现ListItem都变成黑色的了,破坏了整体效果。
如果你只是换背景的颜色的话,可以直接指定android:cacheColorHint为你所要的颜色,如果你是用图片做背景的话,那也只要将android:cacheColorHint指定为透明(#00000000)就可以了
第四divider属性,该属性作用是每一项之间需要设置一个图片做为间隔,或是去掉item之间的分割线
android:divider="@drawable/list_driver" 其中 @drawable/list_driver 是一个图片资源,如果不想显示分割线则只要设置为android:divider="@drawable/@null" 就可以了
第五fadingEdge属性,上边和下边有黑色的阴影
android:fadingEdge="none" 设置后没有阴影了~
第五scrollbars属性,作用是隐藏listView的滚动条,
android:scrollbars="none"与setVerticalScrollBarEnabled(true);的效果是一样的,不活动的时候隐藏,活动的时候也隐藏
第六fadeScrollbars属性,android:fadeScrollbars="true" 配置ListView布局的时候,设置这个属性为true就可以实现滚动条的自动隐藏和显示。
java和javascript互相调用
mWebView = (WebView) findViewById(R.id.webview);
WebSettings mWebSettings = mWebView.getSettings();
//加上这句话才能使用javascript方法
mWebSettings.setJavaScriptEnabled(true);
//增加接口方法,让html页面调用
mWebView.addJavascriptInterface(new Object() {
//这里我定义了一个拨打电话应用的方法
public void callPhone() {
Uri uri= Uri.parse("tel:12345");
Intent mIntent = new Intent(Intent.ACTION_CALL,uri);
startActivity(mIntent);
}
}, "demo");
//加载页面
mWebView.loadUrl("file:///android_asset/demo.html");
mButton = (Button) findViewById(R.id.button);
//给button添加事件响应,执行JavaScript的fillContent()方法
mButton.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
mWebView.loadUrl("javascript:fillContent()");
}
});
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
</head>
<script>
function fillContent(){
document.getElementById("content").innerHTML =
"java调用javascript哈哈,这些话是javascript搞出来的";
}
</script>
<body>
<p><a onClick="window.demo.callPhone()" href="">打电话</a></p>
<p id="content"></p>
<p>java和javascript相互调用</p>
</body>
</html>
<?xml version="1.0" encoding="utf-8"?> </manifest> |
GreenSkin
与BlackSkin项目一样,该工程下也没有任何代码,只是在res\drawable目录下放置2张图片,一张绿色的背景,一张绿色的按钮图片。接着修改AndroidManifest.xml文件。
<?xml version="1.0" encoding="utf-8"?> </manifest> |
我们知道Android给每个APK进程分配一个单独的用户空间,其manifest中的userid就是对应一个Linux用户的(Android 系统是基于Linux)。所以不同APK(用户)间互相访问数据默认是禁止的,但是它也提供了2种APK间共享数据的形式:
1. Share Preference. / Content Provider
APK可以指定接口和数据给任何其他APK读取,需要自己实现接口和Share的数据.
2. Shared User id
通过Shared User id,拥有同一个User id的多个APK可以配置成运行在同一个进程中。所以默认就是可以互相访问任意数据。也可以配置成运行成不同的进程,同时可以访问其他APK的数据目录下的数据库和文件。就像访问本程序的数据一样。本文中的换主题功能就是通过这种方式来实现的。
MainSkin
该工程为主应用,我们新建立一个Activity类,叫MainActivity.java。代码如下:
public class MainActivity extends Activity { @Override |