Android 实现登录界面和功能实例

最后更新于:2022-04-01 19:47:43

最近一个android小程序需要登录功能,我简单实现了一下。现在记录下来也当做个笔记,同时也希望可以相互学习。所以,如果我的代码有问题,还各位请提出来。多谢了! 下面,就简述一下此实例的主要内容: 输入用户名和密码 ,从本地文件userinfo.json中读取users。判断此用户名是否在users中,如果不在则加入users,每次退出Activity都使用AES算法加密users,然后保存到userinfo.json中。用户名下拉菜单是由PopupWindow + ListView 实现。 运行效果图: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-02-17_56c4396c88575.jpg) ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-02-17_56c4396c9d0e2.jpg) ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-02-17_56c4396cabe82.jpg) 主要的代码: 1、用户类User ~~~ package com.example.logindemo; import org.json.JSONException; import org.json.JSONObject; import android.util.Log; public class User { private String mId; private String mPwd; private static final String masterPassword = "FORYOU"; // AES加密算法的种子 private static final String JSON_ID = "user_id"; private static final String JSON_PWD = "user_pwd"; private static final String TAG = "User"; public User(String id, String pwd) { this.mId = id; this.mPwd = pwd; } public User(JSONObject json) throws Exception { if (json.has(JSON_ID)) { String id = json.getString(JSON_ID); String pwd = json.getString(JSON_PWD); // 解密后存放 mId = AESUtils.decrypt(masterPassword, id); mPwd = AESUtils.decrypt(masterPassword, pwd); } } public JSONObject toJSON() throws Exception { // 使用AES加密算法加密后保存 String id = AESUtils.encrypt(masterPassword, mId); String pwd = AESUtils.encrypt(masterPassword, mPwd); Log.i(TAG, "加密后:" + id + " " + pwd); JSONObject json = new JSONObject(); try { json.put(JSON_ID, id); json.put(JSON_PWD, pwd); } catch (JSONException e) { e.printStackTrace(); } return json; } public String getId() { return mId; } public String getPwd() { return mPwd; } } ~~~ 2、保存和加载本地User列表 ~~~ package com.example.logindemo; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; import java.util.ArrayList; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONTokener; import android.content.Context; import android.util.Log; public class Utils { private static final String FILENAME = "userinfo.json"; // 用户保存文件名 private static final String TAG = "Utils"; /* 保存用户登录信息列表 */ public static void saveUserList(Context context, ArrayList users) throws Exception { /* 保存 */ Log.i(TAG, "正在保存"); Writer writer = null; OutputStream out = null; JSONArray array = new JSONArray(); for (User user : users) { array.put(user.toJSON()); } try { out = context.openFileOutput(FILENAME, Context.MODE_PRIVATE); // 覆盖 writer = new OutputStreamWriter(out); Log.i(TAG, "json的值:" + array.toString()); writer.write(array.toString()); } finally { if (writer != null) writer.close(); } } /* 获取用户登录信息列表 */ public static ArrayList getUserList(Context context) { /* 加载 */ FileInputStream in = null; ArrayList users = new ArrayList(); try { in = context.openFileInput(FILENAME); BufferedReader reader = new BufferedReader( new InputStreamReader(in)); StringBuilder jsonString = new StringBuilder(); JSONArray jsonArray = new JSONArray(); String line; while ((line = reader.readLine()) != null) { jsonString.append(line); } Log.i(TAG, jsonString.toString()); jsonArray = (JSONArray) new JSONTokener(jsonString.toString()) .nextValue(); // 把字符串转换成JSONArray对象 for (int i = 0; i < jsonArray.length(); i++) { User user = new User(jsonArray.getJSONObject(i)); users.add(user); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (JSONException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } return users; } } ~~~ 3、AES加密/解密 ~~~ package com.example.logindemo; import java.security.SecureRandom; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; public class AESUtils { public static String encrypt(String seed, String cleartext) throws Exception { byte[] rawKey = getRawKey(seed.getBytes()); byte[] result = encrypt(rawKey, cleartext.getBytes()); return toHex(result); } public static String decrypt(String seed, String encrypted) throws Exception { byte[] rawKey = getRawKey(seed.getBytes()); byte[] enc = toByte(encrypted); byte[] result = decrypt(rawKey, enc); return new String(result); } private static byte[] getRawKey(byte[] seed) throws Exception { KeyGenerator kgen = KeyGenerator.getInstance("AES"); SecureRandom sr = SecureRandom.getInstance("SHA1PRNG", "Crypto"); sr.setSeed(seed); kgen.init(128, sr); SecretKey skey = kgen.generateKey(); byte[] raw = skey.getEncoded(); return raw; } private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception { SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec( new byte[cipher.getBlockSize()])); byte[] encrypted = cipher.doFinal(clear); return encrypted; } private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception { SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec( new byte[cipher.getBlockSize()])); byte[] decrypted = cipher.doFinal(encrypted); return decrypted; } private static String toHex(String txt) { return toHex(txt.getBytes()); } private static String fromHex(String hex) { return new String(toByte(hex)); } private static byte[] toByte(String hexString) { int len = hexString.length() / 2; byte[] result = new byte[len]; for (int i = 0; i < len; i++) result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2), 16).byteValue(); return result; } private static String toHex(byte[] buf) { if (buf == null) return ""; StringBuffer result = new StringBuffer(2 * buf.length); for (int i = 0; i < buf.length; i++) { appendHex(result, buf[i]); } return result.toString(); } private final static String HEX = "0123456789ABCDEF"; private static void appendHex(StringBuffer sb, byte b) { sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f)); } } ~~~ 4、LoginActivity.java ~~~ package com.example.logindemo; import java.util.ArrayList; import android.app.Activity; import android.app.Dialog; import android.graphics.drawable.ColorDrawable; import android.os.Bundle; import android.text.Editable; import android.text.TextWatcher; import android.util.DisplayMetrics; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager; import android.view.View.OnClickListener; import android.view.ViewGroup.LayoutParams; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.EditText; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.PopupWindow; import android.widget.PopupWindow.OnDismissListener; import android.widget.TextView; import android.widget.Toast; public class LoginActivity extends Activity implements OnClickListener, OnItemClickListener, OnDismissListener { protected static final String TAG = "LoginActivity"; private LinearLayout mLoginLinearLayout; // 登录内容的容器 private LinearLayout mUserIdLinearLayout; // 将下拉弹出窗口在此容器下方显示 private Animation mTranslate; // 位移动画 private Dialog mLoginingDlg; // 显示正在登录的Dialog private EditText mIdEditText; // 登录ID编辑框 private EditText mPwdEditText; // 登录密码编辑框 private ImageView mMoreUser; // 下拉图标 private Button mLoginButton; // 登录按钮 private ImageView mLoginMoreUserView; // 弹出下拉弹出窗的按钮 private String mIdString; private String mPwdString; private ArrayList mUsers; // 用户列表 private ListView mUserIdListView; // 下拉弹出窗显示的ListView对象 private MyAapter mAdapter; // ListView的监听器 private PopupWindow mPop; // 下拉弹出窗 @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_login); initView(); setListener(); mLoginLinearLayout.startAnimation(mTranslate); // Y轴水平移动 /* 获取已经保存好的用户密码 */ mUsers = Utils.getUserList(LoginActivity.this); if (mUsers.size() > 0) { /* 将列表中的第一个user显示在编辑框 */ mIdEditText.setText(mUsers.get(0).getId()); mPwdEditText.setText(mUsers.get(0).getPwd()); } LinearLayout parent = (LinearLayout) getLayoutInflater().inflate( R.layout.userifo_listview, null); mUserIdListView = (ListView) parent.findViewById(android.R.id.list); parent.removeView(mUserIdListView); // 必须脱离父子关系,不然会报错 mUserIdListView.setOnItemClickListener(this); // 设置点击事 mAdapter = new MyAapter(mUsers); mUserIdListView.setAdapter(mAdapter); } /* ListView的适配器 */ class MyAapter extends ArrayAdapter { public MyAapter(ArrayList users) { super(LoginActivity.this, 0, users); } public View getView(final int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = getLayoutInflater().inflate( R.layout.listview_item, null); } TextView userIdText = (TextView) convertView .findViewById(R.id.listview_userid); userIdText.setText(getItem(position).getId()); ImageView deleteUser = (ImageView) convertView .findViewById(R.id.login_delete_user); deleteUser.setOnClickListener(new OnClickListener() { // 点击删除deleteUser时,在mUsers中删除选中的元素 @Override public void onClick(View v) { if (getItem(position).getId().equals(mIdString)) { // 如果要删除的用户Id和Id编辑框当前值相等,则清空 mIdString = ""; mPwdString = ""; mIdEditText.setText(mIdString); mPwdEditText.setText(mPwdString); } mUsers.remove(getItem(position)); mAdapter.notifyDataSetChanged(); // 更新ListView } }); return convertView; } } private void setListener() { mIdEditText.addTextChangedListener(new TextWatcher() { public void onTextChanged(CharSequence s, int start, int before, int count) { mIdString = s.toString(); } public void beforeTextChanged(CharSequence s, int start, int count, int after) { } public void afterTextChanged(Editable s) { } }); mPwdEditText.addTextChangedListener(new TextWatcher() { public void onTextChanged(CharSequence s, int start, int before, int count) { mPwdString = s.toString(); } public void beforeTextChanged(CharSequence s, int start, int count, int after) { } public void afterTextChanged(Editable s) { } }); mLoginButton.setOnClickListener(this); mLoginMoreUserView.setOnClickListener(this); } private void initView() { mIdEditText = (EditText) findViewById(R.id.login_edtId); mPwdEditText = (EditText) findViewById(R.id.login_edtPwd); mMoreUser = (ImageView) findViewById(R.id.login_more_user); mLoginButton = (Button) findViewById(R.id.login_btnLogin); mLoginMoreUserView = (ImageView) findViewById(R.id.login_more_user); mLoginLinearLayout = (LinearLayout) findViewById(R.id.login_linearLayout); mUserIdLinearLayout = (LinearLayout) findViewById(R.id.userId_LinearLayout); mTranslate = AnimationUtils.loadAnimation(this, R.anim.my_translate); // 初始化动画对象 initLoginingDlg(); } public void initPop() { int width = mUserIdLinearLayout.getWidth() - 4; int height = LayoutParams.WRAP_CONTENT; mPop = new PopupWindow(mUserIdListView, width, height, true); mPop.setOnDismissListener(this);// 设置弹出窗口消失时监听器 // 注意要加这句代码,点击弹出窗口其它区域才会让窗口消失 mPop.setBackgroundDrawable(new ColorDrawable(0xffffffff)); } /* 初始化正在登录对话框 */ private void initLoginingDlg() { mLoginingDlg = new Dialog(this, R.style.loginingDlg); mLoginingDlg.setContentView(R.layout.logining_dlg); Window window = mLoginingDlg.getWindow(); WindowManager.LayoutParams params = window.getAttributes(); // 获取和mLoginingDlg关联的当前窗口的属性,从而设置它在屏幕中显示的位置 // 获取屏幕的高宽 DisplayMetrics dm = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(dm); int cxScreen = dm.widthPixels; int cyScreen = dm.heightPixels; int height = (int) getResources().getDimension( R.dimen.loginingdlg_height);// 高42dp int lrMargin = (int) getResources().getDimension( R.dimen.loginingdlg_lr_margin); // 左右边沿10dp int topMargin = (int) getResources().getDimension( R.dimen.loginingdlg_top_margin); // 上沿20dp params.y = (-(cyScreen - height) / 2) + topMargin; // -199 /* 对话框默认位置在屏幕中心,所以x,y表示此控件到"屏幕中心"的偏移量 */ params.width = cxScreen; params.height = height; // width,height表示mLoginingDlg的实际大小 mLoginingDlg.setCanceledOnTouchOutside(true); // 设置点击Dialog外部任意区域关闭Dialog } /* 显示正在登录对话框 */ private void showLoginingDlg() { if (mLoginingDlg != null) mLoginingDlg.show(); } /* 关闭正在登录对话框 */ private void closeLoginingDlg() { if (mLoginingDlg != null && mLoginingDlg.isShowing()) mLoginingDlg.dismiss(); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.login_btnLogin: // 启动登录 showLoginingDlg(); // 显示"正在登录"对话框,因为此Demo没有登录到web服务器,所以效果可能看不出.可以结合情况使用 Log.i(TAG, mIdString + " " + mPwdString); if (mIdString == null || mIdString.equals("")) { // 账号为空时 Toast.makeText(LoginActivity.this, "请输入账号", Toast.LENGTH_SHORT) .show(); } else if (mPwdString == null || mPwdString.equals("")) {// 密码为空时 Toast.makeText(LoginActivity.this, "请输入密码", Toast.LENGTH_SHORT) .show(); } else {// 账号和密码都不为空时 boolean mIsSave = true; try { Log.i(TAG, "保存用户列表"); for (User user : mUsers) { // 判断本地文档是否有此ID用户 if (user.getId().equals(mIdString)) { mIsSave = false; break; } } if (mIsSave) { // 将新用户加入users User user = new User(mIdString, mPwdString); mUsers.add(user); } } catch (Exception e) { e.printStackTrace(); } closeLoginingDlg();// 关闭对话框 Toast.makeText(this, "登录成功", Toast.LENGTH_SHORT).show(); finish(); } break; case R.id.login_more_user: // 当点击下拉栏 if (mPop == null) { initPop(); } if (!mPop.isShowing() && mUsers.size() > 0) { // Log.i(TAG, "切换为角向上图标"); mMoreUser.setImageResource(R.drawable.login_more_down); // 切换图标 mPop.showAsDropDown(mUserIdLinearLayout, 2, 1); // 显示弹出窗口 } break; default: break; } } @Override public void onItemClick(AdapterView parent, View view, int position, long id) { mIdEditText.setText(mUsers.get(position).getId()); mPwdEditText.setText(mUsers.get(position).getPwd()); mPop.dismiss(); } /* PopupWindow对象dismiss时的事件 */ @Override public void onDismiss() { // Log.i(TAG, "切换为角向下图标"); mMoreUser.setImageResource(R.drawable.login_more_up); } /* 退出此Activity时保存users */ @Override public void onPause() { super.onPause(); try { Utils.saveUserList(LoginActivity.this, mUsers); } catch (Exception e) { e.printStackTrace(); } } } ~~~ 其他一些布局和资源配置我就不详细列出了,想看的可以下载    [源码](http://download.csdn.net/detail/u012964281/8102005)
';

Android平台 AES加密/解密

最后更新于:2022-04-01 19:47:40

网上有些代码在运行解密时抛出错误:javax.crypto.BadPaddingException: pad block corrupted  以下代码亲测运行无误: ~~~ package com.example.testandroid; import java.security.SecureRandom; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.MenuItem; public class MainActivity extends Activity { private static final String TAG = "MainActivity"; public static String encrypt(String seed, String cleartext) throws Exception { byte[] rawKey = getRawKey(seed.getBytes()); byte[] result = encrypt(rawKey, cleartext.getBytes()); return toHex(result); } public static String decrypt(String seed, String encrypted) throws Exception { byte[] rawKey = getRawKey(seed.getBytes()); byte[] enc = toByte(encrypted); byte[] result = decrypt(rawKey, enc); return new String(result); } private static byte[] getRawKey(byte[] seed) throws Exception { KeyGenerator kgen = KeyGenerator.getInstance("AES"); SecureRandom sr = SecureRandom.getInstance("SHA1PRNG", "Crypto"); sr.setSeed(seed); kgen.init(128, sr); SecretKey skey = kgen.generateKey(); byte[] raw = skey.getEncoded(); return raw; } private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception { SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec( new byte[cipher.getBlockSize()])); byte[] encrypted = cipher.doFinal(clear); return encrypted; } private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception { SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec( new byte[cipher.getBlockSize()])); byte[] decrypted = cipher.doFinal(encrypted); return decrypted; } private static String toHex(String txt) { return toHex(txt.getBytes()); } private static String fromHex(String hex) { return new String(toByte(hex)); } private static byte[] toByte(String hexString) { int len = hexString.length() / 2; byte[] result = new byte[len]; for (int i = 0; i < len; i++) result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2), 16).byteValue(); return result; } private static String toHex(byte[] buf) { if (buf == null) return ""; StringBuffer result = new StringBuffer(2 * buf.length); for (int i = 0; i < buf.length; i++) { appendHex(result, buf[i]); } return result.toString(); } private final static String HEX = "0123456789ABCDEF"; private static void appendHex(StringBuffer sb, byte b) { sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f)); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); String masterPassword = "key"; String originalText = "0123456789"; try { String encryptingCode = MainActivity.encrypt(masterPassword, originalText); Log.e(TAG, "加密后: " + encryptingCode); String decryptingCode = MainActivity.decrypt(masterPassword, encryptingCode); Log.e(TAG, "解密后: " + decryptingCode); } catch (Exception e) { e.printStackTrace(); } } } ~~~
';

Android Base64 编码/解码

最后更新于:2022-04-01 19:47:37

### Base64编码说明 Base64编码要求把3个8位字节(3*8=24)转化为4个6位的字节(4*6=24),之后在6位的前面补两个0,形成8位一个字节的形式。 如果剩下的字符不足3个字节,则用0填充,输出字符使用'=',因此编码后输出的文本末尾可能会出现1或2个'='。 为了保证所输出的编码位可读字符,Base64制定了一个编码表,以便进行统一转换。编码表的大小为2^6=64,这也是Base64名称的由来。 ### Base64编码表
码值字符
码值字符
码值字符
码值字符
0A16Q32g48w
1B17R33h49x
2C18S34i50y
3D19T35j51z
4E20U36k520
5F21V37l531
6G22W38m542
7H23X39n553
8I24Y40o564
9J25Z41p575
10K26a42q586
11L27b43r597
12M28c44s608
13N29d45t619
14O30e46u62+
15P31f47v63/

**用法:** ~~~ String token = "hello world"; // 编码前 String  base64Token = Base64.encodeToString(token.getBytes(), Base64.DEFAULT);//  编码后 byte[] m = Base64.decode(base64Token,Base64.DEFAULT);// 解码后 ~~~ 其中第二个参数: Base64.flag - CRLF 这个参数看起来比较眼熟,它就是Win风格的换行符,意思就是使用CR LF这一对作为一行的结尾而不是Unix风格的LF - DEFAULT 这个参数是默认,使用默认的方法来加密 - NO_PADDING 这个参数是略去加密字符串最后的”=” - NO_WRAP 这个参数意思是略去所有的换行符(设置后CRLF就没用了) - URL_SAFE 这个参数意思是加密时不使用对URL和文件名有特殊意义的字符来作为加密字符,具体就是以-和_取代+和/
';

android socket 编程实例

最后更新于:2022-04-01 19:47:34

[转载来源](http://blog.csdn.net/wuchuanpingstone/article/details/6617276#comments) android客户端通过socket与服务器进行通信可以分为以下几步: 应用程序与服务器通信可以采用两种模式:TCP可靠通信 和UDP不可靠通信。 (1)通过IP地址和端口实例化Socket,请求连接服务器: socket = new Socket(HOST, PORT);   //host:为服务器的IP地址  port:为服务器的端口号 (2)获取Socket流以进行读写,并把流包装进BufferWriter或者PrintWriter: PrintWriter out = new PrintWriter( new BufferedWriter( new OutputStreamWriter(socket.getOutputStream())),true);   这里涉及了三个类:socket.getOutputStream得到socket的输出字节流,OutputStreamWriter是字节流向字符流转换的桥梁,BufferWriter是字符流,然后再包装进PrintWriter。 (3)对Socket进行读写 ~~~     if (socket.isConnected()) {                    if (!socket.isOutputShutdown()) {                        out.println(msg);                    }                } ~~~ (4)关闭打开的流 `     out.close();` 在写代码的过程中一定要注意对socket  输入流  输出流的关闭 下面是一个简单的例子: main.xml ~~~ ~~~ 下面是android客户端的源代码: ~~~ package com.example.socketdemo; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.Socket; import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.os.StrictMode; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; @TargetApi(Build.VERSION_CODES.GINGERBREAD) @SuppressLint("NewApi") public class SocketDemo extends Activity implements Runnable { private TextView tv_msg = null; private EditText ed_msg = null; private Button btn_send = null; // private Button btn_login = null; private static final String HOST = "192.168.1.223"; private static final int PORT = 9999; private Socket socket = null; private BufferedReader in = null; private PrintWriter out = null; private String content = ""; /**Called when the activity is first created. */ @TargetApi(Build.VERSION_CODES.GINGERBREAD) @SuppressLint("NewApi") @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_socket_demo); ////Android 2.3及以上调用严苛模式 if (android.os.Build.VERSION.SDK_INT > 9) { StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder() .permitAll().build(); StrictMode.setThreadPolicy(policy); } tv_msg = (TextView) findViewById(R.id.TextView); ed_msg = (EditText) findViewById(R.id.EditText01); // btn_login = (Button) findViewById(R.id.Button01); btn_send = (Button) findViewById(R.id.Button02); try { socket = new Socket(HOST, PORT); in = new BufferedReader(new InputStreamReader( socket.getInputStream())); out = new PrintWriter(new BufferedWriter(new OutputStreamWriter( socket.getOutputStream())), true); } catch (IOException ex) { ex.printStackTrace(); ShowDialog("login exception" + ex.getMessage()); } btn_send.setOnClickListener(new Button.OnClickListener() { public void onClick(View v) { // TODO Auto-generated method stub String msg = ed_msg.getText().toString(); if (socket.isConnected()) { if (!socket.isOutputShutdown()) { out.println(msg); } } } }); new Thread(SocketDemo.this).start(); } public void ShowDialog(String msg) { new AlertDialog.Builder(this).setTitle("notification").setMessage(msg) .setPositiveButton("ok", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { // TODO Auto-generated method stub } }).show(); } public void run() { try { while (true) { if (socket.isConnected()) { if (!socket.isInputShutdown()) { if ((content = in.readLine()) != null) { content += "\n"; mHandler.sendMessage(mHandler.obtainMessage()); } else { } } } } } catch (Exception e) { e.printStackTrace(); } } public Handler mHandler = new Handler() { public void handleMessage(Message msg) { super.handleMessage(msg); tv_msg.setText(tv_msg.getText().toString() + content); } }; } ~~~ 下面是服务器端的java代码: ~~~ import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Main { private static final int PORT = 9999; private List mList = new ArrayList(); private ServerSocket server = null; private ExecutorService mExecutorService = null; //thread pool public static void main(String[] args) { new Main(); } public Main() { try { server = new ServerSocket(PORT); mExecutorService = Executors.newCachedThreadPool(); //create a thread pool System.out.print("server start ..."); Socket client = null; while(true) { client = server.accept(); mList.add(client); mExecutorService.execute(new Service(client)); //start a new thread to handle the connection } }catch (Exception e) { e.printStackTrace(); } } class Service implements Runnable { private Socket socket; private BufferedReader in = null; private String msg = ""; public Service(Socket socket) { this.socket = socket; try { in = new BufferedReader(new InputStreamReader(socket.getInputStream())); msg = "user" +this.socket.getInetAddress() + "come toal:" +mList.size(); this.sendmsg(); } catch (IOException e) { e.printStackTrace(); } } @Override public void run() { // TODO Auto-generated method stub try { while(true) { if((msg = in.readLine())!= null) { if(msg.equals("exit")) { System.out.println("ssssssss"); mList.remove(socket); in.close(); msg = "user:" + socket.getInetAddress() + "exit total:" + mList.size(); socket.close(); this.sendmsg(); break; } else { msg = socket.getInetAddress() + ":" + msg; this.sendmsg(); } } } } catch (Exception e) { e.printStackTrace(); } } public void sendmsg() { System.out.println(msg); int num =mList.size(); for (int index = 0; index < num; index ++) { Socket mSocket = mList.get(index); PrintWriter pout = null; try { pout = new PrintWriter(new BufferedWriter( new OutputStreamWriter(mSocket.getOutputStream())),true); pout.println(msg); }catch (IOException e) { e.printStackTrace(); } } } } } ~~~ 注意在AndroidManifest.xml中加入对网络的访问权限 在写代码的过程中一定要注意对套接字和输入/输出流的关闭
';

Android存储和加载本地文件(外部存储设备)

最后更新于:2022-04-01 19:47:32

有时候应用需要将数据写入到设备的外部存储上。列如,需要同其他应用或用户共享音乐、图片或者网络下载资料时,保存在外部设备的数据共享起来要比较方便。而且,外部设备通常具有更大的存储空间。 我们可以通过android.os.Environment.getExternalStorageDirectory()方法获取sdCard的路径。再在此路径下创建一个MyFiles的文件,将数据保存在MyFiles文件夹下。 下面就展示如何在外部存储设备中存储和加载本地文件: 1、创建一个名为 DataStorage的工程 2、准备好布局文件(activity_data_storage.xml) ~~~
';

Android存储和加载本地文件(内部存储设备)

最后更新于:2022-04-01 19:47:29

Android设备上的所有应用都有一个放置在沙盘中的文件目录,将文件保存到沙盒中可以阻止其他应用的访问。 沙盒目录的全路径为:/data/data/<包名>  用File Explorer查看: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-02-17_56c4396c35105.jpg) 如上图可见,每个应用都在/data/data下有一个以此应用包名命名的文件目录。 而本文就是介绍将文件保存在/data/data/<包名>/files/ 目录下 下面就展示如何在内部存储设备中存储和加载本地文件: 1、创建一个名为 DataStorage的工程 2、准备好布局文件(activity_data_storage.xml) ~~~
';

Android VideoView实现视频播放

最后更新于:2022-04-01 19:47:26

xml文件 ~~~ ~~~ java文件 ~~~ package com.example.playvideo; import android.support.v7.app.ActionBarActivity; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.widget.MediaController; import android.widget.VideoView; public class PlayVideo extends ActionBarActivity { private VideoView videoView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_play_video); videoView = (VideoView) findViewById(R.id.video_view); MediaController mc = new MediaController(this); videoView.setMediaController(mc); //videoView.setVideoPath("/sdcard/forTest.mp4");//sdcard上的视频 videoView.setVideoPath("android.resource://com.example.showvideo/"+ R.raw.test); videoView.requestFocus(); videoView.start(); } } ~~~ 运行效果如下图: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-02-17_56c4396be8f37.jpg) 备注: 遇到过一个叫Error (1,-2147483648)的错误,程序直接崩溃: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-02-17_56c4396c0d9bc.jpg) ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-02-17_56c4396c23870.jpg) 我查了一下,原来它代表 未知错误 真正的原因在于: MP4有多种编码格式,例如H.264,H.263等,而Android版本较低的机器只支持部分编码。 一旦遭遇不被支持的编码格式,MediaPlayer可能就会抛出上面的错误信息。 于是,我把被测试的mpg格式的视频换成mp4格式,结果就OK了。
';

Android ListFragment

最后更新于:2022-04-01 19:47:24

Android是在Android 3.0(API level 11)开始引入Fragment的(为了兼容较低版本的设备使用支持库类)。可以把Fragment看成Activity中的模块,这个模块有自己的布局,有自己的生命周期(由托管activity调用其周期方法),单独处理自己的输入,在Activity运行的时候可以加载或者移除Fragment模块。 ListFragment是Fragment的子类,内置列表显示支持功能。ListFragment通过内置的ListView显示绑定在其上面的数据。下面就通过例子了解具体的用法: 1、模型层  Day类和DayLab类 通过DayLab对象的getDays()方法获取用来绑定的数据。 Day.java                                  ~~~ package com.example.showdays; import java.util.ArrayList; public class Day { private String mTitle; public String getTitle() { return mTitle; } public void setTitle(String mTitle) { this.mTitle = mTitle; } } ~~~ DayLab.java                            ~~~ package com.example.showdays; import java.util.ArrayList; public class DayLab { private ArrayList mDays; public DayLab() { mDays = new ArrayList(); for (int i = 1; i <= 10; i++) { Day day = new Day(); day.setTitle("Title #" + i); mDays.add(day); } } public ArrayList getDays() { return mDays; } } ~~~ 2、创建DayListFragment类 继承ListFragment类。并给其内置的ListView设置Adapter DayListFragment.java             ~~~ package com.example.showdays; import java.util.ArrayList; import android.os.Bundle; import android.support.v4.app.ListFragment; import android.widget.ArrayAdapter; public class DayListFragment extends ListFragment { private ArrayList days; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); DayLab dayLab = new DayLab(); this.days = dayLab.getDays(); ArrayAdapter adapter = new ArrayAdapter(getActivity(), android.R.layout.simple_list_item_1, days); // 第一个参数: Context对象,使用第二个参数的资源ID需要该Context对象 // 第二个参数: 资源ID,可定位ArrayAdapter用来创建View对象的布局,这里的实参是 Android SDK提供的预定义布局资源 // 第三个参数: 数据集 setListAdapter(adapter);// 给DayListFragment内置的ListView设置adapter } } ~~~ 3、创建DayActivity类 继承FragmentActivity类。托管DayListFragment对象 其布局如下: activity_day.xml                       ~~~ ~~~ 在类中引用此布局文件,并将DayListFragment对象放置在id为fragmentContainer的FrameLayout容器视图中。 DayActivity.java                       ~~~ package com.example.showdays; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.MenuItem; public class DayActivity extends FragmentActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_day); FragmentManager fm = getSupportFragmentManager(); // 继承支持库类FragmentActivity获取FragmentManager对象的方法 // 若继承Activity使用getFragmentManager() Fragment fragment = fm.findFragmentById(R.id.fragmentContainer); if (fragment == null) { // 查看fragment事务队列中是否存在此事物 fragment = new DayListFragment(); fm.beginTransaction().add(R.id.fragmentContainer, fragment) .commit(); // 提交事务(资源ID作为唯一标识符且通知视图位置) } } } ~~~ 至此程序就可以正常运行了,运行效果如下图: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-02-17_56c4396bafd18.jpg) 可以看到,已经呈现出列表形式,但是要显示的内容却不是我想要的。 那是因为 Android SDK提供的预定义布局资源(android.R.layout.simple_list_item_1)布局如下: ~~~ ~~~ 这样在ListView被实例化后与adapter会话时,ArrayAdapter.getView()方法会调用Day对象的toString()方法,然后将返回值传递给TextView。 所以覆盖Day对象toString()方法: Day.java                                  ~~~ package com.example.showdays; import java.util.ArrayList; public class Day { private String mTitle; public String getTitle() { return mTitle; } public void setTitle(String mTitle) { this.mTitle = mTitle; } @Override public String toString() { return mTitle; } } ~~~ 此时再运行程序,运行效果如下图: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-02-17_56c4396bc39f2.jpg) 4、自定义列表项 上面使用的是Android SDK提供的预定义布局资源,直接把数据放置在TextView组件中来显示。 下面我就自定义一个列表项布局,将要显示的信息用Button组件来显示,布局如下: my_list_item.xml                      ~~~ ~~~ 因为ListView更新视图的时候都要调用ArrayAdapter.getView()方法来获取View。所以要想把自己定义的列表项加入到ListView中,可以重写getView()方法,覆盖它并返回一个自己定义的View。做出改变如下: DayListFragment.java             ~~~ package com.example.showdays; import java.util.ArrayList; import android.os.Bundle; import android.support.v4.app.ListFragment; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.Button; public class DayListFragment extends ListFragment { private ArrayList days; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); DayLab dayLab = new DayLab(); this.days = dayLab.getDays(); DayAdapter adapter = new DayAdapter(days); setListAdapter(adapter); } private class DayAdapter extends ArrayAdapter { public DayAdapter(ArrayList days) { super(getActivity(), 0, days); } @Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { // 此列表项是否存在,不存在则创建一个 convertView = getActivity().getLayoutInflater().inflate( R.layout.my_list_item, null); } Day day = getItem(position); // 获取当前位置的Day对象 Button button = (Button) convertView.findViewById(R.id.button); button.setText(day.toString()); return convertView; } } } ~~~ 最后运行一下,运行效果如下图: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-02-17_56c4396bd70f4.jpg) `#DONE#`
';

Android Fragment 基本介绍

最后更新于:2022-04-01 19:47:20

[转载来源](http://www.cnblogs.com/mengdd/archive/2013/01/08/2851368.html) ### Fragment Android是在Android 3.0 (API level 11)开始引入Fragment的。 可以把Fragment想成Activity中的模块,这个模块有自己的布局,有自己的生命周期,单独处理自己的输入,在Activity运行的时候可以加载或者移除Fragment模块。 可以把Fragment设计成可以在多个Activity中复用的模块。 当开发的应用程序同时适用于平板电脑和手机时,可以利用Fragment实现灵活的布局,改善用户体验。 如图: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-02-17_56c4396b29d4d.png) ### Fragment的生命周期 因为Fragment必须嵌入在Acitivity中使用,所以Fragment的生命周期和它所在的Activity是密切相关的。 如果Activity是暂停状态,其中所有的Fragment都是暂停状态;如果Activity是stopped状态,这个Activity中所有的Fragment都不能被启动;如果Activity被销毁,那么它其中的所有Fragment都会被销毁。 但是,当Activity在活动状态,可以独立控制Fragment的状态,比如加上或者移除Fragment。 当这样进行fragment transaction(转换)的时候,可以把fragment放入Activity的**back stack**中,这样用户就可以进行返回操作。 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-02-17_56c4396b3fc97.png) ### Fragment的使用相关 使用Fragment时,需要继承Fragment或者Fragment的子类(DialogFragment, ListFragment, PreferenceFragment, WebViewFragment),所以Fragment的代码看起来和Activity的类似。 **使用Support Library** Support Library是一个提供了API库函数的JAR文件,这样就可以在旧版本的Android上使用一些新版本的APIs。 比如android-support-v4.jar.它的完整路径是: /extras/android/support/v4/android-support-v4.jar. 它就提供了Fragment的APIs,使得在Android 1.6 (API level 4)以上的系统都可以使用Fragment。 为了确定没有在旧版本系统上使用新版本的APIs,需要如下导入语句: ~~~   import android.support.v4.app.Fragment; ~~~ ~~~   import android.support.v4.app.FragmentManager; ~~~ 同时应该将上述的包拷入libs项目下的libs文件夹,然后在项目的Properties中添加:右键单击项目,选Properties,左边选Java Build Path,然后Add External JARs…,添加android-support-v4.jar. ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-02-17_56c4396b5f3df.png) **当创建包含Fragment的Activity时,如果用的是Support Library,那么继承的就应该是FragmentActivity而不是Activity。** **必须实现的三个回调函数** onCreate() 系统在创建Fragment的时候调用这个方法,这里应该初始化相关的组件,一些即便是被暂停或者被停止时依然需要保留的东西。 onCreateView() 当第一次绘制Fragment的UI时系统调用这个方法,必须返回一个View,如果Fragment不提供UI也可以返回null。 注意,如果继承自ListFragment,onCreateView()默认的实现会返回一个ListView,所以不用自己实现。 onPause() 当用户离开Fragment时第一个调用这个方法,需要提交一些变化,因为用户很可能不再返回来。 **实现Fragment的UI** 提供Fragment的UI,必须实现onCreateView()方法。 假设Fragment的布局设置写在example_fragment.xml资源文件中,那么onCreateView()方法可以如下写:    [![复制代码](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2015-10-30_5632e1b8d3b57.gif)]( "复制代码") ~~~ public static class ExampleFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container,   Bundle savedInstanceState) { // Inflate the layout for this fragment return inflater.inflate(R.layout.example_fragment, container, false); } } ~~~ [![复制代码](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2015-10-30_5632e1b8d3b57.gif)]( "复制代码") onCreateView()中container参数代表该Fragment在Activity中的父控件;savedInstanceState提供了上一个实例的数据。 inflate()方法的三个参数: 第一个是resource ID,指明了当前的Fragment对应的资源文件; 第二个参数是父容器控件; 第三个布尔值参数表明是否连接该布局和其父容器控件,在这里的情况设置为false,因为系统已经插入了这个布局到父控件,设置为true将会产生多余的一个View Group。 ### 把Fragment加入Activity 当Fragment被加入Activity中时,它会处在对应的View Group中。 Fragment有两种加载方式:一种是在Activity的layout中使用标签声明;另一种方法是在代码中把它加入到一个指定的ViewGroup中。 另外,Fragment它可以并不是Activity布局中的任何一部分,它可以是一个不可见的部分。这部分内容先略过。 **加载方式1:通过Activity的布局文件将Fragment加入Activity** 在Activity的布局文件中,将Fragment作为一个子标签加入即可。 如: [![复制代码](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2015-10-30_5632e1b8d3b57.gif)]( "复制代码") ~~~ ~~~ [![复制代码](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2015-10-30_5632e1b8d3b57.gif)]( "复制代码") 其中android:name属性填上你自己创建的fragment的完整类名。 **当系统创建这个Activity的布局文件时,系统会实例化每一个fragment,并且调用它们的onCreateView()方法,来获得相应fragment的布局,并将返回值插入fragment标签所在的地方。** 有三种方法为Fragment提供ID: android:id属性:唯一的id android:tag属性:唯一的字符串 如果上面两个都没提供,系统使用容器view的ID。 **加载方式2:通过编程的方式将Fragment加入到一个ViewGroup中** 当Activity处于Running状态下的时候,可以在Activity的布局中动态地加入Fragment,只需要指定加入这个Fragment的父View Group即可。 首先,需要一个FragmentTransaction实例:  ~~~ FragmentManager fragmentManager = getFragmentManager() FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); ~~~ **(注,如果import android.support.v4.app.FragmentManager;那么使用的是:FragmentManager fragmentManager = getSupportFragmentManager();)**    之后,用add()方法加上Fragment的对象: ~~~ ExampleFragment fragment = new ExampleFragment(); fragmentTransaction.add(R.id.fragment_container, fragment); fragmentTransaction.commit(); ~~~ 其中第一个参数是这个fragment的容器,即父控件组。 最后需要调用commit()方法使得FragmentTransaction实例的改变生效。 ### 实例 练习的例子: 写一个类继承自Fragment类,并且写好其布局文件(本例中是两个TextView),在Fragment类的onCreateView()方法中加入该布局。 之后用两种方法在Activity中加入这个fragment: 第一种是在Activity的布局文件中加入标签; 第二种是在Activity的代码中使用FragmentTransaction的add()方法加入fragment。 **贴出代码:** 自己定义的fragment类: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-02-17_56c4396b79c3e.gif) [![复制代码](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2015-10-30_5632e1b8d3b57.gif)]( "复制代码") ~~~ package com.example.learningfragment; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; public class ExampleFragment extends Fragment { //三个一般必须重载的方法 @Override public void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); System.out.println("ExampleFragment--onCreate"); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { System.out.println("ExampleFragment--onCreateView"); return inflater.inflate(R.layout.example_fragment_layout, container, false); } @Override public void onPause() { // TODO Auto-generated method stub super.onPause(); System.out.println("ExampleFragment--onPause"); } ~~~ ~~~ @Override public void onResume() { // TODO Auto-generated method stub super.onResume(); System.out.println("ExampleFragment--onResume"); } @Override public void onStop() { // TODO Auto-generated method stub super.onStop(); System.out.println("ExampleFragment--onStop"); } } ~~~ [![复制代码](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2015-10-30_5632e1b8d3b57.gif)]( "复制代码") fragment的布局文件: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-02-17_56c4396b79c3e.gif) [![复制代码](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2015-10-30_5632e1b8d3b57.gif)]( "复制代码") ~~~ ~~~ [![复制代码](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2015-10-30_5632e1b8d3b57.gif)]( "复制代码") 主Activity: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-02-17_56c4396b79c3e.gif) [![复制代码](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2015-10-30_5632e1b8d3b57.gif)]( "复制代码") ~~~ package com.example.learningfragment; import android.os.Bundle; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; public class LearnFragment extends FragmentActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_learn_fragment); //在程序中加入Fragment FragmentManager fragmentManager = getSupportFragmentManager(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); ExampleFragment fragment = new ExampleFragment(); fragmentTransaction.add(R.id.linear, fragment); fragmentTransaction.commit(); } } ~~~ [![复制代码](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2015-10-30_5632e1b8d3b57.gif)]( "复制代码") Activity的布局文件: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-02-17_56c4396b79c3e.gif) [![复制代码](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2015-10-30_5632e1b8d3b57.gif)]( "复制代码") ~~~
';

activity间的数据传递

最后更新于:2022-04-01 19:47:18

在Activity_A中启动Activity_B 实现Activity_A和Activity_B间的对话 一、信息仅从Activity_A传递到Activity_B Activity_A.java : ~~~ Intent intent = new Intent(Activity_A.this,Activity_B.class); intent.putExtra(key,value); startActivity(intent); ~~~ 将value信息,以键-值的形式,附加在Intent对象上发送过去,value可以是任意数据。 Activity_B.java : ~~~ getIntent().get类型Extra(key,defaultValue); //类型表示接收信息的类型,比如getStringExtra(...)等 ~~~ 通过此行代码返回传递过来的值,明显第二个参数为默认值。 二、Activity_B同时返回信息到Activity_A Activity_A.java : ~~~ Intent intent = new Intent(Activity_A.this,Activity_B.class); intent.putExtra(key,value); startActivityForResult(intent,requestCode); ~~~ 可以看到,启动Activity_B的方法更改成startActivityForResult(...)。 requestCode表示请求代码,当Activity_A启动多个不同类型的子activity时,用于区分各消息反馈。 在Activity_A中还需要重写onActivityResult(...)方法,来获取Activity_B回传的值。 ~~~ @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (data != null) { value = data.get类型Extra(key, defaultValue); // value表示回传的值 } } ~~~ Activity_B.java : ~~~ getIntent().get类型Extra(key,defaultValue); Intent data = new Intent(); data.putExtra(key,value); setResult(resultCode,data); ~~~ 可以看出,子activity通过setResult(...)方法将信息返回给父activity。
';

JavaScript与Java通信

最后更新于:2022-04-01 19:47:16

1、WebView中JavaScript调用Android程序中Java: 使用WebView类中的addJavascriptInterface()方法,可以使用它扩展嵌入式浏览器内的DOM(文档对象模型),并定义JavaScript代码可以访问的新对象。JavaScript代码调用该对象的方法时,实际上它会调用Android程序中的方法。 2、在Android程序中调用JavaScript方法: 调用loadUrl()方法,将URL以javascript:*要执行的代码 *的形式传递给它。浏览器会在当前页面执行给定的JavaScript表达式,而不是转到新的页面。 实例: 构建一个Android程序,布局如下(res/layout/activity_local_browser.xml) ~~~
';

Android颜色对照表

最后更新于:2022-04-01 19:47:13

**颜色代码大全** AA 指定透明度。 00 是完全透明。 FF 是完全不透明。超出取值范围的值将被恢复为默认值。

  

ffff00ffff33ffff66ffff99ffffccffffff
ffcc00ffcc33ffcc66ffcc99ffccccffccff
ff9900ff9933ff9966ff9999ff99ccff99ff
ff6600ff6633ff6666ff6699ff66ccff66ff
ff3300ff3333ff3366ff3399ff33ccff33ff
ff0000ff0033ff0066ff0099ff00ccff00ff
ccff00ccff33ccff66ccff99ccffccccffff
cccc00cccc33cccc66cccc99ccccccccccff
cc9900cc9933cc9966cc9999cc99cccc99ff
cc6600cc6633cc6666cc6699cc66cccc66ff
cc3300cc3333cc3366cc3399cc33cccc33ff
cc0000cc0033cc0066cc0099cc00cccc00ff
99ff0099ff3399ff6699ff9999ffcc99ffff
99cc0099cc3399cc6699cc9999cccc99ccff
9999009999339999669999999999cc9999ff
9966009966339966669966999966cc9966ff
9933009933339933669933999933cc9933ff
9900009900339900669900999900cc9900ff
66ff0066ff3366ff6666ff9966ffcc66ffff
66cc0066cc3366cc6666cc9966cccc66ccff
6699006699336699666699996699cc6699ff
6666006666336666666666996666cc6666ff
6633006633336633666633996633cc6633ff
6600006600336600666600996600cc6600ff
33ff0033ff3333ff6633ff9933ffcc33ffff
33cc0033cc3333cc6633cc9933cccc33ccff
3399003399333399663399993399cc3399ff
3366003366333366663366993366cc3366ff
3333003333333333663333993333cc3333ff
3300003300333300663300993300cc3300ff
00ff0000ff3300ff6600ff9900ffcc00ffff
00cc0000cc3300cc6600cc9900cccc00ccff
0099000099330099660099990099cc0099ff
0066000066330066660066990066cc0066ff
0033000033330033660033990033cc0033ff
0000000000330000660000990000cc0000ff

 

 

 

 #FFFFFF #FFFFF0 #FFFFE0 #FFFF00
 #FFFAFA #FFFAF0 #FFFACD #FFF8DC
 #FFF68F #FFF5EE #FFF0F5 #FFEFDB
 #FFEFD5 #FFEC8B #FFEBCD #FFE7BA
 #FFE4E1 #FFE4C4 #FFE4B5 #FFE1FF
 #FFDEAD #FFDAB9 #FFD700 #FFD39B
 #FFC1C1 #FFC125 #FFC0CB #FFBBFF
 #FFB90F #FFB6C1 #FFB5C5 #FFAEB9
 #FFA54F #FFA500 #FFA07A #FF8C69
 #FF8C00 #FF83FA #FF82AB #FF8247
 #FF7F50 #FF7F24 #FF7F00 #FF7256
 #FF6EB4 #FF6A6A #FF69B4 #FF6347
 #FF4500 #FF4040 #FF3E96 #FF34B3
 #FF3030 #FF1493 #FF00FF #FF0000
 #FDF5E6 #FCFCFC #FAFAFA #FAFAD2
 #FAF0E6 #FAEBD7 #FA8072 #F8F8FF
 #F7F7F7 #F5FFFA #F5F5F5 #F5F5DC
 #F5DEB3 #F4F4F4 #F4A460 #F2F2F2
 #F0FFFF #F0FFF0 #F0F8FF #F0F0F0
 #F0E68C #F08080 #EEEEE0 #EEEED1
 #EEEE00 #EEE9E9 #EEE9BF #EEE8CD
 #EEE8AA #EEE685 #EEE5DE #EEE0E5
 #EEDFCC #EEDC82 #EED8AE #EED5D2
 #EED5B7 #EED2EE #EECFA1 #EECBAD
 #EEC900 #EEC591 #EEB4B4 #EEB422
 #EEAEEE #EEAD0E #EEA9B8 #EEA2AD
 #EE9A49 #EE9A00 #EE9572 #EE82EE
 #EE8262 #EE7AE9 #EE799F #EE7942
 #EE7621 #EE7600 #EE6AA7 #EE6A50
 #EE6363 #EE5C42 #EE4000 #EE3B3B
 #EE3A8C #EE30A7 #EE2C2C #EE1289
 #EE00EE #EE0000 #EDEDED #EBEBEB
 #EAEAEA #E9967A #E8E8E8 #E6E6FA
 #E5E5E5 #E3E3E3 #E0FFFF #E0EEEE
 #E0EEE0 #E0E0E0 #E066FF #DEDEDE
 #DEB887 #DDA0DD #DCDCDC #DC143C
 #DBDBDB #DB7093 #DAA520 #DA70D6
 #D9D9D9 #D8BFD8 #D6D6D6 #D4D4D4
 #D3D3D3 #D2B48C #D2691E #D1EEEE
 #D1D1D1 #D15FEE #D02090 #CFCFCF
 #CDCDC1 #CDCDB4 #CDCD00 #CDC9C9
 #CDC9A5 #CDC8B1 #CDC673 #CDC5BF
 #CDC1C5 #CDC0B0 #CDBE70 #CDBA96
 #CDB7B5 #CDB79E #CDB5CD #CDB38B
 #CDAF95 #CDAD00 #CDAA7D #CD9B9B
 #CD9B1D #CD96CD #CD950C #CD919E
 #CD8C95 #CD853F #CD8500 #CD8162
 #CD7054 #CD69C9 #CD6889 #CD6839
 #CD661D #CD6600 #CD6090 #CD5C5C
 #CD5B45 #CD5555 #CD4F39 #CD3700
 #CD3333 #CD3278 #CD2990 #CD2626
 #CD1076 #CD00CD #CD0000 #CCCCCC
 #CAFF70 #CAE1FF #C9C9C9 #C7C7C7
 #C71585 #C6E2FF #C67171 #C5C1AA
 #C4C4C4 #C2C2C2 #C1FFC1 #C1CDCD
 #C1CDC1 #C1C1C1 #C0FF3E #BFEFFF
 #BFBFBF #BF3EFF #BEBEBE #BDBDBD
 #BDB76B #BCEE68 #BCD2EE #BC8F8F
 #BBFFFF #BABABA #BA55D3 #B9D3EE
 #B8B8B8 #B8860B #B7B7B7 #B5B5B5
 #B4EEB4 #B4CDCD #B452CD #B3EE3A
 #B3B3B3 #B2DFEE #B23AEE #B22222
 #B0E2FF #B0E0E6 #B0C4DE #B0B0B0
 #B03060 #AEEEEE #ADFF2F #ADD8E6
 #ADADAD #ABABAB #AB82FF #AAAAAA
 #A9A9A9 #A8A8A8 #A6A6A6 #A52A2A
 #A4D3EE #A3A3A3 #A2CD5A #A2B5CD
 #A1A1A1 #A0522D #A020F0 #9FB6CD
 #9F79EE #9E9E9E #9C9C9C #9BCD9B
 #9B30FF #9AFF9A #9ACD32 #9AC0CD
 #9A32CD #999999 #9932CC #98FB98
 #98F5FF #97FFFF #96CDCD #969696
 #949494 #9400D3 #9370DB #919191
 #912CEE #90EE90 #8FBC8F #8F8F8F
 #8EE5EE #8E8E8E #8E8E38 #8E388E
 #8DEEEE #8DB6CD #8C8C8C #8B8B83
 #8B8B7A #8B8B00 #8B8989 #8B8970
 #8B8878 #8B8682 #8B864E #8B8386
 #8B8378 #8B814C #8B7E66 #8B7D7B
 #8B7D6B #8B7B8B #8B795E #8B7765
 #8B7500 #8B7355 #8B6969 #8B6914
 #8B668B #8B6508 #8B636C #8B5F65
 #8B5A2B #8B5A00 #8B5742 #8B4C39
 #8B4789 #8B475D #8B4726 #8B4513
 #8B4500 #8B3E2F #8B3A62 #8B3A3A
 #8B3626 #8B2500 #8B2323 #8B2252
 #8B1C62 #8B1A1A #8B0A50 #8B008B
 #8B0000 #8A8A8A #8A2BE2 #8968CD
 #87CEFF #87CEFA #87CEEB #878787
 #858585 #848484 #8470FF #838B8B
 #838B83 #836FFF #828282 #7FFFD4
 #7FFF00 #7F7F7F #7EC0EE #7D9EC0
 #7D7D7D #7D26CD #7CFC00 #7CCD7C
 #7B68EE #7AC5CD #7A8B8B #7A7A7A
 #7A67EE #7A378B #79CDCD #787878
 #778899 #76EEC6 #76EE00 #757575
 #737373 #71C671 #7171C6 #708090
 #707070 #6E8B3D #6E7B8B #6E6E6E
 #6CA6CD #6C7B8B #6B8E23 #6B6B6B
 #6A5ACD #698B69 #698B22 #696969
 #6959CD #68838B #68228B #66CDAA
 #66CD00 #668B8B #666666 #6495ED
 #63B8FF #636363 #616161 #607B8B
 #5F9EA0 #5E5E5E #5D478B #5CACEE
 #5C5C5C #5B5B5B #595959 #575757
 #556B2F #555555 #551A8B #54FF9F
 #548B54 #545454 #53868B #528B8B
 #525252 #515151 #4F94CD #4F4F4F
 #4EEE94 #4D4D4D #4B0082 #4A708B
 #4A4A4A #48D1CC #4876FF #483D8B
 #474747 #473C8B #4682B4 #458B74
 #458B00 #454545 #43CD80 #436EEE
 #424242 #4169E1 #40E0D0 #404040
 #3D3D3D #3CB371 #3B3B3B #3A5FCD
 #388E8E #383838 #36648B #363636
 #333333 #32CD32 #303030 #2F4F4F
 #2E8B57 #2E2E2E #2B2B2B #292929
 #282828 #27408B #262626 #242424
 #228B22 #218868 #212121 #20B2AA
 #1F1F1F #1E90FF #1E1E1E #1C86EE
 #1C1C1C #1A1A1A #191970 #1874CD
 #171717 #141414 #121212 #104E8B
 #0F0F0F #0D0D0D #0A0A0A #080808
 #050505 #030303 #00FFFF #00FF7F
 #00FF00 #00FA9A #00F5FF #00EEEE
 #00EE76 #00EE00 #00E5EE #00CED1
 #00CDCD #00CD66 #00CD00 #00C5CD
 #00BFFF #00B2EE #009ACD #008B8B
 #008B45 #008B00 #00868B #00688B
 #006400 #0000FF #0000EE #0000CD
 #0000AA #00008B #000080 #000000

 

 

颜色代码表2:

 

红色和粉红色,以及它们的16进制代码。
#990033#CC6699#FF6699#FF3366#993366#CC0066#CC0033#FF0066#FF0033..#CC3399..
#FF3399#FF9999#FF99CC#FF0099#CC3366#FF66CC#FF33CC#FFCCFF#FF99FF#FF00CC
紫红色,以及它们的16进制代码。
#FF66FF#CC33CC#CC00FF#FF33FF#CC99FF#9900CC#FF00FF#CC66FF#990099#CC0099
#CC33FF#CC99CC#990066#993399#CC66CC#CC00CC#663366   
蓝色,以及它们的16进制代码。
#660099#666FF#000CC#9933CC#666699#660066#333366#0066CC#9900FF#333399
#99CCFF#9933FF#330099#6699FF#9966CC#3300CC#003366#330033#3300FF#6699CC
#663399#3333FF#006699#6633CC#3333CC#3399CC#6600CC#0066FF#0099CC#9966FF
#0033FF#66CCFF#330066#3366FF#3399FF#6600FF#3366CC#003399#6633FF#000066
#0099FF#CCCCFF#000033#33CCFF#9999FF#0000FF#00CCFF#9999CC#000099#6666CC
#0033CC         
黄色、褐色、玫瑰色和橙色,以及它们的16进制代码。
#FFFFCC#FFCC00#CC99090#663300#FF6600#663333#CC6666#FF6666#FF0000#FFFF99
#FFCC66#FF9900#FF9966#CC3300#996666#FFCCCC#660000#FF3300#FF6666#FFCC33
#CC6600#FF6633#996633#CC9999#FF3333#990000#CC9966#FFFF33#CC9933#993300
#FF9933#330000#993333#CC3333#CC0000#FFCC99#FFFF00#996600#CC6633

 

 


绿色,以及它们的16进制代码。
#99FFFF#33CCCC#00CC99#99FF99#009966#33FF33#33FF00#99CC33#CCC33#66FFFF
#66CCCC#66FFCC#66FF66#009933#00CC33#66FF00#336600#33300#33FFFF#339999
#99FFCC#339933#33FF66#33CC33#99FF00#669900#666600#00FFFF#336666#00FF99
#99CC99#00FF66#66FF33#66CC00#99CC00#999933#00CCCC#006666#339966#66FF99
#CCFFCC#00FF00#00CC00#CCFF66#CCCC66#009999#003333#006633#33FF99#CCFF99
#66CC33#33CC00#CCFF33#666633#669999#00FFCC#336633#33CC66#99FF66#006600
#339900#CCFF00#999966#99CCCC#33FFCC#669966#00CC66#99FF33#003300#99CC66
#999900#CCCC99#CCFFFF#33CC99#66CC66#66CC99#00FF33#009900#669900#669933
#CCCC00         
白色、灰色和黑色,以及它们的16进制代码。
#FFFFF#CCCCCC#999999#666666#333333#000000

古典白色 :古典白色antiquewhite

浅绿色:浅绿色aqua 碧绿色:碧绿色aquamarine 天蓝色:天蓝色azure(汗。。。) 米色:米色beige 桔黄色:桔黄色bisque 黑色:黑色black 白杏色:白杏色blanchedalmond 蓝色:蓝色blue 蓝紫色:蓝紫色blueviolet 褐色:褐色brown 实木色:实木色burlywood 刺桧蓝色:刺桧蓝色cadetblue 亮黄绿色:亮黄绿色chartreuse 巧克力色:巧克力色chocolate 珊瑚色:珊瑚色coral 矢车菊色:矢车菊色cornflowerblue 谷丝色:谷丝色cornsilk 深红色:深红色crimson 蓝绿色:蓝绿色cyan 深蓝色:深蓝色darkblue 深青色:深青色darkcyan 深金杆色:深金杆色darkgoldenrod 深灰色:深灰色darkgray 深绿色:深绿色darkgreen 深黄褐色:深黄褐色darkkhaki 深洋红色:深洋红色darkmagenta 深橄榄绿色:深橄榄绿色darkolivegreen 深橙色:深橙色darkorange 深紫色:深紫色darkorchid 深红色:深红色darkred 深肉色:深肉色darksalmon 深海绿色:深海绿色darkseagreen 深暗灰蓝色:深暗灰蓝色darkslateblue 深暗蓝灰色:深暗蓝灰色darkslategray 深青绿色:深青绿色darkturquoise 深紫色:深紫色darkviolet 深粉色:深粉色deeppink 深天蓝色:深天蓝色deepskyblue 暗灰色:暗灰色dimgray 遮板蓝色:遮板蓝色dodgerblue 砖色:砖色firebrick 花白色:花白色floralwhite 葱绿色:葱绿色forestgreen 紫红色:紫红色fushcia 庚斯博罗灰色:庚斯博罗灰色gainsboro 幽灵白色:幽灵白色ghostwhite 金黄色:金黄色gold 金杆黄色:金杆黄色goldenrod 灰色:灰色gray 绿色:绿色green 绿黄色:绿黄色greenyellow 蜜汁色:蜜汁色honeydew 亮粉色:亮粉色hotpink 印第安红色:印第安红色indianred 靛青色:靛青色indigo 象牙色:象牙色ivory 黄褐色:黄褐色khaki 淡紫色:淡紫色lavender 浅紫红色:浅紫红色lavenderblush 草绿色:草绿色lawngreen 柠檬纱色:柠檬纱色lemonchiffon 浅蓝色:浅蓝色lightblue 浅珊瑚色:浅珊瑚色 lightcoral  浅金杆黄色:浅金杆黄色lightgoldenrodyellow 转载来自:[点击打开链接](http://blog.sina.com.cn/s/blog_7ed4baf90100sbn6.html)
';

前言

最后更新于:2022-04-01 19:47:11

> 原文出处:[Android学习笔记](http://blog.csdn.net/column/details/androidtome.html) 作者:[u012964281](http://blog.csdn.net/u012964281) **本系列文章经作者授权在看云整理发布,未经作者允许,请勿转载!** # Android学习笔记 > 关于Android学习过程中的一些记录和总结
';