java/框架/数据库面试总结
此面试题是我搜索,汇总,涵盖了java、框架、前台、数据库面试精华
java+数据库+ssh+js面试大全
这里有最全的java面试、数据库面试、大数据量处理面试、ssh面试
看完此面试题,没有不通过的
linux命令大全
linux命令大全.
非常经典的命令
JAVA经典算法90题
java很全的java经典算法
经典例子
面试精选编程规范精选(java、oracle)
java面试必备
oracle编程规范
java编程规范
屏幕截图工具
一款强大的屏幕截图,使用方面,代码精炼,欢迎下载、点评
java技术网站
java技术网站,提供各种技术实例
我的收藏
android的基本知识的demo
android的基本知识的demo,里面有一些特效
android地图的使用
android地图的使用,附代码的demo
隐藏状态栏
G1的屏幕的分辨率是320×480,虽说不小但也谈不上大,所以有的应用要使用起来,最好还是希望把状态栏(Status Bar)和标题栏(Title Bar)也隐藏了,这样就可以有更大的屏幕空间给应用程序。
view plaincopy to clipboardprint?
1.
2. @Override
3. public void onCreate(Bundle icicle) {
4. super.onCreate(icicle);
5.
6. final Window win = getWindow();
7. // No Statusbar
8. win.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
9. WindowManager.LayoutParams.FLAG_FULLSCREEN);
10.
11. // No Titlebar
12. requestWindowFeature(Window.FEATURE_NO_TITLE);
13.
14. setContentView(R.layout.mylayout);
15. }
摘自anddev
透明与窗体的设置
1. Custom Dialog
Android支持自定义窗口的风格:
1)首先在资源里面建立style的value;
example:
<style name="Theme.CustomDialog" parent="android:style/Theme.Dialog">
<item name="android:windowBackground">@drawable/filled_box</item>
</style>
drawable/filled_box.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#f0600000"/>
<stroke android:width="3dp" color="#ffff8080"/>
<corners android:radius="3dp" />
<padding android:left="10dp" android:top="10dp"
android:right="10dp" android:bottom="10dp" />
</shape>
PS:关于Styles的学习,可以参见:http://code.google.com/android/reference/available-resources.html#stylesandthemes
2)设置当前activity的属性,两种方式:1.在manifest文件中给指定的activity增加属性
android:theme="@android:style/Theme.CustomDialog"。2.在程序中增加语句setTheme(R.style.Theme_CustomDialog);
PS1:如果只是将Acticity显示为默认的Dialog, 跳过第一步,只需要在manifest文中增加属性:android:theme="@android:style/Theme.Dialog"或者在程序中增加setTheme(android.R.style.Theme_Dialog).
PS2:其他创建Dialog的方法:创建app.Dialog类或者创建app.AlertDialog类。
Next Study:能不能在Activity已经打开以后动态修改当前Activity的风格?
在测试中发现,在onCreate()事件中增加setTheme(),必须在setContentView()之前,否则指定的Style不能生效
2.Custom Title
Android除了可以为指定的Activity设置显示风格,此外也可以为指定的Activity设置一些特效,比如自定义Title,没有Title的Activity或者增加一个ICON等。
有意思的一点是,这些特效并不是你想设置的时候就行设置,你需要在Activity显示之前向系统申请要显示的特效,这样才能在下面的程序中为这些特效进行设置。(这样是不是多此一举有待研究)
为一个Activity设置自定义Title的流程:
1)为自定义的Title建立一个layout(custom_title_1.xml)
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/screen"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:orientation="vertical">
<TextView android:id="@+id/left_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:text="Left" />
<TextView android:id="@+id/right_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:text="Right" />
</RelativeLayout>
关于为什么采用RelativeLayout,可以参见:http://code.google.com/android/devel/ui/layout.html
2)为activity设定自定义Title特效并指定Title的layout:
在onCreate()事件中增加:
requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
setContentView(R.layout.custom_title);
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.custom_title_1);
这三条语句的次序不能颠倒,依次为申请特效,创建view,设置特效属性。其中requestWindowFeature等价于getWindow().requestFeature()
3)在需要修改Title的地方,获取left_text或者right_text进行设置即可。
Next Study:Activity的其他显示特效
Window还有其他一些feature,比如FEATURE_CONTEXT_MENU,FEATURE_NO_TITLE,FEATURE_LEFT_ICON等,有待继续学习研究。
Translucent
Android为透明效果提供了内置的Theme: android:style/Theme.Translucent,只需要把当前的activity的theme设置为这个Theme就可以达到完全透明的效果。
如果要半透明的话,可以增加一个继承该Theme的style即可,实现如下:
<style name="Theme.Translucent" parent="android:style/Theme.Translucent">
<item name="android:windowBackground">@drawable/translucent_background</item>
<item name="android:colorForeground">#fff</item>
</style>
<drawable name="translucent_background">#e0000000</drawable>
此外API Demo中提供了另一个实例,不用继承内置的Theme,可以自己完全创建一个新的style,实现透明效果,同时可以加一些其他特效,比如模糊化等,但我试了半天也没有搞定,完全复制代码,也没有出现这个效果,这个现在可能不是很重要的东西,等以后有时间再研究补充吧。
android 快速翻书
要快速更新畫面的話,可以使用android.view.SurfaceView
照比較正常的作法, 如果不是做Game之類的應該通常會新增thread處理工作後, 使用handler傳送msg去View#invalidate畫面, 或是在非UI thread呼叫View#postInvalidate.
所以如果需要比較高效的畫面更新就可以用看看android.view.SurfaceView
因為他可以讓其他非UI thread直接對畫面操作
做法就是透過SurfaceView的getHolder取得SurfaceHolde,然後對SurfaceHolder的Canvas畫圖
android activity 生命周期
1. 最上層(即焦點所在)。
2. 不在最上層,但被上層蓋掉一部份(還有一部份可看到)。
---- 在此情形發生之際,框架會立即反向呼叫和 onPause()函數。
---- 一旦恢復為最上層時,框架又立即反向呼叫 onResume()函數。
---- 上圖 6-5 就表達了這樣的循環。
3. 不在最上層,而且全部被上層覆蓋掉(全部看不到了)。
---- 在此情形發生之際,框架會立即反向呼叫 onPause()函數,而且呼
叫 onStop()函數。
---- 一旦恢復為最上層時,框架又立即依序反向呼叫 onRestart()、
onStart()和 onResume()函數。
---- 上圖 6-5 也表達了這樣的循環。
※ 由於像 ac01 物件可能會被刪除掉,所以你在寫程式時,可以在框架反向呼
叫 onPause()和 onStop()函數時,趁機把重要的資料存起來,以免被刪除掉。
※ 一但系統又將 ac01 物件恢復時,可以在框架反向呼叫 onRestart()、
onStart()、onResume()函數時,趁機把重要的資料取回來,以便恢復原狀。
※ 在本節裡,只先藉由 onResume()函數,來說明這些框架反向呼叫的用意。在
本書後續各章將會有更詳細的範例說明其它函數的用法。◆p178 高
Activity 是我们开发Android应用程序最重要的一个类。这个类的内容比较多,我理解多少
就写多少,希望你喜欢:)
Service开机自动启动
android上怎样让一个Service开机自动启动
Posted on 2009-02-08 21:55 hk_king 阅读(168) 评论(0) 编辑 收藏 网摘 所属分类: 移动开发
转载出处:http://www.androidlab.cn/viewthread.php?tid=421&extra=page%3D1
1.首先开机启动后系统会发出一个Standard Broadcast Action,名字叫android.intent.action.BOOT_COMPLETED,这个Action只会发出一次。
2.构造一个IntentReceiver类,重构其抽象方法onReceiveIntent(Context context, Intent intent),在其中启动你想要启动的Service。
3.在AndroidManifest.xml中,首先加入<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"></uses-permission>来获得BOOT_COMPLETED的使用许可,然后注册前面重构的IntentReceiver类,在其<intent-filter>中加入<action android:name="android.intent.action.BOOT_COMPLETED" /> ,以使其能捕捉到这个Action。
一个例子
xml:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"></uses-permission>
<receiver android:name=".OlympicsReceiver" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</receiver>
java:
public class OlympicsReceiver extends IntentReceiver
{
/*要接收的intent源*/
static final String ACTION = "android.intent.action.BOOT_COMPLETED";
public void onReceiveIntent(Context context, Intent intent)
{
if (intent.getAction().equals(ACTION))
{
context.startService(new Intent(context,
OlympicsService.class), null);//启动倒计时服务
Toast.makeText(context, "OlympicsReminder service has started!", Toast.LENGTH_LONG).show();
}
}
}
注意:现在的IntentReceiver已经变为BroadcastReceiver,OnReceiveIntent为onReceive。所以java这边的代码为:
(也可以实现应用程序开机自动启动)
public class OlympicsReceiver extends BroadcastReceiver
{
/*要接收的intent源*/
static final String ACTION = "android.intent.action.BOOT_COMPLETED";
public void onReceive(Context context, Intent intent)
{
if (intent.getAction().equals(ACTION))
{
context.startService(new Intent(context,
OlympicsService.class), null);//启动倒计时服务
Toast.makeText(context, "OlympicsReminder service has started!", Toast.LENGTH_LONG).show();
//这边可以添加开机自动启动的应用程序代码
}
}
}
去掉所有的html标签
private String stripTags(final String HTMLString) {
final String noHTMLString = HTMLString.replaceAll("\\<.*?>","");
return noHTMLString;
}
背景透明和模糊
android的背景透明模糊的使用,详解见文档
sqlite的特殊使用
其SQL語
句的格式為:
create table table_name
(column_name1 column_type, column_name2 column_type, …);
例如:
create table Student(stud_no text primary key, stud_name text);
如果你想知道學號為‘102’以外的學生名字,可以寫如下:
select stud_no, stud_name from Student where stud_no ‘102’ ;
如果你想知道學號不是‘101’,而且學生名字不是‘Linda’的資料,可以寫為:
select stud_name from Student
where stud_no ‘101’ and stud_name ‘Linda’;
這就把兩個表格聯結起來:
select Student.stud_name, Course.course_name from Student, Course
where Student.stud_no = Course.stud_no;
這會進行加總了:
select SUM(score1), SUM(score2) from New_Course;
還可計算平均值:
select AVG(score1), AVG(score2) from New_Course
New_Course 表格
course_name stud_no score1 score2
DATABASE 101 70.0 74.5
ART 101 60.0 45.0
DATABASE 102 95.0 90.5
GROUP BY 子句可建立比較小的組(Group),並且對每一個組進行加總等運
算。換句話說,它產生每一組的整體性資訊。例如:
select course_name, SUM(score1), SUM(score2) from New_Course
group by course_name
得出結果為:
course_name SUM(score1) SUM(score2)
DATABASE 165.0 165.0
ART 60.0 45.0
藉由 GROUP BY 語句,可以讓 SUM()等函數對屬於一組的資料進行運算。當
你指定「GROUP BY 區域」時, 屬於同一個區域的一組資料將只會得到一行
(Column)的值。◆
private static class DatabaseHelper extends SQLiteOpenHelper {
DatabaseHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
@Override public void onCreate(SQLiteDatabase db) {}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}
}
private DatabaseHelper mOpenHelper;
public void onClick(View v){
if (v == btn){
mOpenHelper = new DatabaseHelper(v.getContext());
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
String sql = "create table Student(" + "stud_no text not null, "
+ "stud_name text );";
try { db.execSQL(sql); setTitle("create table ok!"); }
catch (SQLException e) {
Log.e("ERROR", e.toString());
setTitle("create table Error!");
}}
if (v == btn2){
mOpenHelper = new DatabaseHelper(v.getContext());
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
String sql = "drop table Student";
try { db.execSQL(sql); setTitle("drop table ok!"); }
catch (SQLException e) {
Log.e("ERROR", e.toString());
setTitle("drop table Error!");
}}
f (v == btn3){
mOpenHelper = new DatabaseHelper(v.getContext());
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
String sql_1 = "insert into Student (stud_no, stud_name) values('S108', 'Lily Chen');";
String sql_2 = "insert into Student (stud_no, stud_name) values('S201', 'Tom Kao');";
String sql_3 = "insert into Student (stud_no, stud_name) values('S333', 'Peter Rabbit');";
try { db.execSQL(sql_1); db.execSQL(sql_2); db.execSQL(sql_3);
setTitle("insert records ok!");
} catch (SQLException e) { Log.e("ERROR", e.toString()); }
}
if (v == btn4){
mOpenHelper = new DatabaseHelper(v.getContext());
SQLiteDatabase db = mOpenHelper.getReadableDatabase();
String col[] = {"stud_no", "stud_name" };
cur = db.query("Student", col, null, null, null, null, null);
Integer n = cur.getCount(); String ss = Integer.toString(n);
setTitle(ss + " records"); cur.moveToFirst();
}
if (v == btn5) finish();
}}
***************8
private static class DatabaseHelper extends SQLiteOpenHelper {
DatabaseHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION); }
@Override public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE Student("
+ "stud_no" + " TEXT PRIMARY KEY,"
+ "stud_name" + " TEXT" + ");"); }
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}
}
@@@@@@@@@
if (v == btn3){
mOpenHelper = new DatabaseHelper(v.getContext());
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put("stud_no", "S108"); cv.put("stud_name", "Lily Chen");
db.insert("Student", null, cv);
cv = new ContentValues(); cv.put("stud_no", "S201");
cv.put("stud_name", "Tom Kao");
db.insert("Student", null, cv);
cv = new ContentValues(); cv.put("stud_no", "S333");
cv.put("stud_name", "Peter Rabbit");
db.insert("Student", null, cv); setTitle("insert record ok!"); }
if (v == btn4){
mOpenHelper = new DatabaseHelper(v.getContext());
SQLiteDatabase db = mOpenHelper.getReadableDatabase();
String col[] = {"stud_no", "stud_name" };
cur = db.query("Student", col, null, null, null, null, null);
Integer n = cur.getCount(); String ss = Integer.toString(n);
setTitle(ss + " records"); cur.moveToFirst(); }
if (v == btn5){
if(!cur.isAfterLast()){
String ss = cur.getString(0) + ", " + cur.getString(1);
setTitle(ss); cur.moveToNext(); }
else setTitle("======"); }
if (v == btn6){
mOpenHelper = new DatabaseHelper(v.getContext());
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put("stud_no", "S288"); cv.put("stud_name", "Linda Wang");
db.update("Student", cv, "stud_no = 'S201'", null); }
if (v == btn7){
mOpenHelper = new DatabaseHelper(v.getContext());
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
db.delete("Student", "stud_no = 'S108'", null); }
if(v.equals(btn8)){
mOpenHelper = new DatabaseHelper(v.getContext());
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
if (db != null) db.close();
this.finish();
}}}
1. 欲新增一筆資料時,上一個範例使用 SQL 語句來達成,如下:
String sql = "insert into Student (stud_no, stud_name)
values ('S108', 'Lily Chen');";
db.execSQL(sql_1);
在本範例則採用另一種途徑,將資料先存入 Android的 ContentValues物件裡,
然後將此物件當成參數而傳遞給 db.insert()函數,如下:
ContentValues cv = new ContentValues();
cv.put("stud_no", "S108"); cv.put("stud_name", "Lily Chen");
db.insert("Student", null, cv);
2. 查詢時,把欲查出的欄位名稱存於字串陣列裡,再把它傳給 db.query()函數即
可。如下:
String col[] = {"stud_no", "stud_name" };
cur = db.query("Student", col, null, null, null, null, null);
Integer n = cur.getCount();
查詢之後,db.query()回傳資料庫游標(Cursor)值給 cur,然後 cur.getCount()就
傳回所查到的資料筆數。
3. 指令: if( !cur.isAfterLast() ){
String ss = cur.getString(0) + ", " + cur.getString(1);
// …….
cur.moveToNext();
}
由 cur.isAfterLast()判斷目前是否已經超出最後一筆資料了。如果不是,就藉由
cur.getString(0)取得第 1 個欄位的資料;而 cur.getString(0)取得第 2 個欄位的資
料值。
intent的各种用法
How to use Intent to send an email, SMS, open a web browser, show map, etc.?
Intent 應該算是 Andorid 中特有的東西。你可以在 Intent 中,指定要應用程式執行的動作 (view, edit, dial),以及應用程式執行該動作時,所需要的資料。都指定好後,只要透過 startActivity(),Android 系統會自動尋找,最符合你指定要求的應用程式,並喚起執行該應用程式。
不過,這部份的文件還不是很完整。Reference of Available Intents 有列一些。底下是我收集的一些用法,分享出來給有需要的你。有些還沒有實際驗證過,如果發現有錯誤,或有新的用法,也請告訴我。
详解intent
当一个application 中有多个 Activity的时候,那么每个Activity之前的传值就是一个问题了。所以这里介绍一下相关的方法。
在Android平台传值,主要使用两种方法一个事 PendingIntent 另一个就是广播了
按照大类,我把相关的类进行了划分
1.实体类 Intent 、Context 、 BroadcastReceiver
2.方法类 PendingIntent Context.sendBroadcast
传递的方法 也就是方法类中的两种
AutoCompleteTextView 显示更多
AutoCompleteTextView 显示更多
android APK的安装卸载
制作好apk后(必须签名),通过adb install xx.apk后,
1)apk文件放在了/data/app/目录下
2)/data/system/packages.xml中增加了条记录
3)如果使用到了数据库,首次运行后/data/data下增加了个apk使用到的数据目录
卸载方式有如下几种:
1)优雅式:通过界面 settings-->applications-->manage applications-->找到应用-->application Info-->uninstall 就可以正常卸载应用了。
2)粗暴式 直接到/data/app目录下删除apk
adb shell
cd /data/app
rm xxx.apk
不推荐这种方式,只删除了apk,如果应用还有其他的目录,如数据库目录/data/data/xxx/databases/并没有清理干净,留有隐患。
3)隐藏式:
adb uninstall package-name (这个在adb的帮助文档中没有说明,但可以用)
什么,不知道package-name?看看你的AndroidManifest.xml中有个必须的属性就是package,它所指定的就是package-name。
PS. android中package和application不是一个东西,但也没有看到清楚的解释。能否这样理解:
package是物理概念,application是运行期的逻辑概念?
android 翻书源码及资料
在android中实现手势翻页效果,主要用到ViewFlipper和GestureDetector.
ViewFlipper变化当前显示内容,GestureDetector监听手势. 用于多页的展示非常酷.
引入了贝塞尔曲线,设置了翻页区域,灵敏度更佳,翻书效果非常明显
android 数据存取Preferences
Android数据存取之Preferences
这种方式应该是用起来最简单的Android读写外部数据的方法了。他的用法基本上和J2SE(java.util.prefs.Preferences)中的用法一样,以一种简单、 透明的方式来保存一些用户个性化设置的字体、颜色、位置等参数信息。一般的应用程序都会提供“设置”或者“首选项”的这样的界面,那么这些设置最后就可以 通过Preferences来保存,而程序员不需要知道它到底以什么形式保存的,保存在了什么地方。当然,如果你愿意保存其他的东西,也没有什么限制。只是在性能上不知道会有什么问题。
android logcat使用
Android SDK下, 如何在程序中输出日志 以及如何查看日志.
闲话少说,直接进入正题
在程序中输出日志, 使用 android.util.Log 类.
该类提供了若干静态方法
Log.v(String tag, String msg);
Log.d(String tag, String msg);
Log.i(String tag, String msg);
Log.w(String tag, String msg);
Log.e(String tag, String msg);
分别对应 Verbose, Debug, Info, Warning,Error.
tag是一个标识,可以是任意字符串,通常可以使用类名+方法名, 主要是用来在查看日志时提供一个筛选条件.
程序运行后 并不会在 ide的控制台内输出任何信息.
如果要后查看日志 请使用
adb logcat
关于adb的更多信息请查看官方网站.
当执行 adb logcat 后会以tail方式实时显示出所有的日志信息.
这时候我们通常需要对信息进行过滤,来显示我们需要的信息, 这时候我们指定的 tag就派上了用场.
adb logcat -s MyAndroid:I
这时将只显示tag为MyAndroid,级别为I或级别高于I(Warning,Error)的日志信息.
示例代码如下:
Java代码
1. package com.zijun;
2.
3. import android.app.Activity;
4. import android.content.Context;
5. import android.graphics.Canvas;
6. import android.os.Bundle;
7. import android.util.Log;
8. import android.view.MotionEvent;
9. import android.view.View;
10.
11. public class MyAndroid extends Activity {
12.
13. protected static final String ACTIVITY_TAG="MyAndroid";
14.
15. @Override
16. protected void onCreate(Bundle icicle) {
17. super.onCreate(icicle);
18. setContentView(new MyView(this));
19. }
20. public class MyView extends View {
21. public MyView(Context c) {
22. super(c);
23. }
24. @Override
25. protected void onDraw(Canvas canvas) {
26.
27. }
28. @Override
29. public boolean onMotionEvent(MotionEvent event) {
30. Log.i(MyAndroid.ACTIVITY_TAG, "=============================");
31.
32. Log.d(MyAndroid.ACTIVITY_TAG, "Haha , this is a DEBUG of MyAndroid. ");
33. Log.i(MyAndroid.ACTIVITY_TAG, "Haha , this is a INFO of MyAndroid. ");
34. Log.w(MyAndroid.ACTIVITY_TAG, "Haha , this is a WARNING of MyAndroid. ");
35.
36. return true;
37. }
38.
android服务
很多情况下,一些与用户很少需要产生交互的应用程序,我们一般让它们在后台运行就行了,而且在它们运行期间我们仍然能运行其他的应用。
为了处理这种后台进程,Android引入了Service的概念。Service在Android中是一种长生命周期的组件,它不实现任何用户界面。最常见的例子如:媒体播放器程序,它可以在转到后台运行的时候仍然能保持播放歌曲;或者如文件下载程序,它可以在后台执行文件的下载。
android多线程断点续传
断点:
首要问题(多线程下载)已经被我们解决了,支持断点下载想必大家也已经想到了。就是将下载的进度保存到文件中,但在Android中却不能这么做。通过老黎的试验,在Android平台中,我们需要向文件中写出下载的文件数据,还需要向另一个文件中写出下载进度,这样会出错。这样会导致有一个文件的内容没有被写出。所以我们就不能以文件的方式来保存下载进度,但可以通过数据库的方式保存下载进度。
这两大问题我们已经有了解决思路,那么就开始动手编写吧!
android调试原理
(笔记中提到的Emulator也可以理解成Device)
一、adb的介绍:
adb(Android Debug Bridge)包括三个部分:
1)adb client, 运行在PC上(为DDMS,即IDE工作)
2)adb daemon(守护进程), 运行于Emulator(为与Emulator中的VM交互工作);
3)adb server(服务进程), 运行在PC(任务管理器上有),管理着adb client和adb daemon的通信.server与client通信的端口是是5037,
adb server会与emulator交互的,使用的端口有两个,一个是5554专门用于与Emulator实例的连接,那么数据可以从Emulator转发给IDE控制台了,另一个则是5555,专门与adb daemon连接为后面调试使用。
PS:Emulator/Device占用两个(一组)端口,一个为偶数的5554,一个奇数的5555。
如果还开启其他的Emulator,则使用的另一组端口是5556,5557,一直到5585.
adb server开启时就是通过查找5555-5585之间端口来建立与模拟器的连接的,建立连接后就可以用adb的相关命令了。
如果您安装了ADT就基本不需要adb的命令了(因为DDMS会调用ADB进行透明操作)
关于本机的端口使用情况可以使用netstat [-a] [-n]来查询验证一下。
二、观察一组数据:
1,在开启仿真器时有一些打印:
[2009-06-06 14:04:16 - Helloworld] Android Launch!
[2009-06-06 14:04:17 - Helloworld] adb is running normally.
[2009-06-06 14:04:17 - Helloworld] Performing com.android.hello.Helloworld activity launch
[2009-06-06 14:04:17 - Helloworld] Automatic Target Mode: Preferred AVD 'lab' is not available. Launching new emulator.
[2009-06-06 14:04:17 - Helloworld] Launching a new emulator with Virtual Device 'lab'
[2009-06-06 14:04:24 - Helloworld] New emulator found: emulator-5554
[2009-06-06 14:04:24 - Helloworld] Waiting for HOME ('android.process.acore') to be launched...
[2009-06-06 14:05:45 - Helloworld] HOME is up on device 'emulator-5554'
[2009-06-06 14:05:45 - Helloworld] Uploading Helloworld.apk onto device 'emulator-5554'
[2009-06-06 14:05:45 - Helloworld] Installing Helloworld.apk...
每一行都基本表示一个命令在执行,emulator-5554是仿真器的初始端口了。
最后一句等于命令:adb -s emulator-5554 install helloworld.apk
如果报了类似以下的错误,那得(加个-r)重装,因为该App已经在该Emulator下运行了
DDM dispatch reg wait timeout
Can't dispatch DDM chunk 52454151: no handler defined
Can't dispatch DDM chunk 48454c4f: no handler defined
网上没有看到这个错误因此顺便提下解决方法:adb -s emulator-5554 install -r helloworld.apk
三,了解下DDMS:(都是adb的命令相当的功能)
DDMS有几个界面:
1)Devices:可以查看到当前运行的Emulator和其内运行的应用
2)Emulator control,即仿真器的硬件设置项等:
设置当前注册的网络状态(Home,Roaming,UnRegistered,Searching)
数据业务的速度设置:有GSM,GPRS,EDGE,UMTS,HSDPA(3.5G?)
还有载入KML或NMEA文件来模拟GPS数据
3)还可以查询Threads,Heap,File Explorer、重启adb,抓屏等,其他都是在调用adb。
4)关于Logcat
从Windows->Prereference->android->DDMS->Loggin Level进行设置打印等级,
不过默认下只打印入口线程的信息,射频和Tapi的动作信息要通过adb Logcat -b radio打开,
os-events相关的打印通过adb logcat -b events.打开,
Log默认被写入到手机的/data/anr/traces.txt文件中。
四,Debug面板
这个面板对于熟悉Eclipse的用户来说应该不用看了。
通过以下三步将自己的应用或将已经跑起来的应用加入调试列表:
1)选择Devices列表中Your app,
2)选择臭虫按钮将该程序加载进调试状态
3)OK,加断点吧。不过源代码要最新的否则断点不起作用。
五、DDMS如何让IDE的调试工作起来呢?
1)有几个组成:
一个是adb(Android Debug Bridge)参考第一部分,它起到调试桥的作用;
另一类是运行在Device/Emulator端的adb daemon, VM, debugger, your Applicatioin,
通过下面句话就可以理解它们的关系:
一个App跑在一个进程中,这个进程又被一个VM绑定,都是一对一的,但VM与Emulator显然是多对一的,
那调试时debugger从VM中拿到栈线程进程等信息,而daemon的作用仅仅是被DDMS用于建立一条连接(看下面)。
最后一类则是运行在PC上的DDMS debugger;
这个debugger是IDE的调试器,你可以改成另一个调试器;
DDMS是Dalvik Debug Monitor Service,负责建立调试的作用,它仅有两个Service,其他的功能都是通过ADB client.让IDE与Emulator交互起来的。
2)开启IDE时,DDMS会建立一个Device monitoring service用于监控Emulator,因为可以开启多个Emulator嘛;
如果找到一个Emulator,那么DDMS才会再开启另一个Service叫VM Monitoring Sevice用于监控该Emulator下的VM; 第一部分提到adb有三个部分,其中的adb client可以多个实例的,DDMS的Service通过从ADB Client与ADb server的交互结果来维护自身的数据。
如果VM Monitor找到Emulator的一个VM,那么DDMS会利用ADB获取目标VM的进程ID,
同时通过client与daemon建立起与vm的debugger的新连接,注意新连接的交互端口是从8600开始的(n个的话端口是8659+n),这条新连接可以让DDMS获得与VM的实际交互。
剩下的就是DDMS把拿到的数据再扔给ide 的 debugger(它们之间默认通过8700端口,可更改,因为与VM的交互端口从8600开始使用的话可能会不够的),
这样IDE的Debug视图就能正确工作了.
android Intent实例
2009-01-18
Android应用协调器------Intent
关键字: android intent实例
刚起步的时候经常困扰我们的是一些本来容易解决的问题,往往我们会花掉很大的力气去找解决的办法,最后才知道原来这么简单,这就是英文世界造成的。
Intent在Android应用开发中,占有很大的分量,关于Intent在Android中的作用在网络上已经有很多资料了,这里不再累赘,本人喜欢直来直去。在网上看到很多关于Intent的资料,说那么多,你也许还是一头雾水,到底如何使用Intent呢?这里总结一些重用的Intent使用,仅供参考。
下面直接给我学习的实例片段。
1,调用web浏览器
Uri myBlogUri = Uri.parse("http://kuikui.javaeye.com");
returnIt = new Intent(Intent.ACTION_VIEW, myBlogUri);
2,地图
Uri mapUri = Uri.parse("geo:38.899533,-77.036476");
returnIt = new Intent(Intent.ACTION_VIEW, mapUri);
3,调拨打电话界面
Uri telUri = Uri.parse("tel:100861");
returnIt = new Intent(Intent.ACTION_DIAL, telUri);
4,直接拨打电话
Uri callUri = Uri.parse("tel:100861");
returnIt = new Intent(Intent.ACTION_CALL, callUri);
5,卸载
Uri uninstallUri = Uri.fromParts("package", "xxx", null);
returnIt = new Intent(Intent.ACTION_DELETE, uninstallUri);
6,安装
Uri installUri = Uri.fromParts("package", "xxx", null);
returnIt = new Intent(Intent.ACTION_PACKAGE_ADDED, installUri);
7,播放
Uri playUri = Uri.parse("file:///sdcard/download/everything.mp3");
returnIt = new Intent(Intent.ACTION_VIEW, playUri);
8,调用发邮件
Uri emailUri = Uri.parse("mailto:shenrenkui@gmail.com");
returnIt = new Intent(Intent.ACTION_SENDTO, emailUri);
9,发邮件
returnIt = new Intent(Intent.ACTION_SEND);
String[] tos = { "shenrenkui@gmail.com" };
String[] ccs = { "shenrenkui@gmail.com" };
returnIt.putExtra(Intent.EXTRA_EMAIL, tos);
returnIt.putExtra(Intent.EXTRA_CC, ccs);
returnIt.putExtra(Intent.EXTRA_TEXT, "body");
returnIt.putExtra(Intent.EXTRA_SUBJECT, "subject");
returnIt.setType("message/rfc882");
Intent.createChooser(returnIt, "Choose Email Client");
10,发短信
Uri smsUri = Uri.parse("tel:100861");
returnIt = new Intent(Intent.ACTION_VIEW, smsUri);
returnIt.putExtra("sms_body", "shenrenkui");
returnIt.setType("vnd.android-dir/mms-sms");
11,直接发邮件
Uri smsToUri = Uri.parse("smsto://100861");
returnIt = new Intent(Intent.ACTION_SENDTO, smsToUri);
returnIt.putExtra("sms_body", "shenrenkui");
12,发彩信
Uri mmsUri = Uri.parse("content://media/external/images/media/23");
returnIt = new Intent(Intent.ACTION_SEND);
returnIt.putExtra("sms_body", "shenrenkui");
returnIt.putExtra(Intent.EXTRA_STREAM, mmsUri);
returnIt.setType("image/png");
用获取到的Intent直接调用startActivity(returnIt)就ok了。
今天就说这么多,有更大需求的可以看源代码。
android正确导入jar包
andriod中如果引入jar包的方式不对就会出现一些奇怪的错误。
工作的时候恰好有一个jar包需要调用,结果用了很长时间才解决出现的bug。刚开始是这样引用的(eclipse):右键工程,Build path,
java build path,选择libraries,在右边的按钮中点击“Add External JARs”,然后选择合适的jar包(大部分人应该会这样做).结果控制台立刻报错:conversion to dalvik format failed with error 1。而且项目上还会出现红叉,虽然项目里并没有错误。clean一下,项目正常,但是bin里的apk文件和dex文件都没了,运行项目出现错误:Can not find **.apk
后来找到原因是因为导入jar包的方式不对,正确的方法如下:
右键工程,
Build path,
java build path,选择libraries
在右边的按钮中点击“Add Library”
选择“User library”,点击“下一步”
点击“User librarys”按钮
在出现的界面中点击“New..”按钮
在弹出的界面中随便起一个名字,点击“确定”
点击“Add jars”按钮选择第三方jar包,点击“确定”完成操作。
这样的话该jar包会被一起打包到apk中,问题也就解决了!
Activity跳转
这个实验描述了Activity之间的另外一种切换方式,通常Activity的切换方式是Activity1通过startActivity切换到Activity2, Activity2再通过startActivity切换到其他的Activity,但是有的时候我们需要启动一个新的Activity获取用户的输入,然后返回到原来的Activity,比如activity是一个通讯录列表,我们通过一个增加按钮打开另一个activity让用户输入新的联系人,输入后再返回通讯录列表。
这个时候,我们可以通过startActivityForResult(Intent, int)方法启动新的Activity,新的Activity通过setResult(int, Intent)方法返回老的Activity,这个时候会触发老的Activity的onActivityResult(int, int, Intent)方法,我们可以在这个方法的实现中处理返回事件。
startActivityForResult(Intent, int),其中int为Request Code,也是onActivityResult的第一个参数,通常一个Activity不仅仅只触发一个获取事件,比如上面提到的通讯录,可能会有一个增加联系人的事件,也可能会有一个修改联系人或给指定联系人增加一个电话的事件,但我们只有一个onActivityResult方法,所以我们需要这么一个Request Code区分是哪个事件的返回,这个值是用户自己定义的,而且完全是用户自己进行管理,很人性化。
setResult(int, Intent),其中的int是Result Code,它表示的是返回的状态,也是onActivityResult的第二个参数。这个参数需要特别注意一下,android为这个值提供了三个默认的常量。我们先看前两个,RESULT_CANCELED和RESULT_OK,这个从字面上很好理解,一个是运行取消,另一个是运行成功返回,当用户按BACK键时,Result Code就是RESULT_CANCELED。但我们看看他们分别对应的值,就会发现奇怪的地方,RESULT_CANCELED=0,RESULT_OK=-1!!!在其他系统中OK通常都是1,而在android,它是-1,这是为什么呢,来让我们看看第三个默认的常量,RESULT_FIRST_USER=1,明白了吧!android把所有大于0的数字都留给了用户自己,多么人性化啊!但是要注意了,如我前面所说,大部分系统都喜欢将大于0作为正确返回,小于0作为错误返回,所以很多人(包括我),喜欢用if(result > 0)表示返回成功,这个在android是不通行的,一定要特别注意!