精华内容
下载资源
问答
  • 模拟短信APP

    2015-12-18 23:03:43
    模拟短信 酒桌脱身,伪装10086 95533装X
  • 主要介绍了Android 如何使用短信链接打开APP,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • FeiYu 基于Android的快递员短信助手APP,方便快递员快捷发送短信。降低短信成本,快捷方便。
  • 原理:安卓手机APP,通过APP获取到手机短信,然后提交到指定的api接口,并显示返回结果,支持php、java等接口。支持获取通知类、验证码短信
  • QKSMS is an open source replacement to the stock messaging app on Android. It is currently available on the Google Play Store and on F-Droid Reporting bugs A great bug report contains a description ...
  • 重开一篇,完整讲述我这个半吊子的android 入门人员是怎么做出一个可以定时启动并且发送短信,读取回信里面的密码 这个功能的app 至于我为什么要做这个功能,可以看上一篇文章。主要是大学里面宽带密码...

    接上一篇:android 发送短信sendTextMessage()真机运行报错,退出,在已申请SEND_SMS权限的情况下Android send SMS not working uid 。。。

    重开一篇,完整讲述我这个半吊子的android 入门人员是怎么做出一个可以定时启动并且发送短信,读取回信里面的密码 这个功能的app 至于我为什么要做这个功能,可以看上一篇文章。主要是大学里面宽带密码定期更新手动去获取太麻烦~~

    得先放出运行效果视屏才行,如下:只是点击了发送按钮,就会做到自动发送、接收、提取短信收到的密码,更能够在29个小时后自动启动。

    有了上面的gif 好解释多了, 不能放视屏这个很头大。。视屏上去截取gif 还不能超过5M。。。我忍。。

    权限:

    <uses-permission android:name="android.permission.SEND_SMS" />
        <uses-permission android:name="android.permission.READ_PHONE_STATE" />
        <uses-permission android:name="android.permission.READ_SMS" />
        <uses-permission android:name="android.permission.RECEIVE_SMS" />

    其中  SEND_SMS、 READ_SMS 、RECEIVE_SMS 为危险权限,android6.0之后要动态申请,这个一开始也是入坑吃了亏。。

    动态申请权限方法:

    多个权限一起申请

    askPermissions();//        运行时权限 (动态权限申请)
            if(!permissionList.isEmpty()){
                String[] permissions = permissionList.toArray(new String[permissionList.size()]);//list-->String
                ActivityCompat.requestPermissions(MainActivity.this,permissions,1);
            }

    askPermissions();

    public void askPermissions(){
            if(ContextCompat.checkSelfPermission(MainActivity.this,Manifest.permission.SEND_SMS)!=
                    PackageManager.PERMISSION_GRANTED){
                permissionList.add(Manifest.permission.SEND_SMS);
            }
            if(ContextCompat.checkSelfPermission(MainActivity.this,Manifest.permission.READ_SMS)!=
                    PackageManager.PERMISSION_GRANTED){
                permissionList.add(Manifest.permission.READ_SMS);
            }
            if(ContextCompat.checkSelfPermission(MainActivity.this,Manifest.permission.RECEIVE_SMS)!=
                    PackageManager.PERMISSION_GRANTED){
                permissionList.add(Manifest.permission.RECEIVE_SMS);
            }
            //多的同样加进去
        }

    先大致说一下这个App的内部组成构建

    不要嫌弃我字丑的一张思路图:

    没错,我就是写字写的不好报的计算机系,我去,这个决定看起来太英明了。。。

    其中右上角 程序执行到MainActivity之前打了 “x”叉叉, 因为我这个程序是想要让他自动自动的,然后按照原来的循序下去就不能在此自动启动这个MainActivity了 ,所以就加了一个rebootBroadcaseReceiver 这个广播接收器,也就是绿色箭头指向的程序块,让他接受来自sendMessageService发送的广播,继而再通过startActivity的方法启动MainActivity,而且这个rebootBroadcaseReceiver必须是静态注册的,整个程序中还有一个SmsReceiver 也是通过静态注册的,道理很简单,这个程序要能够自动启动主界面(MainActivity),那时候主页面是没有的,MainActivity是没有运行的,那么广播接收器就不可以在MainActivity里面动态注册。突然发现讲的有好多,,,先来讲各个组件 及其功能

    0、Send按钮 按着思路图说下去吧,这个send 就是 gif里的发送按钮,点击之后是启动一个后台服务——SendMessageService

    1、sendMessageService 这个服务是利用了 android 的Alarm机制,这个app能自动定时启动(不关机前提)的功能就全靠它了,我要一言不合放代码了

    package com.example.getpassword;
    
    import android.app.AlarmManager;
    import android.app.PendingIntent;
    import android.app.Service;
    import android.content.ComponentName;
    import android.content.Intent;
    import android.content.SharedPreferences;
    import android.os.IBinder;
    import android.preference.PreferenceManager;
    import android.util.Log;
    
    public class sendMessageService extends Service {
        public sendMessageService() {
        }
        private String TAG = "sendMessageService";
        public static Boolean continueSend;
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            Log.d(TAG, "weimeng 启动了服务发送短信");
    
    
    
    
            continueSend = getSharedPreferences("data",MODE_PRIVATE).
                    getBoolean("ContinueSend",true);
    //                sharedPreference在一个app里是共享的
            Log.d(TAG, "weimeng 布尔变量continueSend = "+continueSend);
    
            //判断是否继续发送
            if(continueSend){
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        //MainActivity.sendMessage(MainActivity.destinationAddress,MainActivity.MESSAGE);
                        //改用广播,上面那个方法牵扯到MainActivity的好多属性,不能直接来用
                        Intent mybroadcastIntent = new Intent();
                        mybroadcastIntent.setAction(MainActivity.rebootBroadcast);
                        //1 包名 2 接收器类名
                        mybroadcastIntent.setComponent(new ComponentName("com.example.getpassword",
                                "com.example.getpassword.rebootBroadcastReceiver"));//android8.0要设置的
                        sendBroadcast(mybroadcastIntent);//发送一个广播
                    }
                }).start();
                AlarmManager manager = (AlarmManager) getSystemService(ALARM_SERVICE);
                int aDayMore = 29*60*60*1000;//一天又多个小时
    //            int aMinute = 60*1000;//测试用
                long triggerAtTime = System.currentTimeMillis()+aDayMore;
                Intent i = new Intent(this,sendMessageService.class);//这里搞错了,弄了两天
                PendingIntent pi = PendingIntent.getService(this,0,i,0);
                manager.set(AlarmManager.RTC_WAKEUP,triggerAtTime,pi);
    
                Log.d(TAG, "onStartCommand: 发送成功");
            }
    
            stopSelf();
            return super.onStartCommand(intent, flags, startId);
        }
    
        @Override
        public void onCreate() {
    
            super.onCreate();
    
        }
        @Override
        public IBinder onBind(Intent intent) {
                // TODO: Return the communication channel to the service.
                return null;
        }
    
        @Override
        public void onDestroy() {
    //        stopSelf();
            super.onDestroy();
        }
    }
    

    就是利用AlarmManager 设置模式、一个 PendingIntent 、时间,就可以过这么多时间启动这个服务了。,RTC_WAKE这个模式是可以在手机待机黑屏的情况下手机还能使用cpu的意思,就是还能跑,另外加了一个continueSend这个flag变量控制继不继续自动发送功能。

    你们还注意到了,这个onstartCommand里面还发了一个广播,即这几行

    Intent mybroadcastIntent = new Intent();
                        mybroadcastIntent.setAction(MainActivity.rebootBroadcast);
                        //1 包名 2 接收器类名
                        mybroadcastIntent.setComponent(new ComponentName("com.example.getpassword",
                                "com.example.getpassword.rebootBroadcastReceiver"));//android8.0要设置的
                        sendBroadcast(mybroadcastIntent);//发送一个广播

    有讲到很多,不得不忽略一些细节了,比如这个setComponent 好像是android8.0之后自定义的广播必须要加的一行代码。

    setAction中定义的 MainActivity.rebootBroadcast 是这个: 

    
        public static final String rebootBroadcast = "action.rebootActivity";

    自己定义的一个广播罢了

    这个广播发出去,然后一个静态的广播接收器 rebootBroadcastReceiver接收他,然后再startActivity 的方式再转到MainActivity

    package com.example.getpassword;
    
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    
    public class rebootBroadcastReceiver extends BroadcastReceiver {
    
        @Override
        public void onReceive(Context context, Intent intent) {
    
            Intent intentToStartMainActivity = new Intent(context,MainActivity.class);
            intentToStartMainActivity.addFlags(intent.FLAG_ACTIVITY_NEW_TASK);
            intentToStartMainActivity.putExtra("name","rebootIntent");
            context.startActivity(intentToStartMainActivity);//启动MainActivity
        }
    }

    这里广播接收器里的onReceive方法里怎么用Intent启动Activity要加一个 

    .addFlags(intent.FLAG_ACTIVITY_NEW_TASK);

    方法,这个高版本的android系统要有的,这个也是网上查的,可以自行科普。 

    有人可能会问,为什么要传给一个广播接收器 rebootBroadcastReceiver 而不是直接在MainActivity里面动态注册一个广播接收器,像这样: 有一个动态的在MainActivity注册 广播接收器接受他, 接收到了,会调用MainActivity里的sendMessage功能,这样 短信就真的发送出去了~~这不是很好?  

    事实上我也这么做过,可这样下一次就自动启动不了了呀MainActivity必须要在活着的时候才有用,关闭退出之后我怎么再接收到SendMessageService发来的广播? 只有一个 死了还能接收广播的 静态注册的广播接收器 接收到了这个广播通过这个广播接收器作为中介,再用一个Intent 到MainActivity.class 才能让这个 App “复活” 

    这篇文章的脊髓都在上面的几个字里了, 另外MainActivity 不能设置成 singleTask 或者其他,这个我也不知道为什么,设置之后这个 “复活” 不过来。。

    下面在rebootBroadcastReceiver 运行

    context.startActivity(intentToStartMainActivity);//启动MainActivity

    之后 接收到Intent 的代码:  

    public static final String destinationAddress = "106593005";
        public static final String MESSAGE = "mm";
    Intent rebootIntent = getIntent();
            String name = rebootIntent.getStringExtra("name");
            if(name!=null&&name.equals("rebootIntent")){//短路机制,前一个条件不满足自动跳过if
                Log.d(TAG, "收到重启广播 的 命令并已重启,将发送短信");
                sendMessage(destinationAddress,MESSAGE);
            }
            else{
                Log.d(TAG,"没有收到rebootIntent");
            }

    sendMessage :

     

    /*
         *调用系统短信接口发送短信
         */
        public static void sendMessage(String phoneNumber, String message) {
            SmsManager smsManager = SmsManager.getDefault();
            List<String> divideContents = smsManager.divideMessage(message);
            for (String text : divideContents) {
                smsManager.sendTextMessage(phoneNumber, null, text, MainActivity.sentPI, MainActivity.deliverPI);
            }
        }

    这个号码,这个mm 什么意思?

    好了,从按下按钮 -》启动服务-》服务里发送广播-》广播里启动MainActivity-》MainActivity里面发送短信,

    绕了一圈,终于把短信发出去了,好像很麻烦,但是你忽略了什么? 那个红色标志的环节!——他会过一段时间自行启动的呀!

    这样你按过按钮之后,一段时间后重复  服务-》服务里发送广播-》广播里启动MainActivity-》MainActivity里面发送短信

                                        一段时间后再重复  服务-》服务里发送广播-》广播里启动MainActivity-》MainActivity里面发送短信

                                                                     。

                                                                     。

                                                                     。

                                      不就 一直下去了吗,闪讯密码周期是28小时,所以我给这时间设置了29小时,不是挺好,哈哈哈。。

     

    MainActivity 其他功能自然不必多说,所有UI控件 、动态的一溜儿广播接收器,通过手机接口发送短信的方法函数、有关按键操作的事件。。。

     

    2、SmsReceiver: 这个是手机接收到短信后,会发送一条广播,Manifest.xml 里面定义如下,可见系统会发送一条   

    android.provider.Telephony.SMS_RECEIVED 的广播,我们只要注册一个针对这个广播的广播接收器就行
    <receiver
                android:name=".SmsReceiver"
                android:enabled="true"
                android:exported="true">
                <intent-filter android:priority="999">
                    <action android:name="android.provider.Telephony.SMS_RECEIVED" />
                </intent-filter>
            </receiver>

    SmsReceiver代码如下:

    package com.example.getpassword;
    
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    import android.os.Bundle;
    import android.telephony.SmsMessage;
    import android.util.Log;
    import android.widget.Toast;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    public class SmsReceiver extends BroadcastReceiver {
        private String TAG = "SmsReceiver";
        MainActivity activity;
        private static final String queryString = "尊敬的";//"2018";
        private static final String phoneNumber = "106593005";//"10086";
        @Override
        public void onReceive(Context context, Intent intent) {
    
    //        Toast.makeText( "222我接收到了", Toast.LENGTH_SHORT).show();
            Log.d(TAG, "onReceive: 广播接收器接收到了");
            Bundle bundle = intent.getExtras();
            SmsMessage msg;
            if(null!=bundle)
            {
                Object[] smsObj = (Object[]) bundle.get("pdus");
                for (Object object : smsObj) {
                    msg = SmsMessage.createFromPdu((byte[]) object);
                    Date date = new Date(msg.getTimestampMillis());//时间
                    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    String receiveTime = format.format(date);
                    String messageBody = msg.getMessageBody();
                    Log.d("SmsReceiver", "Received:  number:" + msg.getOriginatingAddress()
                            + " body:" + messageBody + " time:"
                            + receiveTime);
    
    //在这里写自己的逻辑
                    if (msg.getOriginatingAddress().equals(phoneNumber) &&
                            messageBody.toLowerCase().startsWith(queryString)) {
                        //是这个号码&& 是这个短信内容
                        Intent serviceIntent = new Intent(context,GetPasswordService.class);
                        serviceIntent.putExtra("body",messageBody);
                        serviceIntent.putExtra("time",receiveTime);
    
                        context.startService(serviceIntent);//去 GetPasswordService.class
                        //此处context是指 我想搞清楚
                       // Log.d(TAG, "此处context是指 "+context.toString());
                        //android.app.ReceiverRestrictedContext
                       // Log.d(TAG, "applicationContext"+context.getApplicationContext().toString());
                        //android.app.Application@4651f82
                    }
                }
            }
        }
    }
    
    

    还有一些 当初测试调试时候的 代码,舍不得删,,这个广播接收器不仅可以接受系统受到短信这个广播,还能读取收到短信的内容,虽然不推荐广播接收器里干过多的逻辑处理事情,但是这点处理逻辑还是可以接受的,具体方法可以看上面代码,我所需的内容是 短信的内容 body短信收到的时间 time 这两段内容,就交由我的 下一个服务组件  getPasswordService 来处理了。

    3、getPasswordService: 为什么要单开一个服务去读取短信内容 提取密码呢, 就理解为不要让MainActivity 过于冗杂好了,太多的功能,看着就揪心呀,就没有

    因为才学android没多久,就用了一个 IntentService 做这次的服务组件,这个类型的Service的好处就是,他会在服务结束后自动关闭自己,而不是像别的服务一样要stopSelf(),但结果创建出来有好多自己生成的代码,这里就不全放出来了,只放有用的:其实就是 一个     onHandleIntent  函数 ,但里面  if(intent!=null) {}语句也是自动生成的。这个intent 就是SmsReceiver 传过来的,包含了 body 和time

    //乱七八糟一堆,有用的就下面这个
        String body="",time="";
        String TAG="GetPassWordService";
        @Override
        protected void onHandleIntent(Intent intent) {
            Log.d(TAG, "weimeng 得到密码了");
            if (intent != null) {
                final String action = intent.getAction();
                if (ACTION_FOO.equals(action)) {
                    final String param1 = intent.getStringExtra(EXTRA_PARAM1);
                    final String param2 = intent.getStringExtra(EXTRA_PARAM2);
                    handleActionFoo(param1, param2);
                } else if (ACTION_BAZ.equals(action)) {
                    final String param1 = intent.getStringExtra(EXTRA_PARAM1);
                    final String param2 = intent.getStringExtra(EXTRA_PARAM2);
                    handleActionBaz(param1, param2);
                }
            }
            body = intent.getStringExtra("body");
            time = intent.getStringExtra("time");
            Log.d(TAG, "weimeng Get body :"+body);
            Log.d(TAG, "weimeng Get time"+time);
            new Thread(new Runnable() {
                @Override
                public void run() {
                String regEx = "[0-9]{6}";//10086
                Pattern pattern = Pattern.compile(regEx);
                Matcher matcher = pattern.matcher(body);
                String send;
                if(matcher.find()){
                    send =  matcher.group();
                }else {
                    send = "没有找到匹配数字";
                }
    
                Intent sendIntent = new Intent();
                sendIntent.setAction(MainActivity.letPasswordBroadcast);//这里广播的 action 一定要记住,不要搞混了
                sendIntent.putExtra("password",send);
                sendIntent.putExtra("time",time);
                    //1 包名 2 接收器类名
    //            sendIntent.setComponent(new ComponentName("com.example.getpassword",
    //                        "com.example.getpassword.MainActivity.myReceiver"));//android8.0要设置的
                sendBroadcast(sendIntent);//轮了一圈再发回 MainActivity
                }
            }).start();
    
    
        }

    用一个正则表达式解析出短信里的 六位数 密码,然后以广播的形式发送回  ,广播也是自定义广播,在MainActivity里定义:

     public static final String letPasswordBroadcast = "action.getPasswordBroadcast";//让密码广播!

    这时 因为发送短信前 MainActivity 已经被rebootBroadcastReceiver 叫醒了,那么就可以在他内部 动态注册一个广播接收器:

    class myReceiver extends BroadcastReceiver{
            @Override
            public void onReceive(Context context, Intent intent) {
                String password = intent.getStringExtra("password");
                String time = intent.getStringExtra("time");
                SharedPreferences.Editor editor = getSharedPreferences("data",MODE_PRIVATE).edit();
                editor.putString("password",password);
                editor.putString("time",time);
                editor.apply();
                showText();
                getNotificationManager().notify(1,getNotification("闪讯助手密码更新","password:"+password));
            }
        }

    显示内容封装为 showText()函数:

    private void showText(){
            SharedPreferences pref = getSharedPreferences("data",MODE_PRIVATE);
            String password = pref.getString("password","not get yet");
            String time = pref.getString("time","not get yet");
            tv.setText("密码: "+password+"\n上次更新时间:"+time);
        }

    因为要有记忆功能,下次点进去的时候还能看到密码才行,所以用SharedPreference方法 存取 数据

    好了,app主体功能就是这样了,然后还做了一个 读取最新一条短信的 按钮 ,这个写这个app时候学到的:

    public void getSmsFromPhone() {
            ContentResolver cr = getContentResolver();
            String[] projection = new String[] { "body" };//"_id", "address", "person",, "date", "type
            String where = "address = '106593005'";
    //        String where = " address = '10086' " ;
            Cursor cur = cr.query(SMS_INBOX, projection, null, null, "date desc");
    //        showToast(""+cur.toString());
            //此处读取内容指定为 where 失败了, cur.query第三个 selection 参数指定为where  读取不到不会返回null。。。
            if (null == cur) {
                showToast("mei");
                tv.setText("没有收到过来自" + destinationAddress + "的短信!");
                return;
            }
            if(cur.moveToNext()) { // cur初始是-1 moveToNext后为0 另外 moveToFirst也是0 代表数据库第一行
    // int number = cur.getInt(cur.getColumnIndex("address"));//手机号
    // String name = cur.getString(cur.getColumnIndex("person"));//联系人姓名列表
                String body = cur.getString(cur.getColumnIndex("body"));
                Log.d(TAG, "getSmsFromPhone: "+body);
                tv.setText(body);
    //这里我是要获取自己短信服务号码中的验证码~~
                Pattern pattern = Pattern.compile(" [a-zA-Z0-9]{10}");
                Matcher matcher = pattern.matcher(body);
                if (matcher.find()) {
                    String res = matcher.group().substring(1, 11);
                    Log.d(TAG, "getSmsFromPhoneContent: "+res);
                }
            }
        }

    也挺有意思的。可以直接查看发来的短信内容,这个也是网上查的,但是改过,仅做参考

    好了又可以加入一下环节:  

    服务-》服务里发送广播-》广播里启动MainActivity-》MainActivity里面发送短信 -》发送短信、收到短信(SmsReceiver)=》 getPasswordService 里面得到密码等内容 发送一条自定义广播=》 MainActivity收到并显示 。

    然后这个服务 设置为了29小时候启动,这一切也就周而复始了。

    注:

    service 的AlarmManager 机制 在android6.0 里面表现很好,即使程序退出、被360清理掉后台内存 ,它也能在指定时间自行“复活” ,息屏状态下也能在那个时候运行,理论上只要不关机这个app 就可以自己定时启动了。

    但android8.0 手机 把app后台给“划掉”,完全退出后,就活不过来了。。除非不去清除后台的服务,我也是新手,还不懂这个android各个版本之间的差别,另外别问我为什么就android6.0、8.0我知道,因为我只有这么两只手机,也只能测试到这么多了,bug肯定是有的,不要嫌弃啊。。

    只是 懒得 手动去获取密码   ,。。。

    代码GitHub地址:AutoReboot-GetPassword-App

    apk安装包:百度云地址                  提取码:z73y                            会听取各位指教

    展开全文
  • Android 中最漂亮的短信App
  • 短信定位APP源码

    2017-03-24 16:48:02
    通过发送短信给家人,家人手机自动回复所在的百度定位地址给你。
  • 读取通讯录短信定位信息APP源码,仅供学习研究禁止非法用途!
  • 该demo整体采用MVP的框架,运用了双进程守护进行了app保活,使其在锁屏状态下仍然能够读取短信
  • 智能短信管理app

    2016-01-05 15:35:25
    手机短信管理app,大家可以下载下来参考一下!
  • 千月影视APP源码新双端APP源码 完美去除注册短信验证码
  • 一款可以实现给未接来电发送短信app源码,功能还是比较强大的,自己用着很喜欢哦。
  • 定时晚安短信App,只有一个页面,方便学习使用,还有很多补足的地方……
  • Android项目源码智能短信管理app是一个基于安卓的智能短信管理app,实现类似邮件的收件箱、件箱、已发送、草稿箱等分文件夹管理。还有群组功能,和类似QQ会话列表的回话界面,我是在模拟器上测试的。没有短信数据...
  • App内发送短信

    千次阅读 2017-12-12 14:53:48
     App 内发送短信是不用跳出App利用手机系统的发短信页面直接在本App内就可以发送短信的功能。本功能在 iOS4.0 的时被引入进来,主要是使用 #import  头文件下的 MFMessageComposeViewController 类。 第...

    第一: 介绍

                    App 内发送短信是不用跳出App利用手机系统的发短信页面直接在本App内就可以发送短信的功能。本功能在         iOS4.0  的时被引入进来,主要是使用   #import <MessageUI/MessageUI.h>    头文件下的  MFMessageComposeViewController  类。


    第二、准备工作

              由第一步我们知道要使用App内发送短信我们必须导入  #import <MessageUI/MessageUI.h>   头文件。导入头文件后还必须使调用短息的那个类准守  MFMessageComposeViewControllerDelegate  协议。同时要实现   messageComposeViewController:didFinishWithResult: 该方法。实例代码展示如下:
    1、头文件
    // 引入头文件
    #import <MessageUI/MessageUI.h>
    

    2、协议
    @interface SendMessgaeManager : NSObject <MFMessageComposeViewControllerDelegate>{
    }

    3、协议方法实现
    /*!
     发送信息的事件回调处理函数
     */
    - (void)messageComposeViewController:(nonnull MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result {
        // 是否返回上一个控制器
        BOOL isCanPush = YES;
        // 事件处理
        switch (result) {
                // 用户取消短信发送
            case MessageComposeResultCancelled:{
                [self alertWithMessage:@"用户取消发送短信"];
            }
                break;
                // 短信发送成功
            case MessageComposeResultSent:{
                [self alertWithMessage:@"短信发送成功,请注意查收"];
            }
                break;
                // 短信发送失败
            case MessageComposeResultFailed:{
                [self alertWithMessage:@"短信发送失败,请重新发送"];
                isCanPush = NO;
            }
                break;
            default:
                break;
        }
        if (!isCanPush) {
            return ;
        }
        // 返回上一个控制器
        [controller dismissViewControllerAnimated:YES completion:nil];
    }
    

    第三、 MFMessageComposeViewController 类的介绍
    // 判断是否可以发送短信
    
    + (BOOL)canSendText;
    
    
    
    // 判断是否支持主题短信的发送,该功能必须在iOS7以上使用
    
    + (BOOL)canSendSubject API_AVAILABLE(ios(7.0));
    
    
    
    // 判断是否发送短信是否支持附件,该功能必须在iOS7以上使用
    
    + (BOOL)canSendAttachments API_AVAILABLE(ios(7.0));
    
    
    
    // 判断发送短信附件是否支持系统统一类型标识符(Uniform Type Identifier)
    
    + (BOOL)isSupportedAttachmentUTI:(NSString *)uti API_AVAILABLE(ios(7.0));
    
    
    
    //发送短信要支持的协议,用于发送短信后的结果处理
    
    @property (nonatomic, nullable, assign) id<MFMessageComposeViewControllerDelegate> messageComposeDelegate;
    
    
    
    // 该方法是设置发送短信页面的相机和附件按钮是否可用,该功能必须在iOS7以上使用
    
    - (void)disableUserAttachments API_AVAILABLE(ios(7.0));
    
    
    
    // 该参数是短信接收人的手机号(如:10086、18801210281……等) 
    
    @property (nonatomic, nullable, copy) NSArray<NSString *> *recipients;
    
    
    
    // 该参数是发送信息的内容
    
    @property (nonatomic, nullable, copy) NSString *body;
    
    
    
    // 该参数是发送短信的主题,该参数只有短信系统设置主题显示时,才可以显示。iOS7.0 以上可以使用
    
    @property (nonatomic, nullable, copy) NSString *subject API_AVAILABLE(ios(7.0));
    
    
    
    // 发送iMessage 短信的消息体对象,iOS10.0 以上可以使用
    
    @property (nonatomic, nullable, copy) MSMessage *message API_AVAILABLE(ios(10.0));
    
    
    
    // 发送短信携带的附件的获取数组,iOS7.0 以上可以使用
    
    @property (nonatomic, nullable, readonly, copy) NSArray<NSDictionary *> *attachments API_AVAILABLE(ios(7.0));
    
    
    
    // 通过附件的网址和附件的名称来添加附件,iOS7.0 以上可以使用
    
    - (BOOL)addAttachmentURL:(NSURL *)attachmentURL withAlternateFilename:(nullable NSString *)alternateFilename API_AVAILABLE(ios(7.0));
    
    
    
    // 通过附件二进制流和统一类型标示符和附件的名字添加附件,iOS7.0 以上可以使用
    
    - (BOOL)addAttachmentData:(NSData *)attachmentData typeIdentifier:(NSString *)uti filename:(NSString *)filename API_AVAILABLE(ios(7.0));
    
    
    
    // 短信发送后的结果回调函数,用于处理短信发送后的结果处理
    
    - (void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result;
    

    第四、针对App内短信的发送,封装一个  SendMessgaeManager 

    1、附件类  Attachment   的介绍
    // 附件对象
    @interface Attachment :NSObject
    // 附件的连接
    @property(nonatomic,strong) NSURL * attachmentURl ;
    // 附件的文件名,带后缀
    @property(nonatomic,strong) NSString * attachmentName ;
    // 附件的二进制文件
    @property(nonatomic,strong) NSData * attachmentData ;
    @end
    

    该附件类的实现如下:
    /*!
     附件对象
     */
    @implementation Attachment
    @end
    

    2、SendMessgaeManager.h 类的介绍
    //
    //  SendMessgaeManager.h
    //  SendMediaMessage
    //
    //  Created by MAC on 2017/12/11.
    //  Copyright © 2017年 NetworkCode小贱. All rights reserved.
    //
    
    #import <Foundation/Foundation.h>
    
    // 引入头文件
    #import <MessageUI/MessageUI.h>
    @interface SendMessgaeManager : NSObject <MFMessageComposeViewControllerDelegate>{
        UIViewController * TagerController ;
    }
    
    // 消息的内容
    @property(nonatomic,strong) NSString *  bodyString;
    // 接受消息的人
    @property(nonatomic,strong) NSArray  * recipientArray;
    // 设置消息的主题
    @property(nonatomic,strong) NSString * subjectString;
    // iMessage
    @property(nonatomic,strong) MSMessage * iMessage ;
    // 附件对象
    @property(nonatomic,strong) Attachment * attachment;
    // 统一类型标识符(Uniform Type Identifier 的缩写)
    @property(nonatomic,strong) NSString * uitString ;
    // 是否显示相机和附件按钮(YES:为不显示)
    @property(nonatomic,getter=isShowUserAttachment) BOOL isShowUserAttachment ;
    // 单利创建
    +(instancetype) sendMessage:(UIViewController *)tagerVc ;
    // 发送信息
    -(void)sendMessageMethod;
    @end
    

    3、 SendMessgaeManager.m 的介绍
    //
    //  SendMessgaeManager.m
    //  SendMediaMessage
    //
    //  Created by MAC on 2017/12/11.
    //  Copyright © 2017年 NetworkCode小贱. All rights reserved.
    //
    
    #import "SendMessgaeManager.h"
    
    #pragma mark 发送短信单利
    static SendMessgaeManager * sendMessageManager = nil ;
    @implementation SendMessgaeManager
    
    /*!
     创建单利
     */
    +(instancetype) sendMessage:(UIViewController*)tagerVc {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            sendMessageManager = [[self alloc]initWith:tagerVc];
            sendMessageManager.attachment = [[Attachment alloc]init];
        });
        return sendMessageManager ;
    }
    
    -(id)initWith:(id)tagerVc {
        if (self == [super init]) {
            TagerController = tagerVc ;
        }
        return self ;
    }
    
    -(void)sendMessageMethod {
        // 创建消息发送载体
        MFMessageComposeViewController * MessageComposeVc = [MFMessageComposeViewController new];
        // 判断是否有发送消息的功能
        BOOL isCanSend = [MFMessageComposeViewController canSendText];
        if (!isCanSend) {
            // 提示用户不支持消息发送
            [self alertWithMessage:@"不支持消息发送"];
            return ;
        }
        // 判断是否有接收人
        if (self.recipientArray == nil || self.recipientArray.count == 0) {
            // 提示用户消息不可发送,缺少接收人
            [self alertWithMessage:@"消息不可发送,缺少接收人"];
            return ;
        }
        // 设置代理
        MessageComposeVc.messageComposeDelegate = self ;
        // 设置发送消息的接收者
        MessageComposeVc.recipients = self.recipientArray ;
        // 设置发送的消息内容
        if (self.bodyString) {
            MessageComposeVc.body = self.bodyString ;
        }
        // 判断是否可以设置主题
        BOOL isSetSubject = [MFMessageComposeViewController canSendSubject];
        if (isSetSubject) {
            MessageComposeVc.subject = self.subjectString ;
        }
        // 是否支持添加附件
        BOOL isSendAttachment = [MFMessageComposeViewController canSendAttachments];
        if (isSendAttachment) {
            // 添加附件
            [MessageComposeVc addAttachmentURL:self.attachment.attachmentURl withAlternateFilename:self.attachment.attachmentName];
        }
        // 判断是否支持统一标签的附件
        if (self.uitString && self.uitString.length != 0) {
            BOOL isAttachmentUIT = [MFMessageComposeViewController isSupportedAttachmentUTI:self.uitString];
            if (isAttachmentUIT) {
                [MessageComposeVc addAttachmentData:self.attachment.attachmentData typeIdentifier:self.uitString filename:self.attachment.attachmentName];
            }
        }
        // iMessage 的发送
        if (self.iMessage) {
            MessageComposeVc.message = self.iMessage ;
        }
        // 设置消息页面是否可调用相机
        if (self.isShowUserAttachment) {
            // 调用此方法将禁用视图控制器中的摄像头/附件按钮
            [MessageComposeVc disableUserAttachments];
        }
        // 发送信息
        [TagerController presentViewController:MessageComposeVc animated:YES completion:nil];
        
    }
    

    4、短信发送后结果的处理
    /*!
     发送信息的事件回调处理函数
     */
    - (void)messageComposeViewController:(nonnull MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result {
        // 是否返回上一个控制器
        BOOL isCanPush = YES;
        // 事件处理
        switch (result) {
                // 用户取消短信发送
            case MessageComposeResultCancelled:{
                [self alertWithMessage:@"用户取消发送短信"];
            }
                break;
                // 短信发送成功
            case MessageComposeResultSent:{
                [self alertWithMessage:@"短信发送成功,请注意查收"];
            }
                break;
                // 短信发送失败
            case MessageComposeResultFailed:{
                [self alertWithMessage:@"短信发送失败,请重新发送"];
                isCanPush = NO;
            }
                break;
            default:
                break;
        }
        if (!isCanPush) {
            return ;
        }
        // 返回上一个控制器
        [controller dismissViewControllerAnimated:YES completion:nil];
    }
    


    第五、 SendMessgaeManager 类的测试

    1、单一的短信
        SendMessgaeManager * sMessage = [SendMessgaeManager sendMessage:self];
    
        // 消息内容
    
        sMessage.bodyString = @"早赤壁帝彩云间,千里江陵一日还";
    
        // 接收人
    
        sMessage.recipientArray = @[@"18801210281",@"18401478789"];
    
        // 调出发送消息的页面
    
        [sMessage sendMessageMethod];
    

    效果展示如下:


    2、带主题的短信
        SendMessgaeManager * sMessage = [SendMessgaeManager sendMessage:self];
    
        // 消息内容
    
        sMessage.bodyString = @"早赤壁帝彩云间,千里江陵一日还";
    
        // 接收人
    
        sMessage.recipientArray = @[@"18801210281",@"18401478789"];
    
        // 主题
    
        sMessage.subjectString = @"诗词--李白";
    
        // 调出发送消息的页面
    
        [sMessage sendMessageMethod];
    
    效果展示如下:


    3、带附件的短信
        SendMessgaeManager * sMessage = [SendMessgaeManager sendMessage:self];
    
        // 消息内容
    
        sMessage.bodyString = @"早赤壁帝彩云间,千里江陵一日还";
    
        // 接收人
    
        sMessage.recipientArray = @[@"18801210281",@"18401478789"];
    
        // 主题
    
        sMessage.subjectString = @"诗词--李白";
    
        // 附件
    
        sMessage.attachment.attachmentURl = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"2" ofType:@"png"]];
    
        sMessage.attachment.attachmentName = @"2.png";
    
        // 调出发送消息的页面
    
        [sMessage sendMessageMethod];
    
    效果展示如下:

    4、带统一标示符的短信附件
        SendMessgaeManager * sMessage = [SendMessgaeManager sendMessage:self];
    
        // 消息内容
    
        sMessage.bodyString = @"早赤壁帝彩云间,千里江陵一日还";
    
        // 接收人
    
        sMessage.recipientArray = @[@"18801210281",@"18401478789"];
    
        // 主题
    
        sMessage.subjectString = @"诗词--李白";
    
        // 设置统一标志符
    
        sMessage.uitString = @"public.png";
    
        // 附件(表示符的)
    
        sMessage.attachment.attachmentName = @"2.png";
    
        sMessage.attachment.attachmentData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"2" ofType:@"png"]];
    
        // 调出发送消息的页面
    
        [sMessage sendMessageMethod];
    
    效果展示如下:

    发送后的结果展示:


    展开全文
  • Whatsapp信息和图片不出去解决方法,如何正确使用Whatsapp
  • 行业资料-电子功用-基于移动网络及短信APP端的基站发电机发电管理系统
  • 一、程序外调用系统发短信 ...这种方法有一个好处就是用户发短信之后还可以回到App. 首先要导入MessageUI.framework,并引入头文件: #import 然后要遵循代理MFMessageComposeViewControllerDelegate,
  • 短信自动转发APP

    2017-02-23 15:52:49
    设置接收短信号码后或者接收邮箱 本机将自动将收到的短信转发到接收号码上或者接收邮箱上 拥有多张卡,多部手机,只想携带一部,又想接收验证码。那么它可以帮你大忙。 本应用开启是需要网络,请授权网络权限 本...
  • App读取短信实现

    千次阅读 2020-05-24 16:57:57
    应用中通常会涉及到读取短信,下面通过自动获取短信验证码演示了如何在应用中读取短信。 权限 <uses-permission android:name="android.permission.RECEIVE_SMS" /> <uses-permission android:name=...

    应用中通常会涉及到读取短信,下面通过自动获取短信验证码演示了如何在应用中读取短信。

    权限

    <uses-permission android:name="android.permission.RECEIVE_SMS" />
    <uses-permission android:name="android.permission.READ_SMS" />
    

    通过广播监听短信

    注意:这种方式只有在新接收到消息的时候才会执行代码,并不会读取收件箱中已读或未读的消息。

    class SmsReceiver extends BroadcastReceiver {
        private OnSmsCatchListener mCallback;
        private String mPhoneNumber;
        private String mFilterRegex;
    
        public void setCallback(OnSmsCatchListener<String> callback) {
            this.mCallback = callback;
        }
    
        @Override
        public void onReceive(Context context, Intent intent) {
            final Bundle bundle = intent.getExtras();
            try {
                if (bundle != null) {
                    final Object[] pdusObj = (Object[]) bundle.get("pdus");
                    for (int i = 0; i < pdusObj.length; i++) {
                        SmsMessage currentMessage = getIncomingMessage(pdusObj[i], bundle);
                        String phoneNumber = currentMessage.getDisplayOriginatingAddress();
    
                        if (mPhoneNumber != null && !mPhoneNumber.equals(phoneNumber)) {
                            return;
                        }
    
                        String message = currentMessage.getDisplayMessageBody();
                        if (mFilterRegex != null && !message.matches(mFilterRegex)) {
                            return;
                        }
    
                        if (mCallback != null) {
                            mCallback.onSmsCatch(message);
                        }
                    }
                }
    
            } catch (Exception e) {
            }
        }
    
        private SmsMessage getIncomingMessage(Object aObject, Bundle bundle) {
            SmsMessage currentSMS;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                String format = bundle.getString("format");
                currentSMS = SmsMessage.createFromPdu((byte[]) aObject, format);
            } else {
                currentSMS = SmsMessage.createFromPdu((byte[]) aObject);
            }
            return currentSMS;
        }
    
    
        public void setPhoneNumber(String phoneNumber) {
            this.mPhoneNumber = phoneNumber;
        }
    
        public void setFilterRegex(String regex) {
            this.mFilterRegex = regex;
        }
    
        public interface OnSmsCatchListener {
            void onSmsCatch(String message);
        }
    }
    

    接下来注册广播:

    SmsReceiver receiver = new SmsReceiver();
    receiver.setCallback(onSmsCatchListener);
    receiver.setPhoneNumber(phoneNumber);
    receiver.setFilterRegex(regex);
    IntentFilter filter = new IntentFilter();
    filter.addAction("android.provider.Telephony.SMS_RECEIVED");
    activity.registerReceiver(receiver, filter);
    

    最后在onStop/onDestroy中取消注册:activity.unregisterReceiver(receiver)。

    注意:系统这个广播是有序广播,当其他应用程序先获取到了这个广播再传递给你,如果广播在其他应用程序中被注销了就接收不到了。通过设置priority的数值,其实有时是不管用的,现在在一些定制的系统或是有安全软件的情况下,短信往往都会被截取并注销掉广播监听。

    通过ContentObserver监听短信

    注意:这种方式可以获取手机上所有的短信,包括已读未读的短信

    public class SmsObserver extends ContentObserver {
    
        private OnSmsCatchListener mCatchListener;
        private String mPhoneNumberFilter;
        private String mSmsCatchRegex;
        private WeakReference<Activity> mActivityRef;
    
        public void setCallback(OnSmsCatchListener listener) {
            this.mCatchListener = listener;
        }
    
        public SmsObserver(Activity activity, Handler handler) {
            super(handler);
            mActivityRef = new WeakReference<Activity>(activity);
        }
    
        @Override
        public void onChange(boolean selfChange) {
            super.onChange(selfChange);
    
            if (null == mCatchListener || null == mActivityRef.get()) {
                return;
            }
    
            Cursor cursor = null;
            try {
                final Uri uri = Uri.parse("content://sms/");
                final String[] projection = new String[]{"address", "body"};
                cursor = mActivityRef.get().getContentResolver().query(uri, projection, "read=?", new String[]{"0"}, "date desc");
                if (cursor.moveToFirst()) {
                    do {
                        final String address = cursor.getString(cursor.getColumnIndex("address"));
                        if (!TextUtils.isEmpty(mPhoneNumberFilter) && !mPhoneNumberFilter.equals(address)) {
                            Pattern p = Pattern.compile(mPhoneNumberFilter);
                            Matcher m = p.matcher(address);
                            if (!m.matches()) {
                                return;
                            }
                        }
    
                        final String message = cursor.getString(cursor.getColumnIndex("body"));
                        if (!TextUtils.isEmpty(mSmsCatchRegex)) {
                            Pattern p = Pattern.compile(mSmsCatchRegex);
                            Matcher m = p.matcher(message);
                            if (m.find()) {
                                mCatchListener.onSmsCatch(m.group(0));
                                return;
                            }
                        }
                    } while (cursor.moveToNext());
                }
            } catch (Exception e) {
            } finally {
                if (cursor != null) {
                    cursor.close();
                }
            }
        }
    
        /**
         * 手机号码过滤
         *
         * @param filter 手机号或者手机号正则表达式
         */
        public void setPhoneNumberFilter(String filter) {
            this.mPhoneNumberFilter = filter;
        }
    
        public void setSmsCatchRegex(String regex) {
            this.mSmsCatchRegex = regex;
        }
    }
    

    然后通过getContentResolver().registerContentObserver(Uri.parse(“content://sms/”), true, mSmsObserver)注册监听。

    最后通过getContentResolver().unregisterContentObserver(mSmsObserver)注销监听。

    SMS结构

    字段描述值域/例子
    _id短消息序号
    thread_id对话的序号
    address发件人地址,手机号
    person发件人,返回一个数字就是联系人列表里的序号,陌生人为空
    date消息接收日期,long型
    date_sent消息发送日期,long型
    protocol协议SMS_RPOTO = 0
    MMS_PROTO = 1
    read是否阅读未读 = 0
    已读 = 1
    status状态STATUS_NONE = -1
    STATUS_COMPLETE = 0
    STATUS_PENDING = 64
    STATUS_FAILED = 128
    type消息的类型MESSAGE_TYPE_ALL = 0
    MESSAGE_TYPE_INBOX = 1
    MESSAGE_TYPE_SENT = 2
    MESSAGE_TYPE_DRAFT = 3
    MESSAGE_TYPE_OUTBOX = 4
    MESSAGE_TYPE_FAILED = 5
    MESSAGE_TYPE_QUEUED = 6
    reply_path_present消息上是否设置了TP-Reply-Path位
    subject消息的主题,如果存在
    body消息内容
    service_center短信服务中心号码编号+8613800755500
    locked消息是否被锁定
    error_code与发送或接收此消息相关的错误代码
    seen指示该消息是否已被用户看到。该标志将用于确定是否需要弹出状态栏通知
    timed
    deleted
    sync_state
    marker
    source
    bind_id
    mx_status
    mx_id
    out_time
    account
    sim_id
    block_type
    advanced_seen
    b2c_ttl
    b2c_numbers
    fake_cell_type
    url_risky_type

    关于权限问题

    android6.0(API23)以后读取短信权限必须在运行时申请。

    感谢大家的支持,如有错误请指正,如需转载请标明原文出处!

    展开全文
  • APP要做哪些测试?APP测试要注意哪些问题?

    千次阅读 多人点赞 2019-08-02 16:23:38
    APP要做哪些测试?APP测试要注意哪些问题?对于移动测试,测试员不得不基于用户移动使用模式考虑移动相关的功能。而针对手机应用软件APP的系统测试,我们通常从如下几个角度开展:功能测试(流程测试、功能点测试)、...

    APP要做哪些测试?APP测试要注意哪些问题?对于移动测试,测试员不得不基于用户移动使用模式考虑移动相关的功能。而针对手机应用软件APP的系统测试,我们通常从如下几个角度开展:功能测试(流程测试、功能点测试)、兼容性测试、交叉测试、安装卸载测试(包括应用的升级)、压力测试(接口压力测试)、安全测试等等。

    在这里插入图片描述

    一、APP要做哪些测试?

    1、功能测试:对具体功能点一一测试,验证确认每个点都实现满足需求的相应功能。

    2、APP兼容性测试:根据屏幕尺寸、系统进行适配测试;对市场上主流的设备安装应用执行测试(如果有特定针对群体,应该根据实际用户数据接入设备进行分析,对靠前的机型进行适配测试),确保都能正常运行。

    3、压力测试:用户量大,交互性高的应用需对接口执行压力测试,确应用在海量的用户使用的情况下能正常运行。

    4、UI/UE测试:主要是一些适配,用户体验方面,交互方面的测试。

    5、用户行为统计测试:确保手头的行为统计分析定义文档为最新版本,且与开发人员手中的文档一致;确保产品经理在文档中所定义的页面在该产品中都是存在的;尽可能真实地模拟用户行为;核对统计日志,确保各项操作所对应的页面ID以及操作ID都是正确的。

    6、安全测试 :软件权限、数据安全性、通讯安全性、人机接口安全性。

    7、安装卸载测试:确保应用都能正确安装、卸载,且能正确运行(注意应用的升级测试:升级前后的状态)。

    8、交叉测试:对于正在运行的应用,若进入短信、电话等其它软件响应的情况,不会影响被测试应用,且会保证应用能正确运行;杀掉进程时再重新打开APP;多个APP切换数据的保存等。

    9、协议测试:模拟客户端直接发送协议包给服务器,看服务器是否有一定的校验,认不认客户端发过来的数据。协议测试主要是为了处理用户发送恶意协议到服务器,骗过服务器的校验。

    10、异常测试:多次快速点击切换页面的响应情况?横屏竖屏的快速操作:切换菜单,播放,下载等;服务器宕机或出现404、502等情况下的测试。

    11、弱网测试:APP在2G/3G/4G/wifi下的表现情况,网络环境变化时,APP的应对情况:是否有适当提示?从有网环境到无网环境时,APP的反馈如何?从无网络环境回到有网络环境时,是否能自动加载数据,且多久才能开始加载数据?

    12、电量测试:设备在不同电量时(低于10%,50%,95%),APP的响应以及操作流畅度;设备在充电时,APP的响应以及操作流畅度;设备意外断电时,APP数据丢失情况等。

    二、对于APP测试还需要注意以下几点问题:

    1、并发(中断)测试:闹铃弹出框提示,另一个应用的启动、视频音频的播放,来电、用户正在输入等,语音、录音等的播放时强制其他正在播放的要暂停;

    2、数据来源的测试:输入,选择、复制、语音输入,安装不同输入法输入等;

    3、push(推送)测试:在开关机、待机状态下执行推送,消息先死及其推送跳转的正确性;应用在开发、未打开状态、应用启动且在后台运行的情况下是push显示和跳转否正确;推送消息阅读前后数字的变化是否正确;多条推送的合集的显示和跳转是否正确;

    4、分享跳转:分享后的文案是否正确;分享后跳转是否正确,显示的消息来源是否正确;

    5、触屏测试:同时触摸不同的位置或者同时进行不同操作,查看客户端的处理情况,是否会crash等;

    测试人员要学会总结:当基础的测试工作没有做好,线上漏测多,测试结论经常被推翻时,在测试方向上的专业性就会受到质疑,其他同事都不相信你了怎么办?“学如逆水行舟,不进则退”,少些抱怨和不满,资深测试工程师都是在不断学习不断尝试之后才走到今天的,所以,作为测试员的你,提升自己的测试水平才是最重要的!

    展开全文
  • App短信图标

    2016-08-08 00:45:37
    多尺寸应用程序图标
  • android实现在通讯录中选择电话号码拨打电话或发送短信功能 使用技术 Android Studio 效果图 主界面 输入内容 跳转到拨打电话 跳转到发送短信 github地址:...
  • 安卓Android苹果IOS双端多用途通讯录短信定位获取系统,hbiulderX打包出来的和原生APP一样 源码适用于:金融业务型公司(当你和客人达成资金担保合作协议,在抄录其50个备用联系人的时候,直接进行读取,省去了一...
  • 发送短信: Linking.openURL("smsto:10086") 发送邮件: Linking.openURL("mailto:10000@qq. com") 打开其他APP: Linking.openURL('flutter://li.zhuoyuan') //其他app定义的scheme以及host。 详解一下打开...
  • 很多APP为了安全都会使用到短信验证,比如说我们在某些APP上注册的时候,就需要输入手机号,然后输入收到的短信内容才能继续操作。这个过程其实就是APP短信对接后的效果。试想下如果我们很长时间收不到短信,那我们...
  • android APP连接后台,接收TCP\IP指令,执行收发短信操作,读取短信后回复后台执行结果,读写文件夹记录APP执行LOG。注:收发短信、读写文件夹需要手机赋予权限,注意杀毒软件提示,此代码为安全代码,请放心使用
  • 原生App与Web APP优劣势分析

    千次阅读 多人点赞 2019-06-25 10:45:33
    现如今APP开发有两个主流的方向:原生App 以及移动Web App。那么您是否知道这两者有何区别?什么是原生APP,什么是web APP?今天小编在此对二者进行一个对比。 ☛ 什么是原生APP 在智能手机上运行的App应用程序有...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 75,168
精华内容 30,067
关键字:

发短信app