android使用技巧及踩過的坑
Android學習一些小技巧及踩過的坑:
1、jsoup包沒有,顯示紅色錯誤:
在網上下載jsoup包,放到工程目錄libs下面即可
2、開啟網址提示 net::ERR_CACHE_MISS 錯誤(沒有網路訪問許可權):
在AndroidManifest.xml中新增<uses-permission android:name="android.permission.INTERNET"/> 解決
3、xml檔案註釋:
<!--註釋內容-->
可以ctrl+shift+/ 快速生成
4、activity設定背景顏色:
在AndroidManifest.xml中新增屬性 android:name=".MainActivity" android:theme="@android:style/Theme.Black" //新增該屬性 android:label="@string/app_name" >
5、設定apk圖示:
替換res中的每個解析度的資料夾下的icon檔案,再修改AndroidManifest.xml檔案中的
android:icon="@drawable/ic_launcher"
6、獲取時間差:
long start = System.currentTimeMillis();
Document doc = Jsoup.connect(url).get();
long end = System.currentTimeMillis();
time = end - start;
7、輸出log:
import android.util.Log; protected static final String TAG="MyAndroid";//定義TAG Log.v(TAG,"logcat message")
8、android sdk原始碼:
在csdn下載20M左右壓縮原始碼,加壓放到sdk目錄的source下,
在eclipse中新增路徑(按住ctrl鍵,會提示選擇;手動右擊工程下的android.jar,點選屬性,新增Java
Source Attachment)
親測可用。
9、有時顯示appcompat_v7中報錯,編譯不了,可以忽略錯誤,繼續編譯:(蠻有用的)
Window--Preferences--Android--Lint Error Checking--Ingore All 忽略所有錯誤。
10、建立子執行緒:
// Thread是一個類,必須繼承 public class myThread extends Thread { @Override public void run() { super.run(); // 寫子執行緒中的操作 } }
11、新增apk的系統許可權,在AndroidManifest.xml中加:
android:sharedUserId="android.uid.system"
再編譯出的apk中加簽名(右擊工程--Export...---Export Android Application ...選擇簽名檔案)
12、獲取螢幕點選座標位置:
getevent
檢視 0035 0036(x y)
/dev/input/event4: 0003 0035 000001fd
/dev/input/event4: 0003 0036 0000015b
(509,347)
13、模擬長按事件:
Instrumentation mInst = new Instrumentation();
mInst.sendPointerSync(MotionEvent.obtain(SystemClock.uptimeMillis(),
SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, 140, 410, 0));//140 410是座標 x y 按下
Thread.currentThread().sleep(1000);//等待1s
mInst.sendPointerSync(MotionEvent.obtain(SystemClock.uptimeMillis(), //鬆開
SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, 140, 410, 0));
14、android中的onCreateOptionsMenu()用來建立選單:
15、android圖示:
圖示:把所有圖片都放在drawable-hdpi 資料夾就可以
圖示就是在AndroidManifest.xml 中通過android:icon="@drawable/ic_launcher"來指定的
不同的解析度的圖示需要放在不同的資料夾下(x,xx,xxx),裝置會自動選擇適合自己的解析度的圖示
16、android logcat列印:
android.util.Log
Log.v //verbose 級別最低的
17、id使用:
如果你需要在XML 中引用一個id,就使用@id/id_name 這種語法,而如果你需要在XML 中定義一個id,則要使用@+id/id_name 這種語法
18、activity的名稱:
在AndroidManifest.xml給主活動指定的label 不僅會成為標題欄中的內容,還會成為啟動器(Launcher)中應用程式顯示的名稱。
android:label="@string/app_name"
19、toast顯示:
import android.widget.Toast;
Toast.makeText(context, text, duration) //使用方法原型 LENGTH_SHORT LENGTH_LONG
Toast.makeText(MainActivity.this, "this is a toast!", 3).show();//show 3s
//toast顯示在螢幕中間
Toast t = Toast.makeText(mContext, "再按一次退出", Toast.LENGTH_LONG);//3.5s ,短的2s
t.setGravity(Gravity.CENTER, 0, 0);
注意:在button.setOnClickListener中使用必須 MainActivity.this ;在onCreate中可以直接使用this
因為活動本身就是一個Context物件,如果在Listener中使用的話,傳入的引數就是“new View.OnClickListener(){}”,會出現錯誤。
toast只能顯示3s或5s,其他的需要自己定義
20、銷燬一個activity:
使用finish()
21、Intent使用:
Intent 的用法大致可以分為兩種,顯式Intent 和隱式Intent
顯式Intent:
顯示Intent啟動activity
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);//建立一個Intent
startActivity(intent);//接受一個Intent的引數
隱式Intent:
相比於顯式Intent,隱式Intent 則含蓄了許多,它並不明確指出我們想要啟動哪一個活動,而是指定了一系列更為抽象的action 和category 等資訊,然後交由系統去分析這個Intent,並幫我們找出合適的活動去啟動.
新增:
<intent-filter>
<action android:name="com.example.activitytest.ACTION_START" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
隱式Intent啟動(action和category同時匹配才可以啟動activity)
Intent intent = new Intent("com.example.activitytest.ACTION_START");//將action傳入,因為category設定的DEFAULT,所以不用傳也可以
startActivity(intent);//接受一個Intent的引數
每個Intent 中只能指定一個action,但卻能指定多個category
使用隱式Intent,我們不僅可以啟動自己程式內的活動,還可以啟動其他程式的活動。(啟動瀏覽器開啟網頁)
//Intent.ACTION_VIEW 定義的是“android.intent.action.VIEW” action,VIEW,這是一個Android 系統內建的動作
Intent intent = new Intent("android.intent.action.VIEW");
//呼叫Intent 的setData()方法將這個Uri 物件傳遞進去
intent.setData(Uri.parse("http://www.baidu.com"));
22、Intent向下一個活動傳遞資料:
String data = " Hello, SecondActivity"
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);//顯示Intent
intent.putExtra("extra_data", data);
startActivity(intent);
//取值
Intent intent = getIntent();//通過getIntent() 方法獲取到用於啟動SecondActivity 的Intent
String data = intent.getStringExtra("extra_data");
--------------------
使用intent Bundle傳遞一個字串
Intent intent = new Intent(Moving_Ping_Activity.this, Distribute_Test_HistoryRecord.class);
Bundle bundle = new Bundle();
bundle.putStringArrayList("data", "abc");
intent.putExtras(bundle);
startActivity(intent);
取字串
Intent intent = this.getIntent();
testResultList = intent.getStringArrayListExtra("data");
-------------------
使用intent Bundle傳遞一個物件,物件需要實現Serializable,可序列化
Intent intentCheckResult = new Intent(Moving_Ping_Activity.this, Distribute_Test_Check_Result.class);
Bundle bundleCheckResult = new Bundle();
bundleCheckResult.putSerializable("data", roamTestTotal_Toolbox_Current);
intentCheckResult.putExtras(bundleCheckResult);
startActivity(intentCheckResult);
取物件
Intent intent = this.getIntent();
roamTestTotal_Toolbox = (RoamTestTotal_Toolbox) intent.getSerializableExtra("data");
23、活動的啟動模式一共有四種:
分別是standard、singleTop、singleTask 和singleInstance
修改啟動模式:在AndroidManifest.xml的activity標籤中新增
android:launchMode="singleTop"
standard 模式的活動:系統不會在乎這個活動是否已經在返回棧中存在,每次啟動都會建立該活動的一個新的例項。
singleTop 模式的活動:每當想要再啟動一個FirstActivity 時都會直接使用棧頂的活動;不過當FirstActivity並未處於棧頂位置時,這時再啟動FirstActivity,還是會建立新的例項的
singleTask 模式的活動:每次啟動該活動時系統首先會在返回棧中檢查是否存在該活動的例項,如果發現已經存在則直接使用該例項,並把在這個活動之上的所有活動統統出棧,如果沒有發現就會建立一個新的活動例項。
24、遇到將一個後臺的activity調到前臺的問題:
在當前的activity中使用呼叫action,可以調到前臺但是會提示開啟方式
Intent intent1 = new Intent(“android.intent.action.MAIN”);
startActivity(intent1);
解決的方案:在應用中建立一個finish的activity,finish的activy功能就是回到主頁
調到finish activity:
Intent intent1 = new Intent(MainActivity.this,finish.class);// finished 顯示呼叫activity
startActivity(intent1);// back to home
在finish的activity中回到主頁:
Intent intent = new Intent();
ComponentName comp = new ComponentName("com.example.runcmd","com.example.runcmd.MainActivity");//顯示呼叫
intent.setComponent(comp);
startActivity(intent);
25、UI控制元件
TextView:文字控制元件
控制元件的高度和寬度,Android 中所有的控制元件都具有這兩個屬性,可選值有三種match_parent、fill_parent 和wrap_content,
android:match_parent 表示讓當前控制元件的大小和父佈局的大小一樣。
android:wrap_content 表示讓當前控制元件的大小能夠剛好包含住裡面的內容,也就是由控制元件內容決定當前控制元件的大小。
android:gravity="center" //指定文字對齊方式:,可選值有top、bottom、left、right、center等, 可以用“ | ” 來同時指定多個值
android:textSize="24sp" //文字大小
android:textColor="#00ff00" //文字的顏色 RGB
Button:按鈕
和TextView類似,主要設定事件監聽(setOnClickListener)
EditText:可編輯文字框
android:hint="Type something here" //編輯框中的提示語
不過隨著輸入的內容不斷增多,EditText 會被不斷地拉長。這時由於EditText 的高度指定的是wrap_content,因此它總能包含住裡面的內容,但是當輸入的內容過多時,介面就會變得非常難看。
可以使用android:maxLines 屬性來解決這個問題。
android:maxLines="2" //指定了EditText 的最大行數為兩行,超過2行就會自動向上滾動
android:inputType="phone" //值允許輸入數字
預設是數字鍵盤,但是也可以輸入字母:
et_dialog_confirm_input_address.setInputType(EditorInfo.TYPE_CLASS_NUMBER);
String digists = "0123456789abcdefghigklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.:/";
et_dialog_confirm_input_address.setKeyListener(DigitsKeyListener.getInstance(digists));
有個問題:介面有個edittext控制元件的時候,預設進入就會彈出軟鍵盤。
解決的方法是:在介面上加一個view,強制獲取焦點就可以了
例如:
<View
android:layout_width="0dip"
android:layout_height="0dip"
android:focusableInTouchMode="true"
/>
<EditText
android:id="@+id/et_toolbox_router_evaluate_brand"
android:layout_width="match_parent"
android:layout_height="40dp"
android:gravity="center_vertical"
android:textSize="15sp"
android:textColor="#000000"
android:singleLine="true"
android:hint="路由器型號在路由器銘牌上面"
android:background="@drawable/toolbox_network_delay_edit_style"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginTop="4dp"
android:layout_marginBottom="4dp"
android:paddingLeft="15dp"
android:paddingRight="15dp"
/>
ImageView:圖片控制元件
<ImageView
android:id="@+id/image_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content" //由於圖片的寬和高都是未知的,所以將ImageView 的寬和高都設定為wrap_content
android:src="@drawable/ic_launcher" //給ImageView 指定了一張圖片
/>
imageView.setImageResource(R.drawable.jelly_bean); //通過set方法可以設定不同圖片控制元件
ProgressBar
所有的Android 控制元件都具有這個屬性,可以通過 進行指定,可選值有三種,visible、invisible 和gone
我們還可以通過程式碼來設定控制元件的可見性,使用的是setVisibility()方法,傳入View.VISIBLE、View.INVISIBLE 和View.GONE
常用的屬性:
線性佈局
<LinearLayout
android:layout_width="match_parent" //和父類佈局寬度一樣
android:layout_height="match_parent" //和父類佈局高度一樣
android:orientation="horizontal" //線性水平排列 (vertical:垂直排列)
android:layout_gravity="top" //置頂
水平的位置可以按照權重來分配
android:layout_width="0dp" //規範的寫法
android:layout_weight="1" //權重設定為1
注意LinearLayout水平的時候,就不能設定左右對齊 (android:layout_gravity="right" 是無效的)
horizontal線性佈局中,子元素居中
android:layout_width="match_parent"//一定要設定
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:gravity="center"//只有設定了match,內容居中才生效
相對佈局
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
android:layout_alignParentLeft="true" //在父類佈局的左邊
android:layout_alignParentRight="true" //在父類佈局的右邊
android:layout_centerInParent="true" //在父類佈局的中間
android:layout_alignParentBottom="true" //在父類佈局的下邊
android:layout_alignParentTop="true" //在父類佈局的上邊
android:layout_above="@id/button3" //在button3控制元件的上方
android:layout_toLeftOf="@id/button3" //左邊緣和button3對齊
FrameLayout:比較簡單,這種佈局沒有任何的定位方式,所有的控制元件都會擺放在佈局的左上角
TableLayout
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TableRow>
<TextView
android:layout_height="wrap_content"
android:text="Account:" />
<EditText
android:id="@+id/account"
android:layout_height="wrap_content"
android:hint="Input your account" />
</TableRow>
26、獲取WiFi 連線IP地址和閘道器地址
WifiManager wm = (WifiManager)getSystemService(WIFI_SERVICE);
DhcpInfo di = wm.getDhcpInfo();
String gateway_ip = Formatter.formatIpAddress(di.gateway);
String devices_ip= Formatter.formatIpAddress(di.ipAddress);
27、獲取WiFi名稱和訊號強度
需要新增許可權<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
WifiManager wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
Log.d("Hello:wifiInfo", wifiInfo.toString());
Log.d("Hello:SSID",wifiInfo.getSSID());
28、android 多執行緒
執行緒的基本使用方法,3種寫法:
a、
class MyThread extends Thread {
@Override
public void run() {
// 處理具體的邏輯
}
}
new MyThread().start();//啟動執行緒
b、使用繼承的方式耦合性有點高,更多的時候我們都會選擇使用實現Runnable 介面的方式來定義一個執行緒
class MyThread implements Runnable {
@Override
public void run() {
// 處理具體的邏輯
}
}
MyThread myThread = new MyThread();
new Thread(myThread).start(); //啟動執行緒,傳入一個實現Runnable的物件引數
c、如果你不想專門再定義一個類去實現Runnable 介面,也可以使用匿名類的方式,這種寫法更為常見
new Thread(new Runnable() {
@Override
public void run() {
// 處理具體的邏輯 ,直接更新UI會出現程式crash的問題
}
}).start();
Android 的UI 也是執行緒不安全的。也就是說,如果想要更新應用程式裡的UI元素,則必須在主執行緒中進行,否則就會出現異常。
Android 提供了一套非同步訊息處理機制,完美地解決了在子執行緒中進行UI 操作的問題。
下面是段例項程式碼,測試可以正常執行:(執行的效果是點選按鈕先彈3s toast,第5s在更新UI中的text文字)
public class MainActivity extends Activity{
protected static final String TAG = "Hello:"; //定義一個更新處理的標誌
public static final int UPDATE_TEXT = 1;
private TextView text; //UI的元素
private Button button;
private Handler handler = new Handler() { //定義一個handler
public void handleMessage(Message msg) {
switch (msg.what) { //判斷訊息的型別(1,2,3,4)
case UPDATE_TEXT:
Bundle bundle1 = msg.getData(); //定義一個bundle變數接收message中的bundle資料
String arr1[] = bundle1.getStringArray("arr_return"); //接收bundle中的陣列
// 在這裡可以進行UI操作
text.setText("onClicked");
break;
default:
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text= (TextView) findViewById(R.id.textView1);
button= (Button) findViewById(R.id.button1);
button.setOnClickListener(new Button.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "this is a toast!", 3).show();//show 3s
//新建一個子執行緒
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.currentThread().sleep(5000);
Message message = new Message();
Bundle bundle = new Bundle(); //建立個bundle
bundle.putStringArray("arr_return", arr_return); //將一個arr_return陣列放到bundle中
message.what = UPDATE_TEXT;
message.setData(bundle); //將bundle放到message中傳送
handler.sendMessage(message); // 將Message物件傳送出去
} catch (Exception e) {
Log.v(TAG, e.toString());
}
}
}).start();
//結束子執行緒
}
});//end listener
}
29、計算wifi流量
DecimalFormat fnum = new DecimalFormat("##0.0");//設定格式
long lastTimeStamp = System.currentTimeMillis(); //獲取系統時間
long last_total_rx=TrafficStats.getTotalRxBytes();//獲取總的接收資料
Thread.currentThread().sleep(3000);//設定3s重新整理一次
long curTimeStamp = System.currentTimeMillis();
long cur_total_rx=TrafficStats.getTotalRxBytes();
long delta_total_rx=cur_total_rx-last_total_rx;
float speed = ((float)delta_total_rx * 1000 /(float) (curTimeStamp - lastTimeStamp));// 毫秒轉換
//換算
if (speed > (1024 * 1024)) {
speedStr = fnum.format((speed / ((float) (1024 * 1024))))
+ "M/s";
} else if (speed > 1024) {
speedStr = fnum.format((float) speed / ((float) 1024)) + "K/s";
} else {
speedStr = String.valueOf((int)speed) + "B/s";
}
30、自定義toast
a、先定義一個myToast 的class,在單獨的檔案中
public class toast {
private Toast mToast;
private toast(Context context, CharSequence text, int duration) {
View v = LayoutInflater.from(context).inflate(R.layout.toast, null);
TextView textView = (TextView) v.findViewById(R.id.textView1);
textView.setText(text);
mToast = new Toast(context);
mToast.setDuration(duration);
mToast.setView(v);
}
public static toast makeText(Context context, CharSequence text, int duration) { //設定靜態方法,直接通過類呼叫
return new toast(context, text, duration);//duration 設定0 1 (短2s 長3.5s)只能設定2個值
}
public void show() {
if (mToast != null) {
mToast.show();
}
}
public void setGravity(int gravity, int xOffset, int yOffset) {
if (mToast != null) {
mToast.setGravity(gravity, xOffset, yOffset);
}
}
}
b、在Activity中呼叫
toast.makeText(MainActivity.this,"text",1).show();
31、設定選項卡程式碼:
tabHost=(TabHost)findViewById(android.R.id.tabhost);//獲取tabHost物件
tabHost.setup();//初始化TabHost元件
LayoutInflater inflater=LayoutInflater.from(this);//宣告並例項化一個LayoutInflater物件
//關於LayoutInflater詳細,請看我的另外一篇轉載的總結
inflater.inflate(R.layout.tab1, tabHost.getTabContentView());
inflater.inflate(R.layout.tab2, tabHost.getTabContentView());
inflater.inflate(R.layout.tab3, tabHost.getTabContentView());
tabHost.addTab(tabHost.newTabSpec("tab01")
.setIndicator("標籤頁一")
.setContent(R.id.linearLayout1));//新增第一個標籤頁
tabHost.addTab(tabHost.newTabSpec("tab02")
.setIndicator("標籤頁二")
.setContent(R.id.linearLayout2));//新增第二個標籤頁
tabHost.addTab(tabHost.newTabSpec("tab03")
.setIndicator("標籤頁三")
.setContent(R.id.linearLayout3));//新增第三個標籤頁
View view1 = tabHost.getTabWidget().getChildAt(0);
if (tabHost.getCurrentTab() == 0) {
view1.setBackgroundColor(Color.GREEN);
}
32、單位和尺寸
在佈局檔案中指定寬高的固定大小有以下常用單位可供選擇:px、pt、dp 和sp
px pt是固定的畫素大小
dp sp是相對的大小,可以適配不同的解析度的手機
33、使用ListView控制元件,介面顯示類似表格的list(沒有網格)
a、首先需要定義一個主頁的xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<!-- 標題 -->
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="0dp"
android:layout_weight="4"
android:layout_height="wrap_content"
android:text="WiFi名稱" //設定標題名稱
android:textSize="14dp" //設定字型大小
android:gravity="center" //設定對齊方式
/>
</LinearLayout>
<!-- ListView控制元件 -->
<ListView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/wifi_scan_main"
/>
</LinearLayout>
b、定義一個item的xml(每條記錄的格式)
<?xml version="1.0" encoding="utf-8"?>
<!--item -->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:layout_width="0dp"
android:layout_weight="4"
android:layout_height="wrap_content"
android:id="@+id/wifi_name" //只是定義一個模板,可以先不用賦值
/>
</LinearLayout>
c、主函式的程式碼
onCreate函式裡面的程式碼
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView listView = (ListView) this.findViewById(R.id.listView);//獲取在主xml檔案中定義的listView控制元件
List<HashMap<String, Object>> data = new ArrayList<HashMap<String,Object>>(); //定義一個list,儲存需要顯示的資料
HashMap<String, Object> item = new HashMap<String, Object>(); //定義一個HashMap,儲存每條記錄item的資料
item.put("id", 1); //將資料新增到item記錄中
item.put("wifi_name", "ACP1");
item.put("wifi_mac", "8c:34:00:8c:34:00");
item.put("wifi_level", "-30");
item.put("wifi_freq", "2414");
item.put("wifi_channel", "1");
data.add(item); //將記錄item新增到data中,可以用for新增,這裡演示只新增一條記錄
SimpleAdapter adapter = new SimpleAdapter(this, data, R.layout.item,
new String[]{"wifi_name", "wifi_mac", "wifi_level","wifi_freq","wifi_channel"},
new int[]{R.id.wifi_name, R.id.wifi_mac, R.id.wifi_level,R.id.wifi_freq, R.id.wifi_channel}); //建立一個介面卡,將資料繫結到介面卡中
listView.setAdapter(adapter); //將listView控制元件和介面卡關聯
listView.setOnItemClickListener(new ItemClickListener()); //設定點選事件
} //end oncreate
//獲取點選事件
private final class ItemClickListener implements OnItemClickListener{
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
ListView listView = (ListView) parent;
HashMap<String, Object> data = (HashMap<String, Object>) listView.getItemAtPosition(position);
String personid = data.get("wifi_name").toString();
Toast.makeText(getApplicationContext(), personid, 1).show();
} //重寫onItemClick方法,點選後的處理動作
34、android廣播:動態註冊和靜態註冊:
動態註冊:在程式碼中註冊廣播
a、首先新建一個類,讓它繼承自BroadcastReceiver,並重寫父類的onReceive()方法,方法中寫接收到廣播後的處理。
class NetworkChangeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "network changes",Toast.LENGTH_SHORT).show();//只顯示一條toast
}
}
b、主函式中的程式碼:
public class MainActivity extends Activity {
private IntentFilter intentFilter;
private NetworkChangeReceiver networkChangeReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intentFilter = new IntentFilter();
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE"); //建立了一個IntentFilter 的例項,並給它添加了一個值為android.net.conn.CONNECTIVITY_CHANGE 的action.
networkChangeReceiver = new NetworkChangeReceiver();
registerReceiver(networkChangeReceiver, intentFilter); //registerReceiver()方法進行註冊,將NetworkChangeReceiver 的例項和IntentFilter 的例項都傳了進去.
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(networkChangeReceiver); //動態註冊的廣播接收器一定都要取消註冊才行
}
...(第一步的class新增在此)
}
c、這裡有非常重要的一點需要說明,Android 系統為了保證應用程式的安全性做了規定,如果程式需要訪問一些系統的關鍵性資訊,必須在配置檔案中宣告許可權才可以,否則程式將會直接崩潰
在AndroidManifest.xml新增:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
35、使用SharedPreferences進行資料存錯
寫入
SharedPreferences sp=this.getSharedPreferences("settings", MODE_PRIVATE); //this代表當前的activity,settings是儲存的檔名稱。
Editor et= sp.edit();//獲取SharedPreferences.Editor 物件
et.putString("name", "test");//name是欄位名稱,test儲存的資料
et.commit();//提交資料
資料存在 /data/data/包名/shared_prefs /目錄下,有個settings.xml檔案
讀出
String s = sp.getString("name", "default");//讀取name欄位資料,沒有就賦值為default
36、ContentProvider
讀取手機聯絡人
<uses-permission android:name="android.permission.READ_CONTACTS" />
ContentResolver cr = this.getContentResolver();
Uri uri = Uri.parse("content://com.example.app.provider/table1")
cr.insert(url, values);
例如:
Cursor cursor = null;
try {
// 查詢聯絡人資料
cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null, null, null, null);
while (cursor.moveToNext()) {
// 獲取聯絡人姓名
String displayName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
// 獲取聯絡人手機號
String number = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
contactsList.add(displayName + "\n" + number);
}
建立自己的內容提供器
1. *:表示匹配任意長度的任意字元
2. #:表示匹配任意長度的數字
所以,一個能夠匹配任意表的內容URI 格式就可以寫成:
content://com.example.app.provider/*
而一個能夠匹配table1 表中任意一行資料的內容URI 格式就可以寫成:
content://com.example.app.provider/table1/#
37、使用ScrollView包裹TextView實現滑動
<ScrollView
android:id="@+id/text_sv"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="5"
android:fillViewport="true"
>
<TextView
android:id="@+id/text_moving_ping"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="console"
android:background="#000000"
android:textColor="#ffffff"
/>
</ScrollView>
38、保留2位小數點
DecimalFormat fnum = new DecimalFormat("##0.00");
delay_avg=fnum.format(10.23546);
39、android獲取某個應用的流量資料
a、使用TrafficStats.getUidRxBytes 方法,底層也是呼叫 解析檔案
cat proc/uid_stat/(uid#)/tcp_rcv (uid可以通過程序查詢,先ps檢視程序號pid,再進入/proc/pid/,cat裡面的status狀態就可以查到uid)
cat proc/uid_stat/(uid#)/tcp_snd
b、有的手機沒有proc/uid_stat這個資料夾
/proc/net/xt_qtaguid/stats,查詢這個資料夾
查到的資料類似下面:(10117就是uid,第6是rx資料,第8列是tx資料)
38 wlan0 0x0 10117 0 252397 347 24379 395 252397 347 0 0 0 0 24379 395 0 0 0 0
39 wlan0 0x0 10117 1 18728554 18911 2774867 16508 18728554 18911 0 0 0 0 2468507 16138 0 0 306360 370
經過分析可以知道這2列的tx+rx的資料就是應用的接收和傳送的Bytes資料(手動相加和進入設定流量管理檢視 結果一模一樣,可見android系統設定也是解析這個檔案的)
40、顯示和隱藏一個view
ViewGroup vg = (ViewGroup) findViewById(R.id.viewGroup);//找到父容器
Button bt1 = new Button(this);//new一個button
bt1.setWidth(iv.getWidth());//設定寬高
bt1.setHeight(iv.getHeight());
//bt1.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
bt1.setText("顯示");
vg.addView(bt1);//新增
bt1.setOnClickListener(new OnClickListener() {//設定監聽
@Override
public void onClick(View v) {
v.setVisibility(View.GONE);
iv.setVisibility(View.VISIBLE);
}
});
設定一個圖片大小和margin
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(iv_toolbox_network_delay_result_game.getLayoutParams());
DisplayMetrics dm = getResources().getDisplayMetrics();
layoutParams.width = (int)(dm.density*28);//28dp
layoutParams.height = (int)(dm.density*28);
layoutParams.setMargins((int)(dm.density*3), 0, (int)(dm.density*3), 0);
iv_toolbox_network_delay_result_game.setLayoutParams(layoutParams);
建立webView
ViewGroup vg = (ViewGroup) webView.getParent();
int width = webView.getLayoutParams().width;
int height = webView.getLayoutParams().height;
webView = new WebView(cxt);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(width, height);//設定寬高
params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);//設定對齊方式
webView.setLayoutParams(params);
vg.addView(webView);
41、全域性content
<application
android:name="com.example.runcmd.MyApplication"
42、可編輯的圖片顯示,如果圖片需要覆蓋需要使用Ralaytive的佈局
iv = (ImageView) findViewById(R.id.iv);
Bitmap bt = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory()+"/test.png");
//iv.setImageBitmap(bt);
bt_copy = Bitmap.createBitmap(bt.getWidth(), bt.getHeight(), bt.getConfig());
Paint paint = new Paint();
Canvas canvas = new Canvas(bt_copy);
Matrix mt = new Matrix();
//mt.setRotate(30);
canvas.drawBitmap(bt, mt, paint);
iv.setImageBitmap(bt_copy);
43、mpandroidchart使用:
直接在網上下載lib庫檔案,(mpchartlib.jar 、 nineoldandroids-2.4.0.jar)
繪製簡單的圖表
//定義圖表變數
private LineDataSet lineDataSet;//測試結果曲線
private LineDataSet lineDataSet_avg;//標記線
private ArrayList<LineDataSet> dataSets;//將dataSet_moving_ping dataSet_moving_ping_avg新增進來
private LineData lineData;
private LineChart lineChart;// 繪製折線圖
private ArrayList<String> xVals = new ArrayList<String>();// 橫座標資料
private ArrayList<Entry> entries = new ArrayList<Entry>();// y座標資料,顯示測試值
private ArrayList<Entry> entries_avg = new ArrayList<Entry>();//第二條線 ,y座標資料,顯示平均時延
public void showLineChart() {
lineChart.setVisibility(0);//設定圖表顯示
//entries = new ArrayList<Entry>();// 顯示條目
//xVals = new ArrayList<String>();// 橫座標標
// 新增x軸的資料
// xVals.add("1");
// xVals.add("2");
// xVals.add("3");
// xVals.add("4");
// xVals.add("5");
// xVals.add("6");
// 新增y軸的資料
// entries.add(new Entry((float) 16.9,0));
// entries.add(new Entry((float) 8.19,1));
// entries.add(new Entry((float) 9.19,2));
// entries.add(new Entry((float) 74.6,3));
// entries.add(new Entry((float) 51.6,4));
// entries.add(new Entry((float) 21.0,5));
//新增第二條線的資料
// entries_avg.add(new Entry((float) 20.0,0));
// entries_avg.add(new Entry((float) 20.0,1));
// entries_avg.add(new Entry((float) 20.0,2));
// entries_avg.add(new Entry((float) 20.0,3));
// entries_avg.add(new Entry((float) 20.0,4));
// entries_avg.add(new Entry((float) 20.0,5));
//設定線條格式(測試結果的)
lineDataSet = new LineDataSet(entries, "ping時延動態圖");
lineDataSet.setDrawValues(false);//頂部不顯示數值
lineDataSet.setDrawCubic(true);//設定是否圓滑
lineDataSet.setDrawFilled(true);//填充數值
lineDataSet.setColor(Color.RED);//color
lineDataSet.setLineWidth((float) 0.5);
//dataSet_moving_ping.setColors(ColorTemplate.COLORFUL_COLORS);
//dataSet_moving_ping.setFillColor(0x00ff00);//設定填充顏色
//設定第二條線條的格式
//System.out.println(lineDataSet.getFillColor());
//setting avg mark line
lineDataSet_avg= new LineDataSet(entries_avg, "時延平均值");
lineDataSet_avg.setDrawValues(false);//no value
lineDataSet_avg.setLineWidth((float) 0.8);
lineDataSet_avg.setDrawCircles(false);//no circles
lineDataSet_avg.setColor(Color.GREEN);//color
//將2條折線資料新增到dataSets集合中
dataSets = new ArrayList<LineDataSet>();
dataSets.add(lineDataSet);
dataSets.add(lineDataSet_avg);
//將2個折線的資料,加上x座標生成2條曲線,賦值給lineData
lineData = new LineData(xVals, dataSets);
//將2條曲線顯示在圖表上
lineChart.setData(lineData);
// 設定Y方向上動畫animateY(int time);
lineChart.animateY(2000);//設定動畫時間
// 描述
lineChart.setDescription("時延");//圖表的描述,預設在右下角顯示
YAxis leftAxis = lineChart.getAxisRight();//隱藏右邊的y軸座標
leftAxis.setEnabled(false);
// chart_moving_ping.getXAxis().setPosition(XAxisPosition.BOTTOM);
}
動態更新圖表的資料
case SHOW_TEXT_PING:
Bundle bundle = msg.getData();
String arr[] = bundle.getStringArray("str");
//arr[0]:顯示console,在小視窗顯示的文字
//arr[1]:測試一次的傳回來的x軸的值
//arr[2]:測試一次的傳回來的y軸的值
text_moving_ping.setText(arr[0]);
// 更新圖表資料
if (arr[1] != null && arr[2]!="") {//如果==null 測試結束,不用更新圖表
//packages_revieve++;// 增加接收的包數
if (xVals.size() >= 30) {
xVals.remove(0);
entries.remove(0);
entries_avg.remove(0);
// 新增資料
lineData.addXValue(arr[1]);
if(arr[2].equals("time out")){//如果超時,設定y值為 超時時間*1000
arr[2]=TIME_OUT*1000+"";
}else{
recieve_packages_count++;
recieve_packages_total+=Float.valueOf(arr[2]);
DecimalFormat fnum = new DecimalFormat("##0.00");
//接收包時延總值/接收到的包的個數
delay_avg=fnum.format(recieve_packages_total/recieve_packages_count);
}
lineData.addEntry(new Entry(Float.valueOf(arr[2]), Integer.valueOf(arr[1])), 0);//0代表第一條線
lineData.addEntry(new Entry(Float.valueOf(delay_avg), Integer.valueOf(arr[1])), 1);//1代表第二條線
//因為第二條線是一條直線,所以需要把裡面的資料都設定當前的資料
for (int i =0 ; i < entries_avg.size();i++){
entries_avg.get(i).setXIndex(i);//設定第i個數據的x軸的值(0,1,2,3,...)
entries_avg.get(i).setVal(Float.valueOf(delay_avg));//都設定為delay_avg
}
} else {
//這裡處理當資料量不足30個時,就不刪除資料,直接追加顯示
try {
if(arr[2].equals("time out")){//如果超時,設定y值為 超時時間*1000
arr[2]=TIME_OUT*1000+"";
}else{
recieve_packages_count++;
recieve_packages_total+=Float.valueOf(arr[2]);
DecimalFormat fnum = new DecimalFormat("##0.00");
delay_avg=fnum.format(recieve_packages_total/recieve_packages_count);
}
lineData.addXValue(arr[1]);
lineData.addEntry(new Entry(Float.valueOf(arr[2]), Integer.valueOf(arr[1])), 0);
lineData.addEntry(new Entry(Float.valueOf(delay_avg), Integer.valueOf(arr[1])), 1);
//因為第二條線是一條直線,所以需要把裡面的資料都設定當前的資料
for (int i =0 ; i < entries_avg.size();i++){
entries_avg.get(i).setXIndex(i);
entries_avg.get(i).setVal(Float.valueOf(delay_avg));
}
} catch (Exception e) {
e.printStackTrace();
LogUtils.d(TAG, "add data error!");
}
}
// 重新設定資料的圖表索引(0,1,2,3,...)
float ymax = entries.get(0).getVal();// 獲取y最大值
int i = 0;
for (Entry en : entries) {
en.setXIndex(i++);
// 獲取最大值
try {
if (ymax < en.getVal()) {
ymax = en.getVal();
}
} catch (Exception e) {
e.printStackTrace();
}
}
// 獲取y軸物件
YAxis leftAxis = lineChart.getAxisLeft();
// leftAxis.resetAxisMaxValue();//重新設定y軸
leftAxis.setAxisMaxValue(ymax + ymax / 15);
if (ymax>100){
//lineDataSet.setFillColor(0xF2DDDC);
lineDataSet.setFillColor(0xE6B9B8);
}else{
lineDataSet.setFillColor(-7542017);
}
// 重新整理圖表
try {
lineChart.notifyDataSetChanged();
lineChart.invalidate(); // refresh
} catch (Exception e) {
e.printStackTrace();
LogUtils.e(TAG, "flush chart error!");
}
//有資料就更新
if (packages_send>0){
// 更新介面資料
text_ping_send_count.setText(packages_send + "");
text_ping_receive_count.setText((packages_send-packages_lost) + "");
DecimalFormat fnum = new DecimalFormat("##0.00");
String lostRate = fnum.format(packages_lost * 100.0/ packages_send) + "%";
text_ping_lost_rate.setText(lostRate);
if (lostRate.equals("0.00%")) {
text_ping_lost_rate.setTextColor(Color.GREEN);
} else {
text_ping_lost_rate.setTextColor(Color.RED);
}
text_ping_delay_avg.setText(delay_avg+"ms");
}
}
break;
44、啟動app時報了個 “java.lang.SecurityException: Permission Denial: starting Intent”錯誤
查閱資料發現在xml中呼叫另外一個activity需要定義一個exported的屬性
<activity
android:name="com.example.runcmd.MainActivity"
android:launchMode="singleTask"
android:label="@string/app_name"
android:exported="true"><!-- 設定true允許其他元件呼叫這個activity -->
</activity>
定義之後解決
當時出現一個問題,用eclipse啟動應用直接就進入了主頁,沒有過開機嚮導,單獨在手機上啟動沒問題。是因為在run as裡面還是用之前的配置,
把啟動的launcher action替換為你需要啟動的activity,問題解決
45、在合入開機嚮導的時候出現了一個問題
01-16 10:05:08.927: E/AndroidRuntime(29010): java.lang.IllegalStateException: The application's PagerAdapter changed the adapter's contents without calling PagerAdapter#notifyDataSetChanged! Expected adapter item count: 0, found: 3 Pager id: com.example.runcmd:id/viewpager Pager class: class android.support.v4.view.ViewPager Problematic adapter: class com.example.runcmd.ViewPagerAdapter
經過檢查發現在設定 vpAdapter = new ViewPagerAdapter(views); 之前
並沒有給views賦上值
46、mpandroidchart 設定座標軸沒有小數點
private final ValueFormatter vf_Int = new ValueFormatter() {
@Override
public String getFormattedValue(float arg0) {
return ""+(int)arg0;
}
};
dataSet_wifi_level.setValueFormatter(vf_Int);
47、android json資料解析
程式碼演示:
public void click (View v) throws IOException, JSONException{
//System.out.println("/assets/test.json");
String mac = "8c:34:fd";
InputStream is = getAssets().open("test.json");
BufferedReader buf = new BufferedReader(new InputStreamReader(is));
String str = new String();
StringBuilder stringBuilder = new StringBuilder();
try {
while ((str = buf.readLine()) != null) {
//System.out.println(str);
stringBuilder.append(str);
}
} catch (IOException e) {
e.printStackTrace();
}
is.close();
//System.out.println(stringBuilder.toString());
JSONObject jsonObject = new JSONObject(stringBuilder.toString());
JSONArray infArray_Manufacturers = jsonObject.getJSONArray("Manufacturers");
JSONArray infArray_MACs = jsonObject.getJSONArray("MACs");
//獲取id
String id = "";
for (int i = 0; i < infArray_MACs.length(); i++) {
//System.out.println(infArray_MACs.getJSONObject(i).getString("Oui"));
if (mac.equals(infArray_MACs.getJSONObject(i).getString("Oui"))){
id = infArray_MACs.getJSONObject(i).getString("ManufactureId");
break;
}
}
//獲取路由器型號
String routerName = "";
for (int i =0 ; i < infArray_Manufacturers.length(); i++) {
JSONObject inf_Array = infArray_Manufacturers.getJSONObject(i);
if (id.equals(infArray_Manufacturers.getJSONObject(i).getString("Id"))){
routerName = infArray_Manufacturers.getJSONObject(i).getString("Name");
}
}
System.out.println(routerName);
}
json的資料結構:
{
"Manufacturers": [
{
"Id": "1001",
"Name": "Apple",
"Img": "apple.png"
},
{
"Id": "1002",
"Name": "Xiaomi",
"Img": "xiaomi.png"
},
],
"MACs": [
{
"Oui": "00:00:dd",
"ManufactureId": "1028"
},
{
"Oui": "a0:a8:cd",
"ManufactureId": "1031"
}
]
}
48、checkbox 設定
cb.setClickable(ti.getStatus()); //設定是否可選
cb.setChecked(ti.getStatus()); //設定選中狀態
android:layout_alignBaseline="@id/tv_name"//不能設定居中對齊,可以設定layout_alignBaseline, 效果也是居中
49、自定義標題
標題的xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="48dp"
android:background="@color/title_color" >
<ImageButton
android:id="@+id/ib_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="16dp"
android:src="@drawable/back"
android:background="@color/title_color"
android:onClick="back"/>
<TextView
android:id="@+id/title_text"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="16dp"
android:text="測試選項"
android:textColor="#fff"
android:textSize="18sp" />
<ImageButton
android:id="@+id/ib_setting"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginRight="16dp"
android:src="@drawable/settings"
android:background="@color/title_color"
/>
</LinearLayout>
在main的xml新增
<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"
tools:context=".MainActivity"
android:fitsSystemWindows="true"
android:orientation="vertical">
<include layout="@layout/mycustomtitle" />//新增的
<ListView
android:id="@+id/lv"
android:layout_width="match_parent"
android:layout_height="match_parent"
></ListView>
</LinearLayout>
50、listview中載入不同的佈局:
介面卡中的關鍵程式碼
@Override
public int getViewTypeCount() {
return 2;
}
@Override
public int getItemViewType(int position) {
ti = testItem.get(position);
if(ti.getItemName().equals("基本測試") || ti.getItemName().equals("漫遊測試") ||
ti.getItemName().equals("高階測試(需要Root許可權)")){
return TYPE_TITLE;
}else{
return TYPE_ITEM;
}
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ti = testItem.get(position);
int type = getItemViewType(position);
//System.out.println(type);
ViewHolder1 myHolder1 = null;
ViewHolder2 myHolder2 = null;
if (convertView == null){
switch (type) {
case TYPE_TITLE:
convertView = inflater.inflate(R.layout.item_layout_title, parent, false);
myHolder1 = new ViewHolder1();
myHolder1.tv_title = (TextView) convertView.findViewById(R.id.tv_name);
myHolder1.tv_title.setText(ti.getItemName());
convertView.setTag(myHolder1);
break;
case TYPE_ITEM:
convertView = inflater.inflate(R.layout.item_layout, parent, false);
myHolder2 = new ViewHolder2();
myHolder2.tv_item = (TextView) convertView.findViewById(R.id.tv_name);
myHolder2.tv_item.setText(ti.getItemName());
CheckBox cb = (CheckBox) convertView.findViewById(R.id.cb);
cb.setChecked(ti.getStatus());
cb.setClickable(ti.getEnable());
convertView.setTag(myHolder2);
break;
}
}else{
switch (type) {
case TYPE_TITLE:
myHolder1 = (ViewHolder1) convertView.getTag();
myHolder1.tv_title.setText(ti.getItemName());
break;
case TYPE_ITEM:
myHolder2 = (ViewHolder2) convertView.getTag();
myHolder2.tv_item.setText(ti.getItemName());
CheckBox cb = (CheckBox) convertView.findViewById(R.id.cb);
cb.setClickable(ti.getStatus());
cb.setChecked(ti.getStatus());
break;
default :
break;
}
}
return convertView;
}
51、沉浸式狀態列設定(需要android4.4以上才支援),非常簡單
xml定義
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@android:id/tabhost"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:fitsSystemWindows="true"//這2行
android:clipToPadding="true"> //這2行
程式碼設定:
setContentView(R.layout.activity_main);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);//透明狀態列
}
52、主介面實現滑動切換效果
使用的是tabHost+ViewPager
xml檔案:
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@android:id/tabhost"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TabWidget
android:id="@android:id/tabs"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<!-- android:background="@color/test_option_title_color"-->
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="fill_parent"
android:layout_height="0dp"//注意設定0dp
android:layout_weight="0" >
</FrameLayout>
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
</TabHost>
53、android字型設定
Roboto thin:
android:fontFamily="sans-serif-thin"
Roboto:
android:fontFamily="sans-serif"
android:dashWidth 表示'-'這樣一個橫線的寬度
android:dashGap 表示之間隔開的距離
54、xml裡面設定虛線矩形
<?xml version="1.0" encoding="UTF-8"?>
<!-- 開始測試 按鈕預設時的樣式 -->
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<stroke
android:width="1dp"//邊框線條粗細
android:color="#FFFFFF"//邊框線條顏色
android:dashWidth="2dp"//邊框線條 虛線粗細
android:dashGap="5dp" />//邊框虛線的間隔
<!-- 填充的顏色 -->
<solid android:color="#1294F6" />
<!-- 設定按鈕的四個角為弧形 -->
<!-- android:radius 弧形的半徑 -->
<corners android:radius="30dip" />
<!-- 漸變效果 -->
<gradient
android:startColor="#FFFFFF"
android:centerColor="#EEF7FD"
android:endColor="#9BD4FE"
android:angle="270"
/>
<!-- padding:Button裡面的文字與Button邊界的間隔 -->
<padding
android:left="20dp"
android:top="10dp"
android:right="20dp"
android:bottom="10dp"
/>
</shape>
55、給佈局設定偵聽
例如給LinearLayout 整個佈局設定一個偵聽,佈局上面還有其他的控制元件,此時點選其他的控制元件就不會響應偵聽的事件
因為控制元件消耗了事件,所以沒有反應
例如佈局中有個按鈕button , 我們只有把按鈕的 屬性設定下 android:clickable="false" 就行了。
56、關於在自定義listView中(有button checkbox 等)不響應setOnItemClickListener 偵聽的辦法
在自定義的layout的xml檔案最外層新增 android:descendantFocusability="blocksDescendants"
例如:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="56dp"
android:orientation="horizontal"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:descendantFocusability="blocksDescendants">
57、ImageView新增切圖,layout根據切圖縮放
android:scaleType="centerInside"
要注意一點,Drawable資料夾裡面的圖片命名是不能大寫的
<ImageView
android:id="@+id/ib_setting"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginLeft="16dp"
android:layout_gravity="center"
android:gravity="center"
android:src="@drawable/test_option_settings"
android:scaleType="centerInside"
android:clickable="false"
/>
58、解決自定義的checkbox,背景圖片太大的問題
可以設定checkbox的固定寬高
android:button="@null"
android:background="@drawable/test_option_checkbox"
主要是設定android:button="@null"
59、資料庫一定不要使用下劃線做資料庫名稱,不然會報錯
60、static變數設定的重要性
每次在子執行緒中啟動,設定一個漫遊切換體驗的平均時延就會有問題,主執行緒和子執行緒列印的資料不一致,定義為static解決問題。
61、dialog中獲取螢幕的寬高
DisplayMetrics dm = context.getResources().getDisplayMetrics();
int width = dm.widthPixels;
int height = dm.heightPixels;
dialog.getWindow().setLayout(width - width/20, height/3);//設定dialog的寬高
dialog.getWindow().setDimAmount(0f);//背景不透明
// 正常獲取 Android獲得螢幕的寬和高
WindowManager windowManager = getWindowManager();
Display display = windowManager.getDefaultDisplay();
int screenWidth = display.getWidth();
int screenHeight = display.getHeight();
//設定dialog的位置
Window dialogWindow = dialog.getWindow();
WindowManager.LayoutParams lp = dialogWindow.getAttributes();
dialogWindow.setGravity(Gravity.LEFT | Gravity.TOP);
lp.x = location[0];
lp.y = location[1];
dialogWindow.setAttributes(lp);
62、layout顯示為虛線,介面不顯示虛線的問題
<View
android:layerType="software"
android:layout_width="wrap_content"
android:layout_height="2dp"
android:background="@drawable/line_dashed"
android:layout_centerInParent="true"
/>
注意一定要加 android:layerType="software" 這個屬性
63、android彈框動畫效果
在style.xml中新增
<style name="animations_dialog_style" parent="android:Animation">
<item name="@android:windowEnterAnimation">@anim/animations_dialog_enter</item>
<item name="@android:windowExitAnimation">@anim/animations_dialog_exit</item>
</style>
在res資料夾下建立一個anim資料夾,裡面放2個動畫的xml
animations_dialog_enter.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<translate
android:duration="800"
android:fromYDelta="50%p" />
</set>nimations_dialog_enter.xml
animations_dialog_exit.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<translate
android:duration="800"
android:fromYDelta="50%p" />
</set>
程式碼:
Window dialogWindow = dialog.getWindow();
dialogWindow.setGravity(Gravity.BOTTOM);
dialogWindow.setWindowAnimations(R.style.animations_dialog_style);
64、textView中的行間距
android:lineSpacingExtra="6dp"
65、獲取控制元件在螢幕中的位置
int[] location = new int[2];
button_test_start.getLocationOnScreen(location);
int x = location[0];
int y = location[1];
獲取控制元件的寬高
ll_toolbox_distribute_avg_network_speed.getHeight();
ll_toolbox_distribute_avg_network_speed.getWidth();
計算系統狀態列高度
Rect rect = new Rect();
getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
int top = rect.top;
66、獲取使用者的pid和uid
//pid
int pid = android.os.Process.myPid();
int uid = android.os.Process.myUid();
//uid
private int getUid(){
PackageManager packageManager=getApplicationContext().getPackageManager();
List<ApplicationInfo> appList=packageManager.getInstalledApplications(0);
int uid = 0;
for (ApplicationInfo app : appList) {
if (app.packageName.equals(getApplicationContext().getPackageName())){
uid = app.uid;
}
}
System.out.println("uid:"+uid);
return uid;
}
67、去呼叫一個未啟動的activity裡面的一個public static變數,導致裡面的handle接收到訊息介面不重新整理
背景:想通過一個activity的子執行緒獲取排名,獲取到後傳送訊息給即將跳轉的activity顯示
之前的做法是在目標activity裡面定義一個public static的標誌位,當前的activity迴圈判斷,如果頁面啟動就傳送訊息,發現目標activity接收到訊息一直不重新整理介面
hanlde失效了,原因可能是當前去呼叫目標activity的時候就已經把那個類初始化了。
解決的方法:
在本類中定義一個標識位,目標activity啟動後就改變當前activity的標識位就行,當前activit的子執行緒就一直讀取本類的標識位就行。
68、使用onActivityResult接收到的Intent永遠是null ,返回碼是0的問題
是因為在onDestory中呼叫
應該重寫onBackPressed方法,
@Override
public void onBackPressed() {
setResultAndFinish();
super.onBackPressed();//注意這個必須在後面呼叫,否則還是會出現返回值為null的問題
}
private void setResultAndFinish() {
Intent mIntent = new Intent();
mIntent.putExtra("data", testRecordTotal);
setResult(resultCode, mIntent);
finish();
}
69、動畫勻速轉動的程式碼:
//播放動畫
RotateAnimation animation;
animation = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
animation.setDuration(1000);
animation.setRepeatCount(Integer.MAX_VALUE);
animation.setRepeatMode(Animation.RESTART);
animation.setFillAfter(true);
LinearInterpolator lip = new LinearInterpolator();
animation.setInterpolator(lip);//關鍵設定這個屬性
iv_dialog_count_down_second.startAnimation(animation);
70、http請求程式碼:
new Thread() {
public void run() {
DefaultHttpClient client = new DefaultHttpClient();
try {
String uriAPI;// 宣告網址字串
if(CONTANT.VERSION.equals("USER")){
uriAPI = CONTANT.USER.INSERT_TEST_RECORD;
}else{
uriAPI = CONTANT.DEBUG.INSERT_TEST_RECORD;
}
HttpPost httpRequest = new HttpPost(uriAPI); // 建立HTTP
// POST聯機
List<NameValuePair> params = new ArrayList<NameValuePair>(); // Post運作傳送變數必須用NameValuePair[]陣列儲存
params.add(new BasicNameValuePair("testRecord",JsonUtils.toJson(changeToServerFormat())));
System.out.println("testRecord" + JsonUtils.toJson(changeToServerFormat()));
httpRequest.setEntity(new UrlEncodedFormEntity(params,HTTP.UTF_8)); // 發出http請求
HttpResponse httpResponse = client.execute(httpRequest); // 取得http響應
if (httpResponse.getStatusLine().getStatusCode() == 200) {
String strResult = EntityUtils.toString(httpResponse.getEntity()); // 獲取字串
System.out.println("strResult" + strResult);
//上傳成功修改本地資料庫的標記位
ContentValues cv = new ContentValues();
cv.put("upload_mark", "1");
String testTime = testRecordTotal.getUserinfo().getTestTime();
DatabaseOperator dbo = new DatabaseOperator(new MyOpenHelperTestRecord(Check.this));
dbo.update(CONTANT.sheet_test_record, cv, "retain_field_1=?", new String[]{testTime});
}
} catch (Exception e) {
System.out.println("資料上傳失敗");
System.out.println(e.toString());
e.printStackTrace();
}finally{
client.getConnectionManager().shutdown();
}
};
}.start();
71、程式碼動態新增View的方法:
private void addAddressView(String [] strAddress){
DisplayMetrics dm = getResources().getDisplayMetrics();
NetworkDelayAddress networkDelayAddress = new NetworkDelayAddress();
networkDelayAddress.setNam