Android Demo手机获取验证码

简介:        注册很多app或者网络账户的时候,经常需要手机获取验证码,来完成注册,那时年少,只是觉得手机获取验证码这件事儿很好玩,并没有关心太多,她是如何实现的,以及她背后的故事到底是什么样子的,现在小编接手的这个项目里面,就需要通过手机号进行注册,并且手机号发送相应的验证码,来完成注册,那么在一些应用app里面到底是如何实现点击按钮获取验证码,来完成注册这整个流程的呢?今天小编就以注册为例,和小伙伴们分享一下,如何通过手机号获取验证码来完成注册的一整套流程以及如何采用正则表达式来验证手机号码是否符合电信、移动、联通的规范。

       注册很多app或者网络账户的时候,经常需要手机获取验证码,来完成注册,那时年少,只是觉得手机获取验证码这件事儿很好玩,并没有关心太多,她是如何实现的,以及她背后的故事到底是什么样子的,现在小编接手的这个项目里面,就需要通过手机号进行注册,并且手机号发送相应的验证码,来完成注册,那么在一些应用app里面到底是如何实现点击按钮获取验证码,来完成注册这整个流程的呢?今天小编就以注册为例,和小伙伴们分享一下,如何通过手机号获取验证码来完成注册的一整套流程以及如何采用正则表达式来验证手机号码是否符合电信、移动、联通的规范。

       首先我们需要做的第一步就是ApiClient里面编写获取验证码的方法,具体代码如下:

/**
	 * 说明:获取验证码
	 * 作者:丁国华
	 * 时间:2015-8-27 下午5:47:36
	 */
	public static String getValidateCode(AppContext appContext,
			Map<String, Object> map) throws AppException {

		// 定义要访问的接口和要强转的实体
		String validateUrl = _MakeURL(URLs.VALIDATE_CODE_URL, map);
		ValidateCode validateCode = null;

		try {

			// 获取服务器端Json数据
			String json = http_get(appContext, validateUrl);

			// 解析为制定的实体对象
			validateCode = (ValidateCode) JSON.parseObject(json,
					ValidateCode.class);

		} catch (Exception e) {
			if (e instanceof AppException)
				throw (AppException) e;
			throw AppException.network(e);
		}

		// 返回验证码
		return validateCode.getCode();
	}

       第二步编写AppContent里面的接口方法,具体代码如下所示:

 

/**
	 * 说明:获取服务器验证码(不需要缓存)
	 * 作者:丁国华
	 * @date 2015-8-28 上午9:07:14
	 */
	public String getCode(Map<String, Object> map) throws AppException {

		String validateCode = "";

		// 如果网络可连接且解析无误返回正确的验证码,否则返回空字符串
		if (isNetworkConnected()) {
			try {
				validateCode = ApiClient.getValidateCode(this, map);
			} catch (AppException e) {
				if (validateCode == "") {
					throw e;
				}
			}
		}
		return validateCode;
	}
        第三步,在StringUtils里面编写验证号码是否是手机号的正则表达式,具体代码如下:

 

 /* 说明:移动:134、135、136、137、138、139、150、151、157(TD)、158、159、187、188 
	  * 联通:130、131、132、152、155、156、185、186
	  * 电信:133、153、180、189 
	  * 总结起来就是第一位必定为1,第二位必定为3或5或8,其他位置的可以为0-9 
	  * 验证号码 手机号 固话均可
	  * 作者:丁国华
	  * 2015年9月20日 13:52:35 
	  */
	 public static boolean isPhoneNumberValid(String phoneNumber) {
	 boolean isValid = false;

	 String expression = "((^(13|15|18)[0-9]{9}$)|(^0[1,2]{1}\\d{1}-?\\d{8}$)|(^0[3-9] {1}\\d{2}-?\\d{7,8}$)|(^0[1,2]{1}\\d{1}-?\\d{8}-(\\d{1,4})$)|(^0[3-9]{1}\\d{2}-? \\d{7,8}-(\\d{1,4})$))";
	 CharSequence inputStr = phoneNumber;

	 Pattern pattern = Pattern.compile(expression);

	 Matcher matcher = pattern.matcher(inputStr);

	 if (matcher.matches() ) {
	 isValid = true;
	 }

	 return isValid;

	 }
	
      第四步:编写xml里面的文件,具体代码如下所示:

<?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="match_parent"
    android:orientation="vertical" >

    <LinearLayout style="@style/top_title_style" >

        <Button
            android:id="@+id/register_back_login"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="5dp"
            android:background="@null"
            android:drawableLeft="@drawable/back"
            android:paddingLeft="5dp"
            android:text=" 登录"
            android:textColor="#FFFFFF"
            android:textSize="18sp" />

        <!-- 注册的布局 -->

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:layout_marginTop="2dp"
            android:layout_weight="1"
            android:gravity="center"
            android:paddingLeft="4dp"
            android:text="注册"
            android:textColor="#FFFFFF"
            android:textSize="20sp" />

        <!-- 注册的布局 -->

        <TextView
            android:id="@+id/nickname_confirm"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_marginTop="2dp"
            android:gravity="center"
            android:paddingLeft="60dp"
            android:paddingRight="10dp"
            android:textColor="#FFFFFF"
            android:textSize="20sp" />
    </LinearLayout>

    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="45dp"
        android:minHeight="50.0dip"
        android:paddingLeft="14.0dip"
        android:paddingRight="12.0dip" >

        <ImageView
            android:layout_width="23.0dip"
            android:layout_height="23.0dip"
            android:layout_centerVertical="true"
            android:src="@drawable/user_picture" />

        <EditText
            android:id="@+id/et_register_username_id"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="20dp"
            android:background="@null"
            android:hint="用户名/手机号"
            android:paddingLeft="15dip"
            android:paddingTop="8dp"
            android:textColorHint="#BEBEBE"
            android:textSize="20sp" />
    </RelativeLayout>

    <View style="@style/PersonalLine" />

    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="45dp"
        android:minHeight="50.0dip"
        android:paddingLeft="14.0dip"
        android:paddingRight="12.0dip" >

        <ImageView
            android:layout_width="23.0dip"
            android:layout_height="23.0dip"
            android:layout_centerVertical="true"
            android:src="@drawable/phone_picture" />

        <EditText
            android:id="@+id/et_register_code_id"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="20dp"
            android:background="@null"
            android:hint="请输入验证码"
            android:paddingLeft="15dip"
            android:paddingTop="8dp"
            android:textColorHint="#BEBEBE"
            android:textSize="20sp" />

        <Button
            android:id="@+id/bt_getcode_id"
            android:layout_width="120dp"
            android:layout_height="35dp"
            android:layout_marginLeft="200dp"
            android:layout_marginTop="5dp"
            android:background="@drawable/shape1"
            android:text="获取验证码"
            android:textColor="#FFFFFF"
            android:textSize="10sp" />
    </RelativeLayout>

    <View style="@style/PersonalLine" />

    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="45dp"
        android:minHeight="50.0dip"
        android:paddingLeft="14.0dip"
        android:paddingRight="12.0dip" >

        <ImageView
            android:layout_width="23.0dip"
            android:layout_height="23.0dip"
            android:layout_centerVertical="true"
            android:src="@drawable/lock" />

        <EditText
            android:id="@+id/et_register_password_id"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="20dp"
            android:background="@null"
            android:hint="请输入新密码"
            android:paddingLeft="15dip"
            android:paddingTop="8dp"
            android:textColorHint="#BEBEBE"
            android:textSize="20sp" />
    </RelativeLayout>

    <View style="@style/PersonalLine" />

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <!-- 小对勾的布局 -->

        <CheckBox
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="10dp"
            android:layout_marginLeft="-10dp"
            android:scaleX="0.8"
            android:scaleY="0.8" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:text="我同意"
            android:textSize="18sp" />

        <TextView
            android:id="@+id/user_protocol"
            android:layout_width="200dp"
            android:layout_height="match_parent"
            android:layout_gravity="center_vertical"
            android:layout_marginLeft="5dp"
            android:gravity="center"
            android:text="用户协议及隐私条款"
            android:textColor="#FE8B4A"
            android:textSize="18sp" />
    </LinearLayout>

    <Button
        android:id="@+id/bt_register_id"
        android:layout_width="245dp"
        android:layout_height="45dp"
        android:layout_gravity="center_horizontal"
        android:layout_marginBottom="14dp"
        android:layout_marginLeft="15dp"
        android:layout_marginRight="15dp"
        android:layout_marginTop="5dp"
        android:background="@drawable/shape2"
        android:gravity="center"
        android:text="注  册"
        android:textColor="#FFFFFF"
        android:textSize="15sp" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="80dp"
        android:paddingTop="5dp"
        android:text="您也可以直接登录"
        android:textColor="#BEBEBE"
        android:textSize="20sp" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:baselineAligned="false"
        android:gravity="center"
        android:orientation="horizontal" >

        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center"
            android:orientation="vertical" >

            <Button
                android:layout_width="60dp"
                android:layout_height="60dp"
                android:background="@drawable/weixin_login" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="微信登录"
                android:textColor="#BEBEBE"
                android:textSize="20sp" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center"
            android:orientation="vertical" >

            <Button
                android:layout_width="60dp"
                android:layout_height="60dp"
                android:background="@drawable/weibo_login" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="微博登录"
                android:textColor="#BEBEBE"
                android:textSize="20sp" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center"
            android:orientation="vertical" >

            <Button
                android:layout_width="60dp"
                android:layout_height="60dp"
                android:background="@drawable/qq_login" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="QQ登录"
                android:textColor="#BEBEBE"
                android:textSize="20sp" />
        </LinearLayout>
    </LinearLayout>

</LinearLayout>
        第五步:编写java类RegisterActivity里面的代码,具体如下所示:

package com.jczb.car.ui;

import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import com.jczb.car.AppContext;
import com.jczb.car.AppException;
import com.jczb.car.R;
import com.jczb.car.common.StringUtils;

/**
 * 说明:注册功能页面 我们实现了取消线程的机制,从而保证它不会泄露 onDestroy()常常被用来在Activity推出前取消线程 
 * 作者: 吴利昌
 * 时间: 2015-9-3上午9:19:15
 */
public class RegisterActivity extends Activity implements OnClickListener {
   
       // 声明用到的页面控件
	private EditText etRegisterName;
	private EditText etCode;
	private EditText etPassword;
	private Button btCode;
	private Button btRegister;
	private TextView tvUserProtocol;
	private Button btRegisterLoginBack;

	// 定义变量
	private String userName;
	private String passWord;
	
	public boolean isChange = false;
	private boolean tag = true;
	private int i = 60;
	Thread thread = null;
	
	/**客户端输入的验证码*/
	private String valicationCode;
	
	/**服务器端获取的验证码*/
	private static String serverValicationCode;

	/** 注册时所带的参数 */
	private Map<String, Object> registerParams = new HashMap<String, Object>();

	/** 获取验证码时所带的参数 */
	private Map<String, Object> codeParams = new HashMap<String, Object>();

	/** 注册是否成功 */
	private String regisgerStatus;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		setContentView(R.layout.register);
		initView();		
	}
	

	/**
	 * 说明:初始化页面控件和事件
	 * 作者: 吴利昌
	 * 时间: 2015-9-3 上午9:23:42
	 */
	public void initView() {
		// 初始化控件
		etRegisterName = (EditText) findViewById(R.id.et_register_username_id);
		etCode = (EditText) findViewById(R.id.et_register_code_id);
		etPassword = (EditText) findViewById(R.id.et_register_password_id);
		btCode = (Button) findViewById(R.id.bt_getcode_id);
		btRegister = (Button) findViewById(R.id.bt_register_id);
		tvUserProtocol=(TextView)findViewById(R.id.user_protocol);
		btRegisterLoginBack=(Button)findViewById(R.id.register_back_login);
		
		// 初始化监听事件
		btCode.setOnClickListener(this);
		btRegister.setOnClickListener(this);
		tvUserProtocol.setOnClickListener(this);
		btRegisterLoginBack.setOnClickListener(this);
	}
	
	private boolean isvalidate() {
		// TODO Auto-generated method stub
		// 获取控件输入的值
		String userName = etRegisterName.getText().toString().trim();

		
		if (StringUtils.isEmpty(userName)) {
			Toast.makeText(this, "手机号不能为空", Toast.LENGTH_SHORT).show();
			return false;
		}
		if (!StringUtils.isPhoneNumberValid(userName)) {
			Toast.makeText(this, "手机号有误", Toast.LENGTH_SHORT).show();
			return false;
		}
		return true;

	}

	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.bt_getcode_id:
			if(!isvalidate())
				break;
				
			btCode.setText("获取验证码");
			btCode.setClickable(true);
			isChange = true;
			changeBtnGetCode();
			getValidateCode();
			break;
		case R.id.bt_register_id:
			register();
			
			break;
		case R.id.user_protocol:
			Intent intentUserProtocol = new Intent(this,UserProtocolActivity.class);
		    startActivity(intentUserProtocol);
			break;
		case R.id.register_back_login:
			this.finish();
			break;
		
		default:
			break;
		}

	}
	
	private void changeBtnGetCode() {
		thread = new Thread() {
			@Override
			public void run() {
				if (tag) {
					while (i > 0) {
						i--;
						if (RegisterActivity.this == null) {
							break;
						}
						
						RegisterActivity.this
								.runOnUiThread(new Runnable() {
									@Override
									public void run() {
										btCode.setText("获取验证码("
												+ i + ")");
										btCode
												.setClickable(false);
									}
								});
						try {
							Thread.sleep(1000);
						} catch (InterruptedException e) {
							throw new RuntimeException(e);
						}
					}
					tag = false;
				}
				i = 60;
				tag = true;
				if (RegisterActivity.this != null) {
					RegisterActivity.this.runOnUiThread(new Runnable() {
						@Override
						public void run() {
							btCode.setText("获取验证码");
							btCode.setClickable(true);
						}
					});
				}
			};
		};
		thread.start();
	}

	/**
	 * 说明:获取验证码
	 * 
	 * 作者: 吴利昌
	 * 时间: 2015-9-3 下午3:26:55
	 */
	public boolean getValidateCode() {
		
		String name = etRegisterName.getText().toString().trim();
		String code = etCode.getText().toString().trim();
		if (name.equals("")) {
			Toast.makeText(this, "请输入用户名或手机号!", Toast.LENGTH_SHORT).show();
			return false;
		}else {
			userName = name;
			valicationCode = code;
			Thread codeThread = new Thread(codeRunnable);
			codeThread.start();
		}
		return true;
	}

	/**
	 * 说明:注册
	 * 
	 * 作者: 吴利昌
	 * 时间: 2015-9-3 下午3:27:23
	 */
	public void register() {
		// 1.首先判断输入的值是否有效
		// 2.然后判断输入的验证码是否有效(防止没有点击获取验证码自己填的错误验证码)
		// 3.最后注册
		if (isValid()) {
			
			if (valicationCode.equals(serverValicationCode)) {
				Thread thread = new Thread(sRunnable);
				thread.start();
			}else {
				Toast.makeText(this, "输入的验证码不正确!", Toast.LENGTH_SHORT).show();
			}
			
		}
	}
	
	//--------------------------------获取验证码线程处理过程---开始-----------------------------
	/**
	 * 自定义一个静态的具有弱引用的Handler,解决内存泄漏的问题,本handler用来获取验证码
	 */
	private static class CodeHandler extends Handler {
		// 持有对本外部类的弱引用
		private final WeakReference<RegisterActivity> mActivity;

		public CodeHandler(RegisterActivity activity) {
			mActivity = new WeakReference<RegisterActivity>(activity);
		}

		@Override
		public void handleMessage(Message msg) {
			
			// 获取上下文对象
			RegisterActivity activity = mActivity.get();
			if (activity != null) {
				switch (msg.what) {
				case 1:
					serverValicationCode = (String)msg.obj;
					//activity.etCode.setText(serverValicationCode);
					break;
				case -1:
					Toast.makeText(activity, "获取验证码失败!", Toast.LENGTH_SHORT).show();
					break;
				case 0:
					Toast.makeText(activity, "哎呀,出错啦..", Toast.LENGTH_SHORT).show();
					break;
				default:
					break;
				}
			}
		}
	}
	
	/**实例化自定义的handler*/
	private final CodeHandler codeHandler = new CodeHandler(this);
	
	private String serverCode=null;
	
	
	/**定义获取验证码的子线程*/
	private Runnable codeRunnable = new Runnable() {
		@Override
		public void run() {
			Message msg = new Message();
			Map<String, Object> map = new HashMap<String, Object>();
			map.put("jbPhone", userName);
			// 获取全局对象Application
			AppContext appContext = (AppContext) getApplication();

			try {
				// 获取服务器数据
				serverValicationCode = appContext.getCode(map);

				// 返回true则将消息的what值为1,为false则what为-1,异常为0
				if (serverValicationCode.equals("")) {
					msg.what = -1;
				} else {
					msg.what = 1;
					msg.obj = serverValicationCode;
				}

			} catch (AppException e) {
				msg.what = 0;
				e.printStackTrace();
			}
			codeHandler.sendMessage(msg);
		}
	};
	
	//--------------------------------获取验证码线程处理过程----完成------------------------------

	//--------------------------------注册线程处理过程--开始----------------------------------
	/**
	 * 自定义一个静态的具有弱引用的Handler,解决内存泄漏的问题,注册使用
	 */
	private static class MyHandler extends Handler {
		// 持有对本外部类的弱引用
		private final WeakReference<RegisterActivity> mActivity;

		public MyHandler(RegisterActivity activity) {
			mActivity = new WeakReference<RegisterActivity>(activity);
		}

		@Override
		public void handleMessage(Message msg) {
			
			// 获取上下文对象
			RegisterActivity activity = mActivity.get();
			if (activity != null) {
				switch (msg.what) {
				case 1:
					Toast.makeText(activity, "注册成功!", Toast.LENGTH_SHORT).show();
					activity.finish();
					break;
				case -1:
					Toast.makeText(activity, "注册失败!", Toast.LENGTH_SHORT).show();
					break;
				case -2:
					Toast.makeText(activity, "该号已经注册!", Toast.LENGTH_SHORT).show();
					break;
				case 0:
					Toast.makeText(activity, "哎呀,出错啦..", Toast.LENGTH_SHORT).show();
					break;
				default:
					break;
				}
			}
		}
	}
	
	/**实例化自定义的handler*/
	private final MyHandler mHandler = new MyHandler(this);
	
	/**自定义子线程*/
	private Runnable sRunnable = new Runnable() {
		@Override
		public void run() {
			Message msg = new Message();

			// 获取全局对象Application
			AppContext appContext = (AppContext) getApplication();

			try {
				// 获取服务器数据
				regisgerStatus = appContext.register(registerParams);

				// 返回true则将消息的what值为1,为false则what为-1,异常为0
				if (regisgerStatus.equals("true")) {
					msg.what = 1;
					
					msg.obj = regisgerStatus;
				} else if(regisgerStatus.equals("1")){
					msg.what = -2;
					
				}else if(regisgerStatus.equals("false")){
					msg.what = -1;}

			} catch (AppException e) {
				msg.what = 0;
				e.printStackTrace();
			}
			mHandler.sendMessage(msg);
		}
	};

	//--------------------------------注册线程处理过程---完成-----------------------------------

	/**
	 * 说明:注册之前判断数据是否为空
	 * 
	 * @return
	 * 作者: 吴利昌
	 * 时间: 2015-9-3 下午3:29:04
	 */
	public boolean isValid() {

		userName = etRegisterName.getText().toString().trim();
		valicationCode = etCode.getText().toString().trim();
		passWord = etPassword.getText().toString().trim();

		
		
		if (userName.equals("")) {
			Toast.makeText(this, "用户名不能为空!", Toast.LENGTH_SHORT).show();
			return false;
		}

		if (valicationCode.equals("")) {
			Toast.makeText(this, "验证码不能为空!", Toast.LENGTH_SHORT).show();
			return false;
		}
		
		if(!serverValicationCode.equals(valicationCode))
		 {
			Toast.makeText(this, "验证码错误", Toast.LENGTH_SHORT).show();
			return false;
		}

		if (passWord.equals("")) {
			Toast.makeText(this, "密码不能为空!", Toast.LENGTH_SHORT).show();
			return false;
		} else if (passWord.length() < 6) {
			Toast.makeText(this, "密码至少6位!", Toast.LENGTH_SHORT).show();
			return false;
		}

		registerParams.put("username", userName);
		registerParams.put("psd", passWord);

		return true;
	}
}

       最后,我们来运行一下,看看我们的效果,由于小编的genymotion不知道为什么不能运行了,所以委屈小伙伴们一下,看不了动态图片了,不过并不影响,我们首先用一个号码好注册一下,如下图所示:

       

        看一下手机收到的验证码:

         

         最后来看一下,我们的注册:

         

       小编寄语:该博文,小编主要简单的介绍了如何通过手机获取验证码来完成注册的功能,以及如何利用正则表达式来验证码手机号码是否符合移动、联通、电信。还是那句话对于小编来说,既是挑战更是机遇,因为知识都是相通的,再者来说,在小编的程序人生中,留下最珍贵的记忆,虽然以后小编不一定从事安卓这个行业,代码世界里,很多种事,有的甜蜜,有的温馨,有的婉转成歌,有的绵延不息,在这些故事里,我们唯一的共通之处就是,某年,某月,某个波澜不惊的日子里,曾经很爱很爱你!爱你--这段实习的日子里,安卓带给小编的种种的惊喜。    

目录
相关文章
|
7月前
|
XML API Android开发
码农之重学安卓:利用androidx.preference 快速创建一、二级设置菜单(demo)
本文介绍了如何使用androidx.preference库快速创建具有一级和二级菜单的Android设置界面的步骤和示例代码。
215 1
码农之重学安卓:利用androidx.preference 快速创建一、二级设置菜单(demo)
|
2月前
|
缓存 前端开发 IDE
【06】flutter完成注册页面-密码登录-手机短信验证-找回密码相关页面-并且实现静态跳转打包demo做演示-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【06】flutter完成注册页面-密码登录-手机短信验证-找回密码相关页面-并且实现静态跳转打包demo做演示-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
38 0
【06】flutter完成注册页面-密码登录-手机短信验证-找回密码相关页面-并且实现静态跳转打包demo做演示-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
|
7月前
|
JavaScript NoSQL Redis
Vue中实现修改邮箱、手机号等流程的大致过程、验证码由后端的redis生成验证(版本1.0)
这篇文章记录了在Vue中实现修改手机号和邮箱的大致流程,包括使用过滤器部分隐藏展示的手机号和邮箱,以及通过点击触发路由跳转的便捷方式。文章还描述了旧号码和新号码验证的界面实现,其中验证码由后端生成并通过弹窗展示给用户,未来可以接入真正的手机验证码接口。此外,还提供了修改邮箱的页面效果截图,并强调了学习是一个永无止境的过程。
Vue中实现修改邮箱、手机号等流程的大致过程、验证码由后端的redis生成验证(版本1.0)
|
4月前
|
Android开发 数据安全/隐私保护 虚拟化
安卓手机远程连接登录Windows服务器教程
安卓手机远程连接登录Windows服务器教程
647 4
|
5月前
|
Ubuntu Linux Android开发
termux+anlinux+Rvnc viewer来使安卓手机(平板)变成linux服务器
本文介绍了如何在Android设备上安装Termux和AnLinux,并通过这些工具运行Ubuntu系统和桌面环境。
547 2
termux+anlinux+Rvnc viewer来使安卓手机(平板)变成linux服务器
|
4月前
|
安全 搜索推荐 Android开发
Android vs. iOS:解锁智能手机操作系统的奥秘####
【10月更文挑战第21天】 在当今这个数字化时代,智能手机已成为我们生活中不可或缺的伙伴。本文旨在深入浅出地探讨两大主流操作系统——Android与iOS的核心差异、优势及未来趋势,帮助读者更好地理解这两个平台背后的技术哲学和用户体验设计。通过对比分析,揭示它们如何塑造了我们的数字生活方式,并展望未来可能的发展路径。无论您是技术爱好者还是普通用户,这篇文章都将带您走进一个充满创新与可能性的移动世界。 ####
166 3
|
6月前
|
Java Maven 开发工具
第一个安卓项目 | 中国象棋demo学习
本文是作者关于其第一个安卓项目——中国象棋demo的学习记录,展示了demo的运行结果、爬坑记录以及参考资料,包括解决Android Studio和maven相关问题的方法。
第一个安卓项目 | 中国象棋demo学习
|
5月前
|
Web App开发 Android开发
利用firefox调试安卓手机端web
该教程详细介绍如何通过Firefox浏览器实现手机与电脑的远程调试。手机端需安装最新版Firefox,并按指定步骤设置完成;电脑端则需安装15版及以上Firefox。设置完成后,通过工具栏中的“远程调试”选项,输入手机IP地址即可连接。连接确认后,即可使用电脑端Firefox调试器调试手机上的Web信息。注意,调试前手机需提前打开目标网页。
197 2
|
5月前
|
Android开发 iOS开发 UED
安卓与iOS的较量:谁才是智能手机市场的王者?
本文将深入探讨安卓和iOS两大智能手机操作系统之间的竞争关系,分析它们各自的优势和劣势。通过对比两者在市场份额、用户体验、应用生态等方面的表现,我们将揭示出谁才是真正的市场领导者。无论你是安卓粉丝还是iOS忠实用户,这篇文章都将为你提供一些有趣的观点和见解。
|
7月前
|
Web App开发 Android开发
FFmpeg开发笔记(四十六)利用SRT协议构建手机APP的直播Demo
实时数据传输在互联网中至关重要,不仅支持即时通讯如QQ、微信的文字与图片传输,还包括音视频通信。一对一通信常采用WebRTC技术,如《Android Studio开发实战》中的App集成示例;而一对多的在线直播则需部署独立的流媒体服务器,使用如SRT等协议。SRT因其优越的直播质量正逐渐成为主流。本文档概述了SRT协议的使用,包括通过OBS Studio和SRT Streamer进行SRT直播推流的方法,并展示了推流与拉流的成功实例。更多细节参见《FFmpeg开发实战》一书。
108 1
FFmpeg开发笔记(四十六)利用SRT协议构建手机APP的直播Demo

热门文章

最新文章

  • 1
    Android历史版本与APK文件结构
  • 2
    【01】噩梦终结flutter配安卓android鸿蒙harmonyOS 以及next调试环境配鸿蒙和ios真机调试环境-flutter项目安卓环境配置-gradle-agp-ndkVersion模拟器运行真机测试环境-本地环境搭建-如何快速搭建android本地运行环境-优雅草卓伊凡-很多人在这步就被难倒了
  • 3
    【03】仿站技术之python技术,看完学会再也不用去购买收费工具了-修改整体页面做好安卓下载发给客户-并且开始提交网站公安备案-作为APP下载落地页文娱产品一定要备案-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
  • 4
    【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
  • 5
    【03】微信支付商户申请下户到配置完整流程-微信开放平台创建APP应用-填写上传基础资料-生成安卓证书-获取Apk签名-申请+配置完整流程-优雅草卓伊凡
  • 6
    【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
  • 7
    Cellebrite UFED 4PC 7.71 (Windows) - Android 和 iOS 移动设备取证软件
  • 8
    escrcpy:【技术党必看】Android开发,Escrcpy 让你无线投屏新体验!图形界面掌控 Android,30-120fps 超流畅!🔥
  • 9
    Android实战经验之Kotlin中快速实现MVI架构
  • 10
    即时通讯安全篇(一):正确地理解和使用Android端加密算法
  • 1
    算法系统协同优化,vivo与港中文推出BlueLM-V-3B,手机秒变多模态AI专家
    36
  • 2
    【02】整体试验思路,在这之前我们发现sec_uid,sec_uid是什么和uid的关系又是什么?相互如何转换?python开发之理论研究试验,如何通过抖音视频下方的用户的UID获得抖音用户的手机号-本系列文章仅供学习研究-禁止用于任何商业用途-仅供学习交流-优雅草卓伊凡
    58
  • 3
    【03】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-测试hello word效果-虚拟华为手机真机环境调试-为DevEco Studio编译器安装中文插件-测试写一个滑动块效果-介绍诸如ohos.ui等依赖库-全过程实战项目分享-从零开发到上线-优雅草卓伊凡
    40
  • 4
    【01】整体试验思路,如何在有UID的情况下获得用户手机号信息,python开发之理论研究试验,如何通过抖音视频下方的用户的UID获得抖音用户的手机号-本系列文章仅供学习研究-禁止用于任何商业用途-仅供学习交流-优雅草卓伊凡
    145
  • 5
    美团面试:手机扫描PC二维码登录,底层原理和完整流程是什么?
    125
  • 6
    MNN-LLM App:在手机上离线运行大模型,阿里巴巴开源基于 MNN-LLM 框架开发的手机 AI 助手应用
    1610
  • 7
    【06】flutter完成注册页面-密码登录-手机短信验证-找回密码相关页面-并且实现静态跳转打包demo做演示-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
    38
  • 8
    ClKLog支持手机端查询统计数据啦!
    47
  • 9
    OmAgent:轻松构建在终端设备上运行的 AI 应用,赋能手机、穿戴设备、摄像头等多种设备
    296
  • 10
    Mobile-Agent:通过视觉感知实现自动化手机操作,支持多应用跨平台
    542