Android——使用者登陸及使用者名稱和密碼的儲存
目錄
一、Android下的Junit測試
在實際開發中,開發android軟體的過程需要不斷地進行測試。而使用Junit測試框架,側是正規Android開發的必用技術,在Junit中可以得到元件,可以模擬傳送事件和檢測程式處理的正確性。
首先建立一個新的Android專案,這裡我命名為:junit,然後編寫AndroidManifest.xml檔案,在裡面新增uses-library和instrumentation兩個屬性,程式碼如下:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="lq.wangzhen.junit" android:versionCode="1" android:versionName="1.0" > <instrumentation android:name="android.test.InstrumentationTestRunner" android:label="Tests for My App" android:targetPackage="lq.wangzhen.junit" /> <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="8" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <uses-library android:name="android.test.runner" /> <activity android:name="lq.wangzhen.junit.DemoActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
其中在instrumentation中配置的targetPackage為測試類所在的包,我這裡的包名為:lq.wangzhen.junit
編寫完以上的程式碼以後,則可以在lq.wangzhen.junit包中定義一個類,這個類中包含一個Add方法,然後我們進行此方法的測試工作。程式碼如下:
Services.java
package lq.wangzhen.junit; public class Service { /** * 提供一個方法,可以接收兩個整型資料 * @param x * @param y * @return */ public static int add(int x,int y){ return x+y; } }
下面編寫測試類,此類命名為:TestAddService.java,此類必須要整合AndroidTestCase才能夠作為測試類進行使用,程式碼如下:
package lq.wangzhen.junit; import junit.framework.Assert; import android.test.AndroidTestCase; public class TestAddService extends AndroidTestCase { public void testAdd(){ int result = Service.add(3, 5); Assert.assertEquals(8, result); } }
以上就是一個簡單的Android測試過程
二、登陸記錄密碼介面設計
完成完以上的測試功能後,下面我們來完成一個簡單的使用者登陸功能,現在要求使用者輸入使用者名稱和密碼,並選擇是否儲存使用者名稱和密碼,如果儲存使用者名稱和密碼的話,我們要在ROM進行儲存,然後在使用者下次開啟此軟體時會自動的從檔案中提取出對應的使用者名稱和密碼,填入到登陸框中,在本節中就先對介面進行一下設計,介面設計的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"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/username" />
<EditText
android:id="@+id/et_username"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:hint="@string/username"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/password" />
<EditText
android:id="@+id/et_password"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:hint="@string/password"
android:inputType="textPassword"
/>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/login"
android:layout_alignParentLeft="true"/>
<CheckBox
android:id="@+id/cb_remember"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/remember_password"
android:layout_alignParentRight="true"/>
</RelativeLayout>
</LinearLayout>
下面開始編寫MainActivity.java檔案,程式碼如下:
package lq.wangzhen.file;
import android.app.Activity;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends Activity implements OnClickListener {
private static final String TAG = "MainActivity";
private EditText et_username;
private EditText et_password;
private Button button;
private CheckBox cb_remember;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_username = (EditText) this.findViewById(R.id.et_username);
et_password = (EditText) this.findViewById(R.id.et_password);
button = (Button) this.findViewById(R.id.button);
cb_remember = (CheckBox) this.findViewById(R.id.cb_remember);
button.setOnClickListener(this);
}
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()) {
case R.id.button:
String username = et_username.getText().toString().trim();
String password = et_password.getText().toString().trim();
if(TextUtils.isEmpty(username) || TextUtils.isEmpty(password)){
Toast.makeText(this, R.string.error, Toast.LENGTH_SHORT).show();
return;
}
if(cb_remember.isChecked()){
Log.i(TAG, "儲存使用者名稱和密碼,"+username+":"+password);
}else{
Log.i(TAG, "沒有儲存使用者名稱和密碼,"+username+":"+password);
}
break;
}
}
}
以上程式所使用的strings.xml檔案的內容如下:
1 <?xml version="1.0" encoding="utf-8"?> 2 <resources> 3 4 <string name="app_name">file</string> 5 <string name="hello_world">Hello world!</string> 6 <string name="menu_settings">Settings</string> 7 8 <string name="username">使用者名稱</string> 9 <string name="password">密碼</string> 10 <string name="login">登陸</string> 11 <string name="remember_password">記住密碼</string> 12 <string name="error">使用者名稱和密碼不能為空</string> 13 14 </resources>
三、採用rom儲存使用者資料
下面對以上的程式進行修改,加入可以將使用者名稱和程式碼儲存到檔案中的功能,首先新建立一個Service檔案,用來操作檔案的儲存,程式碼如下:
package lq.wangzhen.service;
import java.io.FileOutputStream;
import android.content.Context;
public class FileService {
private Context context;
public FileService(Context context){
this.context = context;
}
/**
* 把使用者名稱和密碼儲存到手機ROM
* @param password 輸入要儲存的密碼
* @param username 要儲存的使用者名稱
* @param filename 儲存到哪個檔案
* @return
*/
public boolean saveToRom(String password,String username,String filename) throws Exception{
//以私有的方式開啟一個檔案
FileOutputStream fos = context.openFileOutput(filename, Context.MODE_PRIVATE);
String result = username+":"+password;
fos.write(result.getBytes());
fos.flush();
fos.close();
return true;
}
}
修改MainActivity.java檔案,程式碼如下:
package lq.wangzhen.file;
import lq.wangzhen.service.FileService;
import android.app.Activity;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends Activity implements OnClickListener {
private static final String TAG = "MainActivity";
private EditText et_username;
private EditText et_password;
private Button button;
private CheckBox cb_remember;
private FileService fileService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_username = (EditText) this.findViewById(R.id.et_username);
et_password = (EditText) this.findViewById(R.id.et_password);
button = (Button) this.findViewById(R.id.button);
cb_remember = (CheckBox) this.findViewById(R.id.cb_remember);
button.setOnClickListener(this);
//初始化檔案服務
fileService = new FileService(this);
}
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()) {
case R.id.button:
String username = et_username.getText().toString().trim();
String password = et_password.getText().toString().trim();
if(TextUtils.isEmpty(username) || TextUtils.isEmpty(password)){
Toast.makeText(this, R.string.error, Toast.LENGTH_SHORT).show();
return;
}
if(cb_remember.isChecked()){
Log.i(TAG, "儲存使用者名稱和密碼,"+username+":"+password);
try {
boolean result = fileService.saveToRom(password, username, "private.txt");
if(result){
Toast.makeText(getApplicationContext(), R.string.success, Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(getApplicationContext(), R.string.failed, Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
Toast.makeText(getApplicationContext(), R.string.failed, Toast.LENGTH_SHORT).show();
}
}
break;
}
}
}
在strings.xml檔案中新增以下的內容:
1 <string name="success">儲存成功</string> 2 <string name="failed">儲存失敗</string>
執行程式,即可儲存成功,儲存的檔案預設的儲存在data/data/lq.wangzhen.file/files資料夾中,其中lq.wangzhen.file表示Activity所在的包名。下面在此程式的基礎上加入可以從檔案中讀取使用者名稱和密碼的功能,首先在FileService.java檔案中新增以下的一個方法,用來從ROM中讀取檔案內容。
public Map<String,String> getUserInfo(String filename) throws Exception{
File file = new File("data/data/lq.wangzhen.file/files/"+filename);
FileInputStream fis = new FileInputStream(file);
//以上的兩句程式碼也可以通過以下的程式碼實現:
//FileInputStream fis = context.openFileInput(filename);
byte[] data = StreamTools.getBytes(fis);
String result = new String(data);
String results[] = result.split(":");
Map<String,String> map = new HashMap<String,String>();
map.put("username", results[0]);
map.put("password", results[1]);
return map;
}
在此方法中呼叫了一個StreamTools.getBytes()方法,此方法是專門用來將一個InputStream流轉換為byte陣列返回的,所以我們編寫此方法為:
package lq.wangzhen.util;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
public class StreamTools {
/**
* 把InputStream中的內容讀出來,放到一個byte[]中返回
* @param is
* @return
* @throws Exception
*/
public static byte[] getBytes(InputStream is) throws Exception{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while((len=is.read(buffer)) != -1){
baos.write(buffer, 0, len);
}
baos.flush();
baos.close();
return baos.toByteArray();
}
}
最後再次修改MainActivity.java檔案,呼叫編寫的getUserInfo方法:
package lq.wangzhen.file;
import java.util.Map;
import lq.wangzhen.service.FileService;
import android.app.Activity;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends Activity implements OnClickListener {
private static final String TAG = "MainActivity";
private EditText et_username;
private EditText et_password;
private Button button;
private CheckBox cb_remember;
private FileService fileService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_username = (EditText) this.findViewById(R.id.et_username);
et_password = (EditText) this.findViewById(R.id.et_password);
button = (Button) this.findViewById(R.id.button);
cb_remember = (CheckBox) this.findViewById(R.id.cb_remember);
button.setOnClickListener(this);
//初始化檔案服務
fileService = new FileService(this);
try {
Map<String,String> map = fileService.getUserInfo("private.txt");
et_username.setText(map.get("username"));
et_password.setText(map.get("password"));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()) {
case R.id.button:
String username = et_username.getText().toString().trim();
String password = et_password.getText().toString().trim();
if(TextUtils.isEmpty(username) || TextUtils.isEmpty(password)){
Toast.makeText(this, R.string.error, Toast.LENGTH_SHORT).show();
return;
}
if(cb_remember.isChecked()){
Log.i(TAG, "儲存使用者名稱和密碼,"+username+":"+password);
try {
boolean result = fileService.saveToRom(password, username, "private.txt");
if(result){
Toast.makeText(getApplicationContext(), R.string.success, Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(getApplicationContext(), R.string.failed, Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
Toast.makeText(getApplicationContext(), R.string.failed, Toast.LENGTH_SHORT).show();
}
}
break;
}
}
}