編輯:關於Android編程
最近做了一個Android開發小demo,主要功能是在手機的ActionBar中的搜索欄,根據用戶輸入的名字從後台(java+Tomcat)數據庫中取出該名字對應的一系列信息,然後通過json形式傳到前台,並用表格的形式顯示到前台。
跟大家分享一下,並且列出幾個比較坑的點。但是只是列出了java文件和layout中的xml文件,drawable以及bean類沒有列
涉及的知識點主要有:
前台主要涉及兩個Activity,一個是SearchActivity,一個是SearchResultActivity。
SearchActivity,它的主要功能是在ActionBar中的搜索欄可以接收用戶輸入的數據,並且可以動態提示,點擊回車後,會將數據傳到SearchResultActivity。
話不多說,上代碼:
package com.wzy.search.aty;
import java.util.ArrayList;
import com.wzy.search.R;
import android.annotation.SuppressLint;
import android.app.ActionBar;
import android.app.Activity;
import android.app.SearchManager;
import android.app.SearchableInfo;
import android.content.ComponentName;
import android.content.Context;
import android.graphics.Color;
import android.opengl.Visibility;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.inputmethod.EditorInfo;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.SearchView;
import android.widget.SearchView.OnCloseListener;
import android.widget.SearchView.OnQueryTextListener;
import android.widget.TextView;
/**
* 該Activity執行前台搜索功能,具備自動提示
* @author wzy
* @version V1.0
*/
@SuppressLint("DefaultLocale")
public class SearchActivity extends Activity {
SearchView searchView = null;
EditText searchText = null;
private ListView searchListView = null;
private ArrayAdapter searchAdapter = null;
private String[] searchNames = null;
private ArrayList searchList = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.search_person);
ActionBar actionBar = getActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true); // 給左上角圖標左邊加上一個返回圖標
}
searchListView = (ListView) findViewById(R.id.searchListView);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// 自定義菜單,設置搜索欄
getMenuInflater().inflate(R.menu.search_menu, menu);
//獲取SearchView對象
searchView = (SearchView) menu.findItem(R.id.search).getActionView();
if (searchView == null) {
Log.e("SearchView", "Fail to get Search");
return true;
}
// 獲得searchview文本對象
int search_text_id = searchView.getContext().getResources().getIdentifier("android:id/search_src_text", null, null);
searchText = (EditText) searchView.findViewById(search_text_id);
searchView.setOnSearchClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
searchListView.setVisibility(View.VISIBLE);
}
});
searchView.setOnCloseListener(new OnCloseListener() {
@Override
public boolean onClose() {
// TODO Auto-generated method stub
searchListView.setVisibility(View.INVISIBLE);
return false;
}
});
searchNames = new String[]{"abc","bcd","cde","def","efg","wxy","xyz"};
searchAdapter = new ArrayAdapter(getApplicationContext(), android.R.layout.simple_expandable_list_item_1,searchNames);
searchListView.setAdapter(searchAdapter);
searchListView.setTextFilterEnabled(true);
searchListView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView arg0, View arg1, int arg2, long arg3) {
// TODO Auto-generated method stub
searchText.setText(((TextView)arg1).getText().toString());
searchText.setSelection(((TextView)arg1).getText().toString().length());
Log.e("string", ((TextView)arg1).getText().toString());
}
});
searchView.setOnQueryTextListener(new OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
// TODO Auto-generated method stub
if (newText.length() != 0) {
setFilterText(newText);
} else {
clearTextFilter();
}
return false;
}
});
//設置搜索圖標。設置為false的時候icon固定於文字左邊,設置為true在文字右邊,隨文字動
searchView.setIconified(true);
//獲取SearchView文本對象
searchText.setTextColor(Color.WHITE);
//核心代碼
//獲取搜索服務管理器
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
// searchable activity的component name,由此系統可通過intent進行喚起
ComponentName componentName = new ComponentName(this, SearchResultActvity.class);
// 通過搜索管理器,從searchable activity中獲取相關搜索信息,就是searchable的xml設置。如果返回null,表示該activity不存在,或者不是searchable
SearchableInfo searchableInfo = searchManager.getSearchableInfo(componentName);
if (searchableInfo == null) {
Log.e("SearchableInfo", "Fail to get SearchableInfo");
}
// 將searchable activity的搜索信息與search view關聯
searchView.setSearchableInfo(searchableInfo);
return true;
}
@SuppressLint("DefaultLocale")
public void setFilterText(String filterText) {
ArrayList list = new ArrayList();
String[] tempStr;
for (int i = 0; i < searchNames.length; i++) {
String searchNameIgnoreCase = searchNames[i].toLowerCase();
String filterTextIgnoreCase = filterText.toLowerCase();
if (searchNameIgnoreCase.contains(filterTextIgnoreCase)) {
list.add(searchNames[i]);
}
}
if (list.size() >= 0) {
tempStr = new String[list.size()];
int j = 0;
for (String str : list) {
tempStr[j++] = str;
}
searchAdapter = new ArrayAdapter(getApplicationContext(),
android.R.layout.simple_expandable_list_item_1, tempStr);
searchListView.setAdapter(searchAdapter);
}
}
public void clearTextFilter() {
searchAdapter = new ArrayAdapter(getApplicationContext(),
android.R.layout.simple_expandable_list_item_1, searchNames);
searchListView.setAdapter(searchAdapter);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// TODO Auto-generated method stub
switch (item.getItemId()) {
case android.R.id.home:
overridePendingTransition(R.anim.tran_return_in, R.anim.tran_return_out);
finish();
break;
case R.id.search:
break;
default:
break;
}
return super.onOptionsItemSelected(item);
}
long lastClickTime = 0;
@Override
public void onBackPressed() {
overridePendingTransition(R.anim.tran_return_in, R.anim.tran_return_out);
finish();
}
}
search_person.xml如下:
上面的代碼就把數據傳到SearchResultActivity了。下面看該類代碼:
package com.wzy.search.aty;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.wzy.search.R;
import com.wzy.search.bean.Person;
import com.wzy.search.util.HttpUtil;
import com.wzy.search.util.Material;
import com.wzy.search.util.SerializableMap;
import com.wzy.search.StringUtil;
import com.wzy.bean.PersonData;
import com.wzy.bean.StringBean;
import android.app.ActionBar;
import android.app.Activity;
import android.app.SearchManager;
import android.content.Intent;
import android.os.Bundle;
import android.os.DropBoxManager.Entry;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;
/**
* 該類返回搜索的結果,並以表格的形式顯示
* @author wzy
*
*/
public class SearchResultActvity extends Activity{
private List datas;
private ListView listView = null;
private List
result_names_new.xml如下所示:
<framelayout android:id="@+id/id_fl" android:layout_height="20dip" android:layout_margintop="10dip" android:layout_width="match_parent">
</framelayout>
nameitems如下所示:
從xml可以看出來,表格是自己畫的,先是畫出表頭,然後再用ListView,再將list化成和表頭一樣的框,就成了表格了。只不過需要調整一下間距,否則比較難看。
這裡還有幾個點:
一是調用HttpUtil方法時,必須使用線程,否則會報錯;
二是對於listview的操作,比如初始化和setAdapter,必須放在onCreate方法裡,否則會出現問題。
本例使用HttpUrlConnection進行通信,在com.wzy.util包下新建HttpUtil類,主要用於發送前台傳到後台的參數,並且接受後台傳過來的數據,並且把數據包裝成PersonData的形式。
package com.wzy.util;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
i mport java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.siemens.bean.MaterialData;
import android.util.Log;
/**
* 該類用於與後台進行通信,通過json方式,將結果以PersonData形式進行封裝
* @author wzy
*
*/
public class HttpUtil {
private final static String PATH = "http://127.0.0.1:8088/PersonServlet/QueryController";
private static URL url;
private static List datas = null;
public HttpUtil() {
}
@SuppressWarnings("deprecation")
public static List sendHttpRequst(Map params, String encode) throws Exception {
datas = new ArrayList();
// 對查詢的參數進行封裝
StringBuffer buffer = new StringBuffer();
if (params != null && !params.isEmpty()) {
for (Map.Entry entry : params.entrySet()) {
buffer.append(entry.getKey()).append("=").append(URLEncoder.encode(entry.getValue())).append("&");
}
buffer.deleteCharAt(buffer.length() - 1);
}
// 打印傳遞的參數
Log.e("data", buffer.toString());
try {
url = new URL(PATH);
// System.out.println("url:" + url.toString());
if (url != null) {
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
Log.e("TEST", urlConnection+"");
if (urlConnection == null) {
System.out.println("urlConnection: " + urlConnection);
return null;
}
urlConnection.setConnectTimeout(3000);
urlConnection.setRequestMethod("POST"); // 設置請求方式
urlConnection.setDoInput(true); // 表示從服務器獲取數據
urlConnection.setDoOutput(true); // 表示向服務器發送數據
byte[] data = buffer.toString().getBytes();
// System.out.println("buffer:" + data.toString());
// 設置請求體的是文本類型
urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
urlConnection.setRequestProperty("Content-Length", String.valueOf(data.length));
// 獲得輸出流
OutputStream outputStream = urlConnection.getOutputStream();
outputStream.write(data);
outputStream.close();
// 獲得服務器的響應結果和狀態碼
int responseCode = urlConnection.getResponseCode();
Log.e("RESCODE", responseCode + "");
// 服務器響應成功
if (responseCode == 200) {
// 獲取查詢結果
InputStream in = urlConnection.getInputStream();
// 結果為JSON格式,對JSON進行解析
datas = parseJSON(in);
}
}
return datas;
} catch (IOException e) {
e.printStackTrace();
Log.e("my error", "這裡肯定發生了錯誤");
}
return null;
}
private static List parseJSON(InputStream in) throws Exception {
String str = read(in);
Gson gson = new Gson();
datas = gson.fromJson(str, new TypeToken>(){}.getType());
return datas;
}
private static String read(InputStream in) throws IOException {
byte[] data;
ByteArrayOutputStream bout = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int len = 0;
while ((len = in.read(buf)) != -1) {
bout.write(buf, 0, len);
}
data = bout.toByteArray();
return new String(data, "utf-8");
}
}
這裡就沒什麼好說的了,需要注意的是,這裡用Gson進行的數據解析,講json轉化為PeronData,傳給SearchResultActivity
本例中,後台不需要view層,所以只需要以下包
-com.wzy.bean,封裝數據庫的表;
-com.wzy.service,對某個表進行操作;
-com.wzy.controller,控制某個service進行操作;
-com.wzy.util,有SqlHelper類,進行數據庫的增刪改查操作,涉及數據庫的都可以用這個類,也可以叫com.wzy.dao包;
本例中,用QueryController接受前台傳過來的數據,並用PersonService進行查詢操作,返回PersonData數據
代碼如下:
package com.wzy.controller;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.google.gson.Gson;
import com.wzy.bean.PersonData;
import com.wzy.bean.StringBean;
import com.wzy.service.PersonService;
/**
* 該類用於控制查詢相關事務,不包括單表查詢。即需要查詢多個表,通過該controller,調用相關service進行處理
* @author wzy
*
*/
public class QueryController extends HttpServlet {
private static final long serialVersionUID = 1L;
private String materialName = "";
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doPost(request, response);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
request.setCharacterEncoding("utf-8");
response.setContentType("text/json;charset=utf-8");
response.setContentType("utf-8");
OutputStream out = response.getOutputStream();
ArrayList datas = null; //定義需要返回的數據
if (request != null) {
name = request.getParameter(StringBean.NAME);
// 調用PersonService的方法,根據名字得到需要返回的ArrayList
PersonService personService = new PersonService();
datas = personService.getPersonByName(name);
// 測試代碼,輸出查詢到的數據
for (PersonData data : datas) {
System.out.println(data);
}
// 通過gson返回數據
Gson gson = new Gson();
out.write(gson.toJson(datas).getBytes("utf-8"));
out.flush();
out.close();
}
}
}
需要注意的是,要用json的話,需要導包,這個可以百度一下,有一個主要包,還有幾個支持包,都要導
package com.wzy.service;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import com.google.gson.Gson;
import com.wzy.bean.PersonData;
import com.wzy.bean.Person_name;
import com.wzy.utils.DBString;
import com.wzy.utils.SqlHelper;
/**
* 對涉及多表的業務進行操作
* @author wzy
*
*/
public class PersonService {
private String sql = "";
private String[] params = null;
private PersonData data = null;
private ArrayList datas = null;
/**
* 根據name查找,並返回封裝name,age,address的數據結構
* @param name
* @return 封裝name,age,address的對象的ArrayList
*/
public ArrayList getPersonByName (String name) {
params = new String[]{"%" + name + "%"};
sql = "select "+Person_name.NAME+","+Person_name.AGE+","
+Person_name.ADDRESS+" from "+DBString.TABLE_Person_NAME
+" where "+Person_name.PERSON_NAME+" like ?";
System.out.println("sql test:" + sql);
ResultSet rs = SqlHelper.executeQuery(sql,params);
datas = new ArrayList<>();
try {
while (rs.next()) {
data = new PersonData();
data.setPersonAge(rs.getString(Person_name.PERSON_AGE));
data.setPersonName(rs.getString(Person_name.PERSON_NAME));
data.setPersonAddress(rs.getString(Person_name.ADDRESS));
datas.add(data);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
SqlHelper.close(SqlHelper.getConn(), SqlHelper.getStat(), rs);
}
return datas;
}
}
這裡又有一個坑:
當preparestatement語句中,有?又有%時,需要把%放在params定義中,而不能夠放在?旁邊,這個錯誤檢查了半天,始終找不出來,最後還是慢慢試出來的。
另外,上面代碼提到的Person_name是一個表,裡面僅僅存放了所有人的名字,方便用於查找用的。
0x00為了避免我們的so文件被動態分析,我們通常在so中加入一些反調試代碼,常見的Android native反調試方法有以下幾種。1、直接調用ptrace(PTRAC
樂視pro3支持NFC嗎? 根據樂視官方介紹,樂視pro3支持全功能NFC,支持讀卡、寫卡、卡模擬及P2P模式等豐富應用。用戶使用樂視pro3可以完成公交
最近公司的軟件需要改國際版,需要Facebook和Twitter的登錄和分享。本人先用Umeng的第三方社會化分享實現了該功能,但是後來一想問題來了,經過查證。Umeng
要說攔截Android系統來電,就不得不說起在低版本的時候Android提供給開發者使用的一個方法:endCall(),但由於谷歌後來考慮到對於一部手機來說,最重要的功能